Tám bài trước xoay quanh 1 repo cục bộ duy nhất. Bài này mở rộng ra tình huống thực tế nhất: nhiều
người cùng làm việc trên 1 remote (thường là GitHub/GitLab). fetch, pull,
push chỉ là các cách khác nhau để đồng bộ 2 đồ thị commit — repo cục bộ của bạn và repo
trên server — vốn có thể phân kỳ (diverge) bất cứ lúc nào đồng nghiệp push trước bạn.
1. git fetch vs git pull: Tải Về Nhưng Không (Hoặc Có) Trộn
git fetch tải các commit mới từ remote về máy bạn và cập nhật con trỏ
origin/main — nhưng
không đụng tới branch main cục bộ hay Working Directory của bạn. Đây là
lệnh 100% an toàn, có thể chạy bất cứ lúc nào chỉ để "xem đồng nghiệp đã làm gì" mà không ảnh hưởng
việc bạn đang làm dở.
git pull đơn giản là git fetch rồi tự động trộn
origin/main vào branch hiện tại của bạn — mặc định bằng merge (tạo commit
hợp nhất nếu đã phân kỳ, xem lại Bài 4), hoặc bằng
rebase nếu bạn chạy git pull --rebase.
2. Remote-tracking Branch: origin/main Là Gì?
origin/main không phải là branch trên remote — nó là một
bản sao cục bộ, chỉ đọc, ghi nhớ "lần cuối tôi fetch, remote đang ở commit nào".
Local main và local origin/main hoàn toàn có thể trỏ tới 2 commit khác nhau
cùng lúc — đó chính xác là lúc bạn "phía trước" hoặc "phía sau" remote, giống hệt cơ chế con trỏ đã
học ở Bài 3.
git fetch tuyệt đối không làm hỏng thứ gìorigin/main (không đụng
main hay Working Directory), nó không thể gây conflict hay mất dữ liệu. Thói quen tốt:
git fetch thường xuyên để luôn biết trạng thái remote, rồi tự quyết định khi nào
merge hoặc rebase — thay vì để pull tự động quyết định hộ
bạn.
3. git push: Fast-forward Hay Bị Từ Chối?
git push chỉ thành công khi lịch sử remote là tổ tiên trực tiếp của lịch
sử bạn đang push — tức remote có thể "tiến nhanh" (fast-forward, xem lại
Bài 3) tới đúng commit bạn gửi lên. Nếu ai đó đã push trước bạn kể từ
lần fetch gần nhất, remote chứa commit bạn chưa có — Git từ chối với lỗi non-fast-forward,
buộc bạn fetch/pull để tích hợp trước.
git push --force ghi đè lịch sử người khác
--force bỏ qua kiểm tra fast-forward, ép remote nhận đúng lịch sử của bạn — kể cả khi
nó xoá mất commit của đồng nghiệp. Đây là vi phạm trực tiếp Golden Rule đã học ở
Bài 5: không viết lại lịch sử đã chia sẻ. Nếu thực sự cần (ví dụ
sau khi rebase 1 nhánh cá nhân), luôn dùng --force-with-lease — nó từ chối ghi đè nếu
ai đó đã push thêm gì mà bạn chưa fetch, an toàn hơn --force thường rất nhiều.
4. Rebase vs Merge Khi Làm Việc Nhóm
git pull (merge, mặc định) |
git pull --rebase |
|
|---|---|---|
| Lịch sử kết quả | Có commit hợp nhất (2 cha) khi phân kỳ | Tuyến tính — commit cục bộ được phát lại (replay) trên đỉnh remote |
| Hash commit cục bộ | Giữ nguyên | Đổi mới (giống cherry-pick ở Bài 6) |
| An toàn khi nào | Luôn an toàn, kể cả commit đã push | Chỉ an toàn với commit CHƯA push — đúng Golden Rule ở Bài 5 |
Nhiều team đặt git config pull.rebase true làm mặc định để giữ lịch sử tuyến tính, dễ đọc
hơn khi nhiều người cùng push liên tục vào 1 branch.
git merge (hoặc rebase/squash tuỳ cấu hình) mà bạn đã học ở
Bài 4 và Bài 5 — không có phép màu
Git nào khác đứng sau nó.
git branch -vvpush, pull, hay cả 2 mà không cần đoán.
Lần đầu push 1 branch mới, dùng git push -u origin <tên-branch> để thiết lập quan
hệ upstream này.
Sân chơi tương tác: Demo Diverge & Sync Giữa Local Và Remote
Kịch bản khởi đầu: bạn đã commit 1 thay đổi cục bộ, nhưng chưa fetch — trong lúc đó 1
đồng nghiệp đã âm thầm push 1 commit khác lên remote. Hãy thử git push ngay xem điều gì
xảy ra, rồi git fetch, rồi thử cả git pull lẫn
git pull --rebase (reset demo giữa 2 lần thử) để so sánh kết quả.
Terminal giả lập (local)
git commit -m "..."git fetchgit pullgit pull --rebasegit pushgit log
Nhật ký
Trắc nghiệm ôn tập
Câu 1: Sau khi chạy git fetch, điều gì chắc chắn KHÔNG thay đổi?
Trắc nghiệm ôn tập
Câu 2: Vì sao git push đôi khi bị từ chối với lỗi "non-fast-forward"?
Trắc nghiệm ôn tập
Câu 3: Pull Request (GitHub) hay Merge Request (GitLab) có phải là 1 khái niệm cốt lõi của Git không?