Danh sách branch dài dằng dặc: Nỗi ám ảnh sau mỗi sprint
Trong các team từ 5–10 lập trình viên chạy Scrum, mỗi sprint 2 tuần thường phát sinh từ 40 đến 60 Pull Request (PR). Sau khi review và merge vào main hoặc develop, chúng ta thường bấm nút Delete branch ngay trên giao diện web của GitHub hay GitLab để giữ repository gọn gàng.
Vấn đề phát sinh khi bạn quay lại terminal máy cá nhân và gõ lệnh:
git branch -r
# hoặc xem toàn bộ:
git branch -a
Màn hình tràn ngập hàng trăm nhánh dạng origin/feature/... và origin/hotfix/.... Phần lớn các nhánh này thực chất đã bị xóa trên GitHub từ 3–6 tháng trước. Cứ mỗi lần bạn bấm phím Tab để auto-complete, terminal lại bung ra cả danh sách dài ngoằng. Trải nghiệm tìm kiếm cực kỳ khó chịu. Rủi ro checkout nhầm code cũ cũng tăng vọt từ đây.
Chỉ cần lơ đãng checkout nhầm vào một nhánh trùng tên rồi commit đè, bạn sẽ mất hàng giờ revert và giải quyết conflict. Dọn dẹp branch rác không chỉ là sở thích ngăn nắp. Đây là bước phòng ngừa rủi ro bắt buộc khi làm dự án thực tế.
Vì sao Git không tự xóa nhánh cũ trên máy bạn?
Hiện tượng này bắt nguồn từ cấu trúc 3 tầng quản lý nhánh của Git:
- Local branch: Nhánh vật lý nằm trực tiếp trên máy bạn (ví dụ:
feature/payment). - Remote branch: Nhánh thực tế lưu trên server GitHub/GitLab (ví dụ:
paymenttrên remote). - Remote-tracking branch: Bản sao cục bộ ghi lại trạng thái remote branch trong lần liên lạc gần nhất (ví dụ:
origin/feature/payment).
Khi đồng nghiệp xóa nhánh trên GitHub, mục (2) đã biến mất hoàn toàn. Tuy nhiên, mục (3) vẫn nằm nguyên trong thư mục ẩn .git/refs/remotes/origin/ ở máy bạn.
Các lệnh cơ bản không tự giải quyết được vấn đề này:
git fetch
git pull
Triết lý cốt lõi của Git là ưu tiên an toàn dữ liệu. Git chỉ tải thêm commit và ref mới về. Nó không bao giờ tự ý xóa bất kỳ con trỏ tham chiếu (reference) nào ở local nếu bạn không ra lệnh rõ ràng. Kết quả là các nhánh đã bị hủy trên server vẫn tồn tại mãi mãi ở máy bạn dưới dạng “nhánh ma” (stale branches).
2 cách dọn sạch stale branches trong tích tắc
Git tích hợp sẵn cơ chế prune (cắt tỉa) để đối chiếu và xóa các nhánh tracking không còn tồn tại trên server. Bạn có thể chọn 1 trong 2 cách dưới đây:
Cách 1: Chạy lệnh chuyên dụng git remote prune
Muốn dọn dẹp riêng các liên kết remote mà không kéo code mới về, bạn dùng cú pháp:
git remote prune <tên-remote>
Thông thường remote mặc định có tên origin. Trước khi thao tác thật, bạn nên chạy thử chế độ an toàn để xem trước danh sách nhánh sẽ bị loại bỏ:
git remote prune origin --dry-run
Nếu danh sách hiển thị đúng các nhánh đã xóa trên server, hãy thực thi lệnh dọn dẹp:
git remote prune origin
Terminal sẽ báo cáo kết quả chi tiết:
Pruning origin
URL: [email protected]:my-team/backend-core.git
* [pruned] origin/feature/oauth2-login
* [pruned] origin/fix/cache-redis-leak
Toàn bộ tracking branch rác lập tức biến mất khỏi máy bạn.
Cách 2: Gộp dọn dẹp vào git fetch qua cờ –prune
Thay vì chạy hai bước riêng biệt, bạn có thể bảo Git vừa fetch code mới vừa tỉa nhánh cũ cùng lúc. Thêm cờ --prune (hoặc viết tắt là -p):
git fetch --prune
# hoặc lệnh tắt:
git fetch -p
Lệnh này giải quyết hai việc song song:
- Tải đầy đủ commit mới và nhánh mới từ GitHub về máy.
- Đối chiếu server với local, lập tức xóa các bản
origin/...không còn tồn tại trên server.
Lệnh git pull cũng hỗ trợ cờ tương tự:
git pull --prune
Điểm cần phân biệt: Tracking branch khác gì Local branch?
Cần lưu ý: Cả hai lệnh trên chỉ xóa remote-tracking branch (tiền tố origin/). Chúng hoàn toàn không chạm vào nhánh local của bạn.
Nếu trước đó bạn từng checkout nhánh về máy để code, nhánh local đó vẫn còn nguyên. Để dọn nốt nhánh local sau khi PR đã merge thành công, hãy gõ:
git branch -d feature/oauth2-login
Trường hợp nhánh chưa merge nhưng bạn muốn bỏ hẳn, đổi cờ -d thành -D để xóa dứt điểm.
Giải pháp triệt để: Bật tự động prune vĩnh viễn
Chẳng ai muốn phải nhớ gõ thêm cờ -p sau mỗi lần fetch. Cách tối ưu nhất là cấu hình Git tự động prune mỗi khi trao đổi dữ liệu với remote.
Chạy duy nhất một dòng lệnh trong terminal:
git config --global fetch.prune true
Từ thời điểm này, mỗi khi bạn gõ git fetch hoặc git pull, Git sẽ tự động kích hoạt tính năng tỉa nhánh ngầm. Danh sách branch ở local sẽ luôn khớp chính xác với trạng thái thực tế trên remote.
Để kiểm tra lại thiết lập trên máy cá nhân:
git config --global --get fetch.prune
Nếu terminal trả về kết quả true, cấu hình đã sẵn sàng hoạt động.
