Hướng dẫn · 26/09/2026

Git hai chấm và ba chấm: Đọc đúng khác biệt giữa hai nhánh

Bạn xem một nhánh tính năng bằng git log rồi mở git diff, nhưng phạm vi thay đổi có vẻ không giống nhau. Nguyên nhân thường là đang coi ký hiệu hai chấm và ba chấm có cùng ý nghĩa trong mọi lệnh. Trước khi review, hãy xác định mình cần xem lịch sử commit hay khác biệt nội dung file.

Git hai chấm và ba chấm: Đọc đúng khác biệt giữa hai nhánh

Bạn xem một nhánh tính năng bằng git log rồi mở git diff, nhưng phạm vi thay đổi có vẻ không giống nhau. Nguyên nhân thường là đang coi ký hiệu hai chấm và ba chấm có cùng ý nghĩa trong mọi lệnh. Trước khi review, hãy xác định mình cần xem lịch sử commit hay khác biệt nội dung file.

1. Dùng một lịch sử nhỏ để hình dung

      M1---M2  main
     /
O---B
     \
      F1---F2  feature

Trong ví dụ, hai nhánh có tổ tiên chung B, chưa merge qua lại. main có thêm M1 và M2; feature có thêm F1 và F2. Các chữ là nhãn minh họa, không phải mã commit thật. Những lệnh dưới đây giả định cả hai nhánh tồn tại trong repository local.

2. git log: chọn tập commit

git log --oneline main..feature
git log --oneline feature..main
git log --oneline --left-right main...feature

Theo tài liệu Git revisions, A..B chọn commit đi tới được từ B nhưng không từ A. A...B chọn phần riêng của cả hai phía, loại phần chung. Trong sơ đồ, lệnh đầu chọn F1, F2; lệnh thứ hai chọn M1, M2; lệnh cuối chọn cả bốn.

Với --left-right, dấu < đánh dấu phía main và > đánh dấu phía feature trong lệnh cuối. Đây không phải ký hiệu dòng bị xóa hoặc được thêm trong file. Thứ tự hiển thị commit không nhất thiết giống thứ tự các nhãn trong đoạn giải thích.

3. git diff: so nội dung, không liệt kê tập commit

git diff main..feature
git diff main...feature

Tài liệu Git diff mô tả hai chấm ở đây là so hai đầu mút, tương đương git diff main feature. Ba chấm so từ merge base của hai nhánh đến đầu mút phía phải. Trong ví dụ, đó là so B với F2, không phải gom thay đổi riêng của cả hai nhánh.

Vì vậy, khi main thêm một file sau B nhưng feature không có file đó, so hai đầu mút có thể hiển thị file như bị xóa ở phía feature. Điều này chưa chứng minh người viết feature đã xóa file trong công việc của họ. Cần đọc đúng mốc so sánh trước khi nhận xét.

4. Chọn câu hỏi trước, chọn lệnh sau

Câu hỏiLệnh tham khảo
Feature có commit nào chưa thuộc lịch sử main?git log main..feature
Hai nhánh có commit riêng nào?git log --left-right main...feature
Nội dung hai đầu nhánh khác nhau ra sao?git diff main feature
Feature thay đổi gì so với merge base?git diff main...feature

Đổi thứ tự hai nhánh cũng đổi câu hỏi. Với diff ba chấm, phía phải quyết định đầu mút được so với merge base; không nên đảo tên chỉ để output trông thuận mắt hơn.

5. Những giới hạn dễ bỏ qua

Các lệnh so commit không bao gồm thay đổi chưa commit trong working tree. main local cũng có thể khác origin/main, và origin/main chỉ phản ánh lần cập nhật tham chiếu gần nhất, không phải truy vấn trực tiếp server mỗi lần chạy log.

Sau cherry-pick hoặc rebase, hai commit có thể mang thay đổi tương tự nhưng mã khác nhau. Danh sách commit riêng không tự chứng minh chức năng đó còn thiếu ở nhánh kia. Với lịch sử merge phức tạp có nhiều merge base, hãy kiểm tra đồ thị thay vì áp dụng máy móc sơ đồ đơn giản trên.

  • Ghi rõ hai tham chiếu dùng để review.
  • Phân biệt so lịch sử với so nội dung.
  • Kiểm tra hướng trái/phải của lệnh.
  • Đọc patch và chạy test, không chỉ đếm commit.
  • Không merge hoặc rebase chỉ để làm hai output giống nhau.

Các lệnh trong bài dùng để đọc và so sánh, không chuyển nhánh hay áp dụng patch. Hiểu đúng mốc so sánh giúp review tập trung vào thay đổi cần đánh giá, thay vì phản ứng với khác biệt do chọn sai phạm vi.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.