Git Branches – Hiểu Cơ Chế Branch, Tag, HEAD, Detached HEAD và Stash Trong Git
Một trong những lý do khiến Git trở thành công cụ quản lý mã nguồn phổ biến nhất hiện nay chính là khả năng tạo branch cực kỳ nhanh và nhẹ. Điều này đặc biệt quan trọng trong DevOps, GitOps, CI/CD và phát triển phần mềm theo mô hình Agile, nơi các nhánh được tạo và hợp nhất (merge) liên tục.
Điều thú vị là một Git Branch không phải là bản sao của source code như nhiều người lầm tưởng.
Git Branch thực chất là gì?
Một Git Branch chỉ bao gồm:
Ví dụ:
A → B → C
↑
master
Branch master chỉ đơn giản là một con trỏ đang tham chiếu đến commit C.
Khi tạo commit mới:
A → B → C → D
↑
master
Git tự động cập nhật pointer của branch để luôn trỏ đến commit mới nhất.
Do branch chỉ là một pointer nên:
Đây là nền tảng giúp Git cực kỳ phù hợp với:
Branch mặc định: master/main
Khi khởi tạo repository:
git init
Git sẽ tạo branch đầu tiên.
Trước đây là:
master
Ngày nay đa số repository sử dụng:
main
Branch này được tạo ngay từ đầu để bạn có thể thực hiện:
git commit
và bắt đầu xây dựng chuỗi commit của dự án.
Tạo Branch mới
Khi muốn phát triển tính năng mới mà không ảnh hưởng đến branch chính:
git branch feature-login
Lệnh trên chỉ tạo thêm một pointer:
A → B → C
↑
master
↑
feature-login
Cả hai branch đều trỏ đến cùng commit.
Checkout Branch
Khi chuyển sang branch mới:
git checkout feature-login
hoặc:
git switch feature-login
HEAD sẽ bắt đầu theo dõi branch này:
HEAD
↓
feature-login
↓
A → B → C
Trạng thái này gọi là: Attached State
HEAD đang "gắn" với một branch.
Commit trên Branch
Nếu tạo commit mới:
A → B → C → D
↑
feature-login
↑
HEAD
master
↓
C
Chỉ branch hiện tại di chuyển.
Branch khác hoàn toàn không bị ảnh hưởng.
Đây là cơ chế giúp nhiều developer có thể làm việc song song trên cùng một repository.
Git Tag – Đánh dấu các cột mốc quan trọng
Git cung cấp một loại pointer đặc biệt gọi là: Tag
Tag thường được dùng để đánh dấu:
Ví dụ:
v1.0
↓
A → B → C
hoặc:
v2.0
↓
A → B → C → D → E
Tạo tag:
git tag v1.0
Tạo annotated tag:
git tag -a v1.0 -m "Release version 1.0"
Vì sao Tag quan trọng trong DevOps?
Ví dụ:
Pipeline:
Build hỏi về lệnh ip ospf network point-to-point
Build làm thế nào để phát hiện là mình đang gặp routing-loop?
Build Một số điều góp ý
Tester phát hiện lỗi:
Bug xuất hiện ở Build làm thế nào để phát hiện là mình đang gặp routing-loop?
Developer có thể:
git checkout build-202
để tái tạo chính xác môi trường khi lỗi xảy ra.
Đây là lý do các pipeline CI/CD hiện đại thường:
Git Commit
↓
Build
↓
Tag
↓
Release
Điểm khác nhau giữa Branch và Tag
Branch
Ví dụ:
master → D → E → F
Tag
Ví dụ:
v1.0 → C
Tag giống như một cột mốc lịch sử.
HEAD là gì?
HEAD là một pointer đặc biệt của Git.
HEAD cho biết:
Ví dụ:
HEAD
↓
master
↓
A → B → C
HEAD giúp Git xác định:
Attached HEAD
Trạng thái phổ biến nhất:
HEAD
↓
feature
↓
A → B → C
HEAD không trỏ trực tiếp vào commit.
Nó trỏ đến branch.
Branch trỏ đến commit.
Khi commit mới xuất hiện:
A → B → C → D
↑
feature
↑
HEAD
Cả HEAD và branch cùng di chuyển.
Detached HEAD là gì?
Đôi khi bạn muốn kiểm tra một commit cũ:
git checkout a1b2c3
Khi đó:
HEAD
↓
A → B → C
HEAD trỏ trực tiếp đến commit.
Không còn gắn với branch nào.
Đây gọi là: Detached HEAD State
Detached HEAD dùng để làm gì?
Rất hữu ích trong: Troubleshooting
git checkout v1.0 Reproduce Bug
git checkout build-202 Test Release
git checkout 9fceb Rollback Investigation
git checkout old-commit
CI/CD Pipeline cũng thường xuyên sử dụng Detached HEAD khi checkout theo commit hash hoặc tag.
Rủi ro của Detached HEAD
Nếu commit trong trạng thái này:
A → B → C
\
D
↑
HEAD
Commit D không thuộc branch nào.
Nếu checkout sang branch khác:
git checkout main
commit D có thể trở thành orphan commit và sau đó bị Git garbage collection xóa.
Cách thoát Detached HEAD
Tạo branch mới
git switch -c hotfix
hoặc:
git checkout -b hotfix
Khi đó:
A → B → C → D
↑
hotfix
↑
HEAD
Hoặc quay lại branch cũ
git checkout main
Git Stash – Cứu cánh khi đang làm dở
Tình huống rất quen thuộc:
Bạn đang viết:
my_network.py
thì production bị lỗi.
Bạn cần:
Nhưng Working Directory còn rất nhiều code chưa hoàn thành.
Git sẽ không cho phép chuyển branch khi:
Giải pháp: Git Stash
Stash là một snapshot tạm thời của:
Lưu công việc:
git stash push -m "Work in progress"
Ví dụ:
$ git status -s
M my_network.py
Lưu:
$ git stash push -m "Work in progress"
Saved working directory and index state On feature: Work in progress
Kiểm tra:
$ git status
On branch feature
nothing to commit, working tree clean
Working Directory đã sạch hoàn toàn.
Khôi phục Stash
git stash pop
Kết quả:
On branch feature
Changes not staged for commit:
modified: my_network.py
File quay trở lại đúng trạng thái trước đó.
Một số lệnh Stash hữu ích
Xem danh sách:
git stash list
Lưu:
git stash push -m "Terraform WIP"
Khôi phục:
git stash pop
Khôi phục nhưng giữ lại stash:
git stash apply
Xóa:
git stash drop
Xóa toàn bộ:
git stash clear
Tại sao DevOps Engineer dùng Stash rất nhiều?
Ví dụ:
Bạn đang viết:
Đột nhiên production có sự cố.
Thay vì:
Tạo branch tạm
Commit code chưa hoàn thiện
Push lên remote
bạn chỉ cần:
git stash push -m "K8s deployment WIP"
git checkout hotfix
Sau khi xử lý xong:
git checkout feature
git stash pop
Toàn bộ công việc tiếp tục đúng nơi đã dừng.
Tóm tắt
Các khái niệm cốt lõi của Git Branching:
Branch = Pointer di động đến commit mới nhất
Tag = Pointer cố định đến một commit
HEAD = Vị trí hiện tại trong repository
Attached HEAD = HEAD → Branch → Commit
Detached HEAD = HEAD → Commit
Stash = Snapshot tạm thời của công việc chưa hoàn thành
Hiểu rõ các khái niệm này là nền tảng để làm chủ:
Một trong những lý do khiến Git trở thành công cụ quản lý mã nguồn phổ biến nhất hiện nay chính là khả năng tạo branch cực kỳ nhanh và nhẹ. Điều này đặc biệt quan trọng trong DevOps, GitOps, CI/CD và phát triển phần mềm theo mô hình Agile, nơi các nhánh được tạo và hợp nhất (merge) liên tục.
Điều thú vị là một Git Branch không phải là bản sao của source code như nhiều người lầm tưởng.
Git Branch thực chất là gì?
Một Git Branch chỉ bao gồm:
- Tên của branch
- Một pointer (con trỏ) trỏ đến commit cuối cùng của branch
Ví dụ:
A → B → C
↑
master
Branch master chỉ đơn giản là một con trỏ đang tham chiếu đến commit C.
Khi tạo commit mới:
A → B → C → D
↑
master
Git tự động cập nhật pointer của branch để luôn trỏ đến commit mới nhất.
Do branch chỉ là một pointer nên:
- Tạo branch gần như tức thời
- Không nhân bản toàn bộ source code
- Có thể tạo hàng trăm branch mà không tốn nhiều tài nguyên
Đây là nền tảng giúp Git cực kỳ phù hợp với:
- Feature Branch Workflow
- GitFlow
- Trunk-Based Development
- CI/CD Pipeline
Branch mặc định: master/main
Khi khởi tạo repository:
git init
Git sẽ tạo branch đầu tiên.
Trước đây là:
master
Ngày nay đa số repository sử dụng:
main
Branch này được tạo ngay từ đầu để bạn có thể thực hiện:
git commit
và bắt đầu xây dựng chuỗi commit của dự án.
Tạo Branch mới
Khi muốn phát triển tính năng mới mà không ảnh hưởng đến branch chính:
git branch feature-login
Lệnh trên chỉ tạo thêm một pointer:
A → B → C
↑
master
↑
feature-login
Cả hai branch đều trỏ đến cùng commit.
Checkout Branch
Khi chuyển sang branch mới:
git checkout feature-login
hoặc:
git switch feature-login
HEAD sẽ bắt đầu theo dõi branch này:
HEAD
↓
feature-login
↓
A → B → C
Trạng thái này gọi là: Attached State
HEAD đang "gắn" với một branch.
Commit trên Branch
Nếu tạo commit mới:
A → B → C → D
↑
feature-login
↑
HEAD
master
↓
C
Chỉ branch hiện tại di chuyển.
Branch khác hoàn toàn không bị ảnh hưởng.
Đây là cơ chế giúp nhiều developer có thể làm việc song song trên cùng một repository.
Git Tag – Đánh dấu các cột mốc quan trọng
Git cung cấp một loại pointer đặc biệt gọi là: Tag
Tag thường được dùng để đánh dấu:
- Release
- Build
- Milestone
- Version
Ví dụ:
v1.0
↓
A → B → C
hoặc:
v2.0
↓
A → B → C → D → E
Tạo tag:
git tag v1.0
Tạo annotated tag:
git tag -a v1.0 -m "Release version 1.0"
Vì sao Tag quan trọng trong DevOps?
Ví dụ:
Pipeline:
Build hỏi về lệnh ip ospf network point-to-point
Build làm thế nào để phát hiện là mình đang gặp routing-loop?
Build Một số điều góp ý
Tester phát hiện lỗi:
Bug xuất hiện ở Build làm thế nào để phát hiện là mình đang gặp routing-loop?
Developer có thể:
git checkout build-202
để tái tạo chính xác môi trường khi lỗi xảy ra.
Đây là lý do các pipeline CI/CD hiện đại thường:
Git Commit
↓
Build
↓
Tag
↓
Release
Điểm khác nhau giữa Branch và Tag
Branch
- Có thể di chuyển
- Luôn trỏ đến commit mới nhất
- Thay đổi sau mỗi commit
Ví dụ:
master → D → E → F
Tag
- Cố định
- Không thay đổi sau khi tạo
- Đánh dấu một commit cụ thể
Ví dụ:
v1.0 → C
Tag giống như một cột mốc lịch sử.
HEAD là gì?
HEAD là một pointer đặc biệt của Git.
HEAD cho biết:
"Hiện tại bạn đang đứng ở đâu trong repository."
Ví dụ:
HEAD
↓
master
↓
A → B → C
HEAD giúp Git xác định:
- Working Directory phải chứa file nào
- Commit tiếp theo sẽ được tạo ở đâu
- Branch nào đang được sử dụng
Attached HEAD
Trạng thái phổ biến nhất:
HEAD
↓
feature
↓
A → B → C
HEAD không trỏ trực tiếp vào commit.
Nó trỏ đến branch.
Branch trỏ đến commit.
Khi commit mới xuất hiện:
A → B → C → D
↑
feature
↑
HEAD
Cả HEAD và branch cùng di chuyển.
Detached HEAD là gì?
Đôi khi bạn muốn kiểm tra một commit cũ:
git checkout a1b2c3
Khi đó:
HEAD
↓
A → B → C
HEAD trỏ trực tiếp đến commit.
Không còn gắn với branch nào.
Đây gọi là: Detached HEAD State
Detached HEAD dùng để làm gì?
Rất hữu ích trong: Troubleshooting
git checkout v1.0 Reproduce Bug
git checkout build-202 Test Release
git checkout 9fceb Rollback Investigation
git checkout old-commit
CI/CD Pipeline cũng thường xuyên sử dụng Detached HEAD khi checkout theo commit hash hoặc tag.
Rủi ro của Detached HEAD
Nếu commit trong trạng thái này:
A → B → C
\
D
↑
HEAD
Commit D không thuộc branch nào.
Nếu checkout sang branch khác:
git checkout main
commit D có thể trở thành orphan commit và sau đó bị Git garbage collection xóa.
Cách thoát Detached HEAD
Tạo branch mới
git switch -c hotfix
hoặc:
git checkout -b hotfix
Khi đó:
A → B → C → D
↑
hotfix
↑
HEAD
Hoặc quay lại branch cũ
git checkout main
Git Stash – Cứu cánh khi đang làm dở
Tình huống rất quen thuộc:
Bạn đang viết:
my_network.py
thì production bị lỗi.
Bạn cần:
- Chuyển branch
- Pull code
- Fix khẩn cấp
Nhưng Working Directory còn rất nhiều code chưa hoàn thành.
Git sẽ không cho phép chuyển branch khi:
- Có modified file
- Có staged file
Giải pháp: Git Stash
Stash là một snapshot tạm thời của:
- Modified files
- Staged files
Lưu công việc:
git stash push -m "Work in progress"
Ví dụ:
$ git status -s
M my_network.py
Lưu:
$ git stash push -m "Work in progress"
Saved working directory and index state On feature: Work in progress
Kiểm tra:
$ git status
On branch feature
nothing to commit, working tree clean
Working Directory đã sạch hoàn toàn.
Khôi phục Stash
git stash pop
Kết quả:
On branch feature
Changes not staged for commit:
modified: my_network.py
File quay trở lại đúng trạng thái trước đó.
Một số lệnh Stash hữu ích
Xem danh sách:
git stash list
Lưu:
git stash push -m "Terraform WIP"
Khôi phục:
git stash pop
Khôi phục nhưng giữ lại stash:
git stash apply
Xóa:
git stash drop
Xóa toàn bộ:
git stash clear
Tại sao DevOps Engineer dùng Stash rất nhiều?
Ví dụ:
Bạn đang viết:
- Terraform Module
- Ansible Playbook
- Jenkinsfile
- Kubernetes Manifest
Đột nhiên production có sự cố.
Thay vì:
Tạo branch tạm
Commit code chưa hoàn thiện
Push lên remote
bạn chỉ cần:
git stash push -m "K8s deployment WIP"
git checkout hotfix
Sau khi xử lý xong:
git checkout feature
git stash pop
Toàn bộ công việc tiếp tục đúng nơi đã dừng.
Tóm tắt
Các khái niệm cốt lõi của Git Branching:
Branch = Pointer di động đến commit mới nhất
Tag = Pointer cố định đến một commit
HEAD = Vị trí hiện tại trong repository
Attached HEAD = HEAD → Branch → Commit
Detached HEAD = HEAD → Commit
Stash = Snapshot tạm thời của công việc chưa hoàn thành
Hiểu rõ các khái niệm này là nền tảng để làm chủ:
- GitFlow
- Pull Request/Merge Request
- GitOps
- CI/CD Pipeline
- Release Management
- Troubleshooting Production
- Infrastructure as Code với Terraform, Ansible và Kubernetes.