- git pull = git fetch + git merge.
- Nghe đơn giản, nhưng chọn sai lệnh đồng nghĩa với merge commit rác, conflict bất ngờ, và đôi khi mất cả đống công sức.
- Đây là khi nào nên dùng cái nào, và vì sao 'fetch often, pull rarely' là câu thần chú đáng nhớ.
TL;DR
git fetch tải changes từ remote về local repo nhưng không đụng đến working directory hay branch hiện tại — chỉ cập nhật remote-tracking refs (vd origin/main). git pull = git fetch + git merge, tự động apply changes vào branch đang đứng. Công thức đơn giản: git pull = git fetch + git merge. Fetch an toàn 100%. Pull có thể gây conflict hoặc merge commit rác nếu không cẩn thận.
Vấn đề: tại sao dev vẫn nhầm?
Một tweet viral từ @paypaldev tóm gọn trong 2 dòng:
Fetch: lấy changes mới từ remote, không áp dụng vào local branch.
Pull: là kết hợp củagit fetchvàgit merge.
Nghe đơn giản nhưng hàng ngày vẫn có dev chạy git pull trên branch bẩn rồi ngồi gỡ conflict 30 phút. Hoặc tệ hơn: pull nhầm branch, overwrite commit chưa push. Hiểu đúng 2 lệnh này là bài học Git cơ bản nhất mà ai cũng nên đóng đinh lại.
git fetch làm gì chính xác?
Theo git-scm.com/docs/git-fetch, fetch tải về:
- Commits, blobs, trees và mọi object cần để hoàn thiện history
- Cập nhật remote-tracking branches như
refs/remotes/origin/main - Ghi thông tin ref vào
.git/FETCH_HEAD
Và không làm gì khác:
- KHÔNG merge hay rebase
- KHÔNG sửa working directory — chạy bất cứ lúc nào đều an toàn
- KHÔNG update local branch của bạn
- KHÔNG tạo merge commit
- KHÔNG fast-forward branch hiện tại
Nói cách khác: fetch chỉ "xem remote đang có gì mới". Không có gì trong code của bạn thay đổi.
git pull làm gì?
Git pull là một convenience wrapper, tương đương chạy:
git fetch origin
git merge FETCH_HEADNếu bạn config pull.rebase=true, nó chạy git rebase thay vì merge — replay commits local của bạn lên trên tip remote mới nhất, cho history tuyến tính, không có merge commit rác.
So sánh trực tiếp
| Aspect | git fetch | git pull |
|---|---|---|
| Download remote refs | Có | Có |
| Cập nhật working dir | Không | Có |
| Cập nhật local branch | Không | Có |
| Rủi ro merge conflict | Không | Có |
| Reversible | Dễ | Cần reset/revert |
| Use case | Xem trước rồi quyết định | Sync nhanh |
Khi nào dùng cái nào?
Fetch-first workflow (khuyên dùng cho team)
git fetch origin
git log origin/main..main # commits local chưa có trên remote
git log main..origin/main # commits remote chưa có trên local
git diff main origin/main # xem diff thực sự
git merge origin/main # chỉ merge khi đã reviewBước fetch giúp bạn thấy được ai push gì trước khi đụng đến branch hiện tại. Đặc biệt quan trọng khi nhiều người cùng làm một branch.
Pull để sync nhanh
git pull origin mainỔn khi bạn làm solo hoặc branch của bạn ổn định, ít divergence với remote.
Rebase pull cho history sạch
git pull --rebase origin main
# hoặc set global:
git config --global pull.rebase trueKhông còn merge commit "Merge branch 'main' of origin..." rác trong log.
Dọn remote branches đã bị xoá
git fetch --all --pruneRemove mọi origin/* ref đã không còn tồn tại trên remote.
Cạm bẫy thường gặp
- git pull khi working tree bẩn: Git sẽ từ chối merge nếu có uncommitted changes xung đột với incoming. Commit hoặc stash trước.
- Merge commit rác: mỗi lần pull trên branch có local commits chưa push tạo thêm merge commit. Dùng
--rebase. - Pull nhầm branch:
git pull origin wrong-branchmerge branch lạ vào. Luôn check branch trước. - Quên fetch: làm việc với remote-tracking branches cũ. Fetch thường xuyên, tốt nhất là auto-fetch qua IDE hoặc hook.
Best practice
Khẩu quyết từ GitLab: "Fetch often, pull only when necessary."
- Fetch thường xuyên (hoặc bật auto-fetch trong IDE) để luôn biết remote có gì mới.
- Chỉ pull khi thật sự muốn apply changes vào branch hiện tại.
- Bật
pull.rebase=truecho team repo để tránh merge commit rác. - Với branch quan trọng (main, release): luôn fetch trước, review log, rồi merge/rebase thủ công.
Kết
git fetch vs git pull không phải kiến thức mới lạ — nhưng nó là một trong những nhầm lẫn phổ biến nhất của Git, kể cả với dev nhiều năm kinh nghiệm. Nhớ công thức: git pull = git fetch + git merge. Khi không chắc, fetch trước, xem log, rồi mới quyết định.
Nguồn: git-scm.com, GitLab blog, @paypaldev.

