Fetch, pull và push: đồng bộ với remote
Fetch, Pull and Push
Sau khi đã có remote, bạn cần ba thao tác để đồng bộ sync: fetch để tải về, pull để tải và gộp, push để gửi lên. Hiểu rõ chúng giúp bạn tránh các xung đột và lịch sử rối.
git fetch: chỉ tải về, không gộp
git fetch tải các commit mới từ remote về repo local, cập nhật các nhánh theo dõi remote (như origin/main), nhưng không đụng tới nhánh đang làm việc của bạn.
# Tải mọi cập nhật từ origin, không thay đổi nhánh hiện tại
git fetch origin
Sau khi fetch, bạn có thể xem trước thay đổi trước khi quyết định gộp:
# So sánh nhánh local với nhánh remote vừa fetch về
git log main..origin/main --oneline
Vì fetch an toàn (không tự sửa code đang làm), nó là cách tốt để xem người khác đã đẩy gì lên trước khi gộp.
git pull: fetch rồi merge
git pull thực chất là hai bước gộp một: git fetch rồi git merge. Nó tải về và ngay lập tức gộp nhánh remote vào nhánh hiện tại.
# Tương đương: git fetch origin + git merge origin/main
git pull origin main
Nếu nhánh của bạn và remote đã phân nhánh (cả hai cùng có commit mới), pull tạo một merge commit để gộp. Nếu có xung đột nội dung, Git dừng lại để bạn giải quyết.
git push: đẩy commit lên remote
git push gửi các commit local của bạn lên remote.
# Đẩy nhánh main local lên origin
git push origin main
Git từ chối push nếu remote có commit mà bạn chưa có (non-fast-forward) để tránh ghi đè mất việc của người khác. Khi đó bạn phải pull (hoặc pull --rebase) để gộp về trước, rồi push lại.
Tránh git push --force
git push --force ghi đè lịch sử remote và có thể xóa mất commit của đồng đội. Chỉ dùng trên nhánh riêng của bạn, và ưu tiên --force-with-lease an toàn hơn vì nó kiểm tra remote chưa thay đổi ngoài dự kiến.
pull --rebase: lịch sử thẳng hàng
git pull --rebase thay vì tạo merge commit, sẽ rebase các commit local của bạn lên trên commit mới nhất của remote. Kết quả là lịch sử thẳng, không có merge commit thừa.
# Fetch rồi rebase commit local lên trên origin/main
git pull --rebase origin main
| Tiêu chí | git pull (merge) | git pull --rebase |
|---|---|---|
| Tạo merge commit | Có (khi phân nhánh) | Không |
| Hình dạng lịch sử | Có nhánh, có gộp | Thẳng, tuyến tính |
| Giữ nguyên hash commit | Có | Không (viết lại) |
| Hợp với nhánh đã chia sẻ | An toàn hơn | Cẩn thận với nhánh chung |
Đặt rebase làm mặc định
Nhiều đội đặt git config --global pull.rebase true để mọi git pull mặc định rebase, cho lịch sử gọn. Nhưng tránh rebase commit đã được push và người khác đã pull về.
Trọng tâm thi
git fetch chỉ tải về (cập nhật origin/main), không đụng nhánh local. git pull = fetch + merge (gộp ngay). git pull --rebase = fetch + rebase cho lịch sử thẳng. git push bị từ chối nếu non-fast-forward — phải pull về trước.
Tóm tắt
git fetch: tải commit mới về, cập nhật nhánh remote (origin/main), không sửa nhánh đang làm.git pull: fetch rồi merge — tải và gộp ngay vào nhánh hiện tại, có thể tạo merge commit.git push: đẩy commit local lên remote; bị từ chối nếu remote có commit bạn chưa có.git pull --rebase: fetch rồi rebase, cho lịch sử thẳng, không merge commit thừa.- Tránh
push --forcetrên nhánh chung; nếu cần thì ưu tiên--force-with-lease.