Skip to content

3. Branching Basics

IMPORTANT

Branch không phải đồ trang trí. Nó là cơ chế an toàn để nhiều người cùng làm việc mà không giẫm lên nhau, không làm bẩn main, và không biến release thành canh bạc.

3.1 Branching giải quyết vấn đề gì?

Nếu cả team cùng commit trực tiếp lên main, bạn sẽ gặp đúng 4 loại hỗn loạn:

  1. Code chưa hoàn tất lọt vào luồng ổn định
  2. Một bug khẩn cấp phải chen ngang giữa lúc team đang làm feature
  3. QA cần chốt release, nhưng dev vẫn tiếp tục đẩy thay đổi mới
  4. Review khó khăn vì lịch sử commit trộn nhiều mục tiêu khác nhau

Branching giải quyết chuyện đó bằng cách tách công việc theo mục đích:

  • main: đường ổn định, đại diện cho trạng thái đáng tin cậy
  • feature/...: nơi phát triển tính năng mới
  • hotfix/...: nơi xử lý sự cố production khẩn cấp
  • release/...: nơi ổn định bản phát hành trước khi ship

Nói ngắn gọn: branching giúp làm việc song song mà vẫn giữ được kỷ luật tích hợp.


3.2 Mental model: xem branch như “làn đường giao thông”

  • main = làn cao tốc đang chở khách hàng
  • feature/... = làn thi công tính năng
  • hotfix/... = xe cứu hỏa chạy ưu tiên
  • release/... = khu kiểm định cuối trước khi bàn giao

Nếu bạn đem xe đang sửa dở chạy thẳng lên cao tốc, bạn không “tiết kiệm thời gian” — bạn đang tăng xác suất gây tai nạn cho cả hệ thống.

Sơ đồ branch flow

ASCII nhìn nhanh

text
main:      o----o-------------------o---------
             \                    /
feature:      o----o----o--------'

main:      o----o-----------o-----------------
                           /
hotfix:                   o

main:      o----o----o------------------------
                    \
release:             o----o----o

3.3 Vì sao engineer không nên làm việc “casual” trên main?

WARNING

main không phải sandbox cá nhân. Trong team nghiêm túc, main là branch được bảo vệ, có review, có CI, có trách nhiệm vận hành đi kèm.

Nếu bạn làm trực tiếp trên main, bạn đang đánh đổi:

Rủi roHậu quả thực tế
Commit code đang dởCI đỏ, deploy lỗi, QA mất niềm tin
Trộn nhiều mục tiêu vào cùng lịch sửReview khó, revert khó, root-cause khó
Đẩy nhầm debug codeRò rỉ log, giảm chất lượng production
Sửa nóng ngay trên main khi đang hoảngDễ chữa cháy thành cháy to hơn

Nguyên tắc thực chiến

  • Không dùng main để thử nghiệm
  • Không commit “tạm để đó” lên main
  • Không force-push lên shared branch
  • Mọi thay đổi nên đi qua branch có mục đích rõ ràng

Trường hợp ngoại lệ có thể tồn tại trong hạ tầng rất nhỏ hoặc incident cực kỳ khẩn cấp, nhưng ngay cả khi đó, quy trình vẫn phải bị kiểm soát, không phải “thích thì sửa”.


3.4 Ba pattern branch mà bạn phải hiểu

3.4.1 Feature branch: làm tính năng mà không phá luồng ổn định

Mental model: một không gian cô lập cho một mục tiêu phát triển cụ thể.

Ví dụ thực tế: payment retry feature

Team payments cần thêm cơ chế retry khi cổng thanh toán timeout:

bash
git switch main
git pull origin main
git switch -c feature/payment-retry

Trong branch này, bạn có thể:

  • thêm retry logic
  • viết test cho retry policy
  • chỉnh UI thông báo “đang thử lại”
  • refactor phần nhỏ liên quan trực tiếp

Điểm quan trọng: mọi thay đổi vẫn bị giữ ngoài main cho đến khi review xong.

Feature branch phù hợp khi:

  • bạn đang làm một tính năng hoặc improvement có phạm vi rõ
  • cần review riêng
  • chưa muốn tác động ngay đến branch ổn định

Feature branch không phù hợp khi:

  • thay đổi quá nhỏ nhưng vẫn cần PR: vẫn có thể tạo branch ngắn-lived, nhưng đừng biến nó thành nhánh sống cả tháng
  • team deploy liên tục: branch nên ngắn hạn, không ôm việc kéo dài vô tận

3.4.2 Hotfix branch: ưu tiên cứu production

Mental model: nhánh dành cho sự cố cần xử lý ngay, tách khỏi các công việc đang phát triển dở dang.

Ví dụ thực tế: production login hotfix

Sau deploy, người dùng không đăng nhập được do cookie session bị set sai.

Thay vì chen fix giữa feature đang làm, bạn tách nhánh:

bash
git switch main
git pull origin main
git switch -c hotfix/login-prod

Bạn sửa đúng lỗi production, test tối thiểu, mở PR khẩn cấp, rồi merge lại vào main.

Vì sao phải tách branch?

  • tránh kéo theo code chưa hoàn tất từ các feature khác
  • review tập trung đúng vào lỗi cần cứu
  • dễ cherry-pick hoặc merge lại sang release branch nếu cần

Hotfix branch phù hợp khi:

  • bug đang ảnh hưởng production
  • cần xử lý nhanh nhưng vẫn phải truy vết được
  • cần cô lập thay đổi để rollback/review dễ hơn

Hotfix branch không phù hợp khi:

  • lỗi không khẩn cấp, không ảnh hưởng production
  • bạn đang dùng “hotfix” chỉ để lách review hoặc lách quy trình

3.4.3 Release branch: chốt bản phát hành để ổn định

Mental model: đóng băng phạm vi thay đổi, chỉ cho phép các chỉnh sửa giúp bản phát hành đạt chất lượng.

Ví dụ thực tế: release stabilization branch

Team chuẩn bị phát hành v2.8.0. Tính năng đã đủ, nhưng QA cần 3 ngày để test hồi quy.

Bạn tách:

bash
git switch main
git pull origin main
git switch -c release/2.8.0

Từ lúc này:

  • release/2.8.0 chỉ nhận bug fix, wording fix, config fix cần cho bản phát hành
  • feature mới tiếp tục đi trên branch khác, không chen vào bản sắp ship

Release branch phù hợp khi:

  • có giai đoạn hardening hoặc QA stabilization
  • cần cố định phạm vi release
  • cần chuẩn bị version, changelog, kiểm thử cuối

Release branch không phù hợp khi:

  • team deploy liên tục nhiều lần mỗi ngày và không có khái niệm freeze window
  • dự án quá nhỏ, một release branch riêng chỉ tạo thêm ceremony mà không tăng an toàn

TIP

Không phải mọi team đều cần full Git Flow. Điều cần giữ là nguyên tắc an toàn cộng tác, không phải nghi lễ phức tạp.


3.5 Khi nào KHÔNG nên dùng một branch pattern?

Đây là câu hỏi nhiều người bỏ qua.

Không phải lúc nào cũng cần full pattern feature/hotfix/release

Bạn không nên áp dụng máy móc nếu:

  1. Repo cá nhân, demo ngắn, throwaway prototype

    • có thể chỉ cần main + vài branch ngắn hạn
  2. Team nhỏ, deploy liên tục, không có giai đoạn stabilization

    • có thể không cần release/...
  3. Thay đổi cực nhỏ nhưng branch sống quá lâu

    • vấn đề không nằm ở branch, mà ở việc giữ branch quá lâu và đồng bộ quá kém
  4. Dùng branch pattern để che giấu kỷ luật kém

    • ví dụ đặt tên hotfix/... cho mọi việc để né review

Quy tắc chọn pattern đúng

  • Chọn pattern theo mức độ cộng tác và rủi ro
  • Ưu tiên branch ngắn hạn, mục tiêu rõ ràng
  • Đừng biến workflow thành nghi thức phức tạp hơn nhu cầu thực tế

3.6 Nếu lỡ làm việc trên nhánh sai thì cứu thế nào?

Đây là câu hỏi bắt buộc phải biết trước khi bạn hoảng.

3.6.1 Trường hợp 1: commit nhầm vào main, chưa push

Mục tiêu: giữ lại công việc, đưa nó sang branch đúng, trả main về trạng thái sạch.

bash
git switch -c feature/payment-retry
git switch main
git reset --hard origin/main

Ý nghĩa:

  • commit nhầm vẫn được giữ trên branch mới
  • main local quay về đúng trạng thái remote

CAUTION

Chỉ dùng reset --hard origin/main khi bạn chắc chắn commit nhầm chưa được push và nội dung đã được “cứu” sang branch khác.

3.6.2 Trường hợp 2: commit nhầm vào main, đã push

Lúc này đừng rewrite shared history một cách casual.

Cách an toàn hơn:

  1. tạo branch cứu hộ từ commit hiện tại để giữ dấu vết nếu cần
  2. tạo PR revert commit sai trên main
  3. cherry-pick hoặc giữ commit đó trên branch đúng nếu thay đổi vẫn cần tồn tại

Ví dụ:

bash
git switch -c rescue/payment-retry-main-mistake
git switch main
git revert <sha-commit-nham>
git switch -c feature/payment-retry origin/main
git cherry-pick <sha-commit-nham>

Tại sao không reset/force-push?

Vì khi commit đã nằm trên shared branch:

  • người khác có thể đã pull về
  • CI, deploy, audit trail có thể đang bám vào SHA đó
  • rewrite history lúc incident xảy ra thường làm tình hình tệ hơn

3.6.3 Trường hợp 3: đang sửa trên feature branch nhưng lẽ ra phải là hotfix branch

Nếu code sửa đúng là fix production:

bash
git switch -c hotfix/login-prod

Tức là bạn “đổi tên ngữ nghĩa” bằng cách tách nhánh mới ngay tại commit hiện tại, rồi tiếp tục đi đúng quy trình hotfix.


3.7 Nguyên tắc cộng tác an toàn với branch

Checklist trước khi tạo branch

  • Tôi đang giải quyết một mục tiêu rõ ràng chưa?
  • Branch này thuộc loại nào: feature, hotfix, hay release?
  • Nếu merge branch này hôm nay, team có hiểu ngay nó dùng để làm gì không?

Checklist trước khi merge về main

  • đã review chưa?
  • CI xanh chưa?
  • branch có trộn việc không liên quan không?
  • rollback hoặc revert có đơn giản không?

Nếu câu trả lời là “không rõ”, bạn chưa sẵn sàng chạm vào main.


3.8 Tóm tắt quyết định nhanh

Tình huốngNên dùng branch nào?Ghi nhớ
Làm payment retry featurefeature/payment-retryCô lập tính năng để review sạch
Login production đang lỗihotfix/login-prodCứu production, scope thật hẹp
Chuẩn bị ship bản 2.8.0release/2.8.0Chốt phạm vi, ưu tiên ổn định
Muốn test linh tinhKhông phải mainTạo branch riêng
Commit nhầm vào mainbranch cứu hộ + reset/revert tùy push stateCứu lịch sử trước, sửa sau

🧠 Quiz

Câu 1: Branching chủ yếu giải quyết vấn đề gì trong team?

  • [ ] A) Giúp Git chạy nhanh hơn
  • [x] B) Cho phép nhiều luồng công việc chạy song song mà không phá branch ổn định
  • [ ] C) Bắt buộc để dùng git commit
  • [ ] D) Thay thế hoàn toàn code review

💡 Giải thích: Branching là cơ chế an toàn cộng tác. Nó tách tính năng, hotfix, và release để main vẫn đáng tin cậy.

Câu 2: Khi nào không nên áp dụng máy móc pattern release/...?

  • [ ] A) Khi chuẩn bị QA regression cho một bản phát hành lớn
  • [x] B) Khi team deploy liên tục và không có giai đoạn stabilization riêng
  • [ ] C) Khi cần chốt phạm vi bản phát hành
  • [ ] D) Khi cần sửa lỗi nhỏ trước ngày ship

💡 Giải thích: Release branch có giá trị khi team thật sự cần freeze window. Nếu không có nhu cầu đó, giữ thêm branch lâu dài chỉ tạo ceremony.

Câu 3: Bạn commit nhầm vào mainđã push. Hành động an toàn nhất là gì?

  • [ ] A) git reset --hard rồi force-push ngay lên main
  • [x] B) Revert commit sai trên main, rồi chuyển phần thay đổi cần giữ sang branch đúng
  • [ ] C) Xóa branch main rồi tạo lại
  • [ ] D) Kệ luôn vì Git đã lưu lịch sử rồi

💡 Giải thích: Với shared branch, ưu tiên revert thay vì rewrite history. Sau đó bạn có thể cherry-pick commit sang feature/... hoặc hotfix/... phù hợp.