Giao diện
Advanced Repository Management 🏗️
ROLE: HPN (Architecture & DevOps).
AUDIENCE: Engineers quản lý monorepos, shared libraries, và large assets.
Khi dự án của bạn lớn lên, bạn sẽ gặp các vấn đề mà git add && git commit không giải quyết được: shared libraries, multiple parallel workstreams, và large binary files. Module này trang bị cho bạn các công cụ nâng cao để xử lý chúng.
🎯 Mục tiêu
Sau module này, bạn sẽ:
- Quản lý Submodules - repos lồng nhau
- Dùng Worktrees - làm việc trên nhiều branches cùng lúc
- Setup Git LFS - xử lý large binaries hiệu quả
📦 Git Submodules - Repos Inside Repos
The Problem
"Team A đang maintain thư viện
ui-components. Team B, C, D đều muốn dùng. Copy-paste? Vendor folder? Fork?"
Solution: Git Submodules - embed một repo vào trong repo khác.
How It Works
Key insight: Main repo chỉ lưu pointer (commit SHA) đến submodule, không phải toàn bộ code.
Basic Commands
bash
# 1. Thêm submodule
git submodule add https://github.com/team/ui-components.git libs/ui-components
# 2. Clone repo có submodules
git clone --recurse-submodules https://github.com/company/main-project.git
# Hoặc nếu đã clone rồi:
git submodule update --init --recursive
# 3. Cập nhật submodule lên version mới
cd libs/ui-components
git checkout v2.0.0 # hoặc git pull origin main
cd ../..
git add libs/ui-components
git commit -m "chore: update ui-components to v2.0.0"
# 4. Xem status của submodules
git submodule status❌ The Pain: Detached HEAD
Vấn đề phổ biến nhất: Sau khi git submodule update, bạn ở trạng thái detached HEAD.
bash
$ cd libs/ui-components
$ git status
HEAD detached at abc123 # 😱 Không ở branch nào!Tại sao? Submodule checkout exact commit, không phải branch tip.
Cách fix:
bash
# 1. Checkout branch thay vì commit
cd libs/ui-components
git checkout main # or develop, etc.
# 2. Hoặc config để tự động track branch
git config -f .gitmodules submodule.libs/ui-components.branch main
git submodule update --remote --mergeSubmodule Workflows
Update All Submodules
bash
# Cập nhật tất cả submodules lên latest commit của tracked branch
git submodule update --remote --merge
# Recursive (nested submodules)
git submodule update --init --recursive --remoteRemove a Submodule
bash
# 1. Deinit
git submodule deinit -f libs/ui-components
# 2. Remove from .git/modules
rm -rf .git/modules/libs/ui-components
# 3. Remove from working tree
git rm -f libs/ui-components
# 4. Commit
git commit -m "chore: remove ui-components submodule"Foreach - Run Command in All Submodules
bash
# Pull all submodules
git submodule foreach 'git pull origin main'
# Check status of all
git submodule foreach 'git status'
# Recursive foreach
git submodule foreach --recursive 'git fetch --all'.gitmodules File
ini
[submodule "libs/ui-components"]
path = libs/ui-components
url = https://github.com/team/ui-components.git
branch = main
[submodule "libs/shared-utils"]
path = libs/shared-utils
url = git@github.com:team/shared-utils.gitCOMMON PITFALL
Sau khi git pull main repo, luôn chạy:
bash
git submodule update --init --recursiveNếu không, submodule của bạn sẽ ở version cũ!
🌳 Git Worktrees - Multiple Branches, One Repo
The Problem
"Đang code dở feature branch, có bug urgent cần fix trên main. Stash? Commit WIP? Cả hai đều messy."
Solution: Git Worktrees - checkout nhiều branches vào nhiều folders khác nhau, từ cùng một repo.
How It Works
Key insight: Tất cả worktrees share cùng .git/ directory → không duplicate objects.
Basic Commands
bash
# 1. Tạo worktree cho branch có sẵn
git worktree add ../app-hotfix hotfix/urgent-fix
# 2. Tạo worktree với branch mới
git worktree add -b feature/new-ui ../app-new-ui main
# 3. List all worktrees
git worktree list
# /home/user/projects/app abc123 [main]
# /home/user/projects/app-hotfix def456 [hotfix/urgent-fix]
# /home/user/projects/app-new-ui ghi789 [feature/new-ui]
# 4. Remove worktree khi xong
git worktree remove ../app-hotfix
# 5. Prune stale worktrees
git worktree pruneReal-World Workflow
bash
# Scenario: Đang code feature, có bug urgent
# 1. Bạn đang ở main worktree, working on feature
cd ~/projects/myapp
git switch feature/login-redesign
# ... đang code dở ...
# 2. Có bug urgent! Tạo worktree mới, không disturb work hiện tại
git worktree add ../myapp-hotfix hotfix/critical-bug
# 3. Switch sang folder mới, fix bug
cd ../myapp-hotfix
# fix bug...
git add . && git commit -m "fix: critical security issue"
git push origin hotfix/critical-bug
# Create PR, merge...
# 4. Quay lại feature work
cd ../myapp
# Code của feature vẫn y nguyên! Không cần stash/unstash
# 5. Cleanup
cd ~/projects/myapp
git worktree remove ../myapp-hotfixWorktree Use Cases
| Scenario | Worktree Solution |
|---|---|
| Fix urgent bug mid-feature | Tạo worktree cho hotfix branch |
| Test two versions side-by-side | Worktree cho main và develop |
| Review PR mà không làm gián đoạn work | Worktree checkout PR branch |
| Long-running experiment | Worktree cho experiment branch |
PRO TIP
Đặt worktrees ở cùng parent folder với main repo:
~/projects/
├── myapp/ (main worktree)
├── myapp-hotfix/ (hotfix worktree)
└── myapp-feature/ (feature worktree)🗃️ Git LFS - Large File Storage
The Problem
"Designer commit file PSD 500MB. Repo clone từ 100MB lên 2GB. Mọi người muốn giết designer."
Tại sao Git xử lý binary kém?
- Git lưu full snapshot, không delta compression cho binaries
- Mỗi version = thêm full file size
- Clone phải download toàn bộ history
The Solution: Git LFS
Git LFS lưu pointer trong repo, actual file trên LFS server riêng.
Setup Git LFS
bash
# 1. Install (một lần trên máy)
# macOS
brew install git-lfs
# Windows
winget install GitHub.GitLFS
# Ubuntu
sudo apt install git-lfs
# 2. Initialize trong user profile (một lần)
git lfs install
# 3. Track file types trong repo
cd your-repo
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "*.mp4"
git lfs track "assets/**"
# 4. Commit .gitattributes
git add .gitattributes
git commit -m "chore: configure Git LFS"How LFS Works
Pointer File
Thay vì actual binary, Git repo chứa pointer file:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 536870912Workflow
Essential Commands
bash
# Xem files đang được track
git lfs track
# Xem LFS files trong repo
git lfs ls-files
# Pull LFS files (nếu chưa có)
git lfs pull
# Clone với LFS files
git clone <url> # Tự động pull LFS nếu đã install
# Clone KHÔNG có LFS files (lightweight)
GIT_LFS_SKIP_SMUDGE=1 git clone <url>
# Migrate existing files to LFS
git lfs migrate import --include="*.psd" --everything
# Fetch specific LFS files
git lfs fetch --include="assets/logo.png".gitattributes Configuration
gitattributes
# Images
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
# Videos
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
# Archives
*.zip filter=lfs diff=lfs merge=lfs -text
*.tar.gz filter=lfs diff=lfs merge=lfs -text
# ML Models
*.bin filter=lfs diff=lfs merge=lfs -text
*.onnx filter=lfs diff=lfs merge=lfs -text
# Specific folders
assets/** filter=lfs diff=lfs merge=lfs -textLFS Considerations
| Aspect | Details |
|---|---|
| Storage | GitHub: 1GB free, 50GB với $5/mo data pack |
| Bandwidth | GitHub: 1GB/mo free, paid tiers available |
| CI/CD | Cần git lfs install + git lfs pull trong pipeline |
| Submodules | LFS works với submodules, cần config đúng |
LFS GOTCHA
Nếu forget để git lfs install trước khi commit large files:
bash
# Migrate những files đã commit nhầm
git lfs migrate import --include="*.psd" --include-ref=refs/heads/main
git push --force # ⚠️ Rewrites history!📊 Quick Reference
Submodules
| Command | Purpose |
|---|---|
git submodule add <url> <path> | Add submodule |
git submodule update --init --recursive | Initialize & update |
git submodule update --remote | Update to latest |
git submodule foreach '<cmd>' | Run command in all |
git submodule status | Check versions |
Worktrees
| Command | Purpose |
|---|---|
git worktree add <path> <branch> | Create worktree |
git worktree add -b <new> <path> <base> | Create with new branch |
git worktree list | List all worktrees |
git worktree remove <path> | Remove worktree |
git worktree prune | Cleanup stale |
LFS
| Command | Purpose |
|---|---|
git lfs install | Setup LFS |
git lfs track "<pattern>" | Track file pattern |
git lfs ls-files | List tracked files |
git lfs pull | Download LFS files |
git lfs migrate import | Migrate existing files |
💡 Key Takeaways
HPN'S INSIGHT
"Submodules cho shared code, Worktrees cho parallel work, LFS cho binaries. Đúng tool cho đúng problem."
- Submodules lưu pointers: Main repo chỉ track commit SHA, không phải code
- Always
--recursive:git submodule update --init --recursivelà bạn tốt - Worktrees share objects: Không duplicate data, instant checkout
- LFS là mandatory cho binaries: Files >10MB nên dùng LFS
- CI/CD needs setup: Submodules và LFS cần explicit commands trong pipelines
CHOOSE WISELY
| Problem | Wrong Tool | Right Tool |
|---|---|---|
| Shared library | Copy-paste | Submodule |
| Parallel branches | Stash | Worktree |
| Large binaries | Regular commit | LFS |
| Forked customization | Submodule | Subtree or fork |