Kamu sedang mengerjakan fitur feature/export-laporan di project Laravel. Partner satu tim baru saja push beberapa commit ke main. Kamu tidak mau ketinggalan, jadi jalankan git pull — dan tiba-tiba muncul merge commit yang tidak diduga, atau malah konflik yang bikin bingung. Padahal cuma mau update.
Keprihatinan ini sangat umum, dan akar masalahnya sering sama: tidak memahami perbedaan antara git fetch dan git pull. Keduanya memang mengambil data dari remote repository, tapi dampaknya ke working tree dan branch lokal sangat berbeda. Memakai yang salah di momen yang salah bisa menghasilkan merge commit yang tidak diinginkan atau konflik yang bisa dicegah.
Artikel ini membahas perbedaan konseptual dan praktis antara keduanya, cara kerja remote-tracking branch, varian integrasi (fast-forward, merge, rebase), flag --ff-only, --prune, dan kapan sebaiknya memakai masing-masing.
Apa Itu git fetch?
Fetch mengunduh tanpa menggabungkan
Secara resmi, git fetch mengunduh branch, tag, dan objek yang diperlukan untuk melengkapi history dari remote. Remote-tracking branch seperti origin/main atau origin/feature-x diperbarui sesuai state terbaru di remote.
Poin terpenting yang harus kamu pahami sejak awal: git fetch tidak menyentuh working tree atau branch lokal sama sekali. File di folder project tidak berubah. Dari dokumentasi resmi Pro Git: "While the git fetch command will fetch all the changes on the server that you don't have yet, it will not modify your working directory at all. It will simply get the data for you and let you merge it yourself."
Artinya, setelah git fetch, kamu mungkin melihat bahwa origin/main sudah lebih maju dari main lokal — tapi file di working directory masih persis seperti sebelum fetch. Kamu "tertinggal" dari remote secara data, tapi dalam kondisi yang sepenuhnya aman.
Remote-tracking branch
Sebelum melangkah lebih jauh, kamu perlu memahami apa itu remote-tracking branch. Dari Pro Git: "Remote-tracking branches are references to the state of remote branches. Remote-tracking branch names take the form <remote>/<branch>." Jadi origin/main adalah referensi yang menyimpan state branch main di remote bernama origin.
Remote-tracking branch hanya diperbarui saat fetch. Kalau kamu tidak pernah menjalankan git fetch, referensi origin/main tetap pada state terakhir kali fetch dilakukan — berapapun commit baru yang sudah di-push partnermu.
Satu hal lagi: remote-tracking branch baru hasil fetch bukan salinan lokal yang bisa kamu edit. Kamu tidak bisa langsung commit ke origin/main. Kalau ingin bekerja di branch baru yang muncul dari remote, buat branch lokal dulu:
git switch -c fitur-export-asli origin/feature-export
Fetch dalam praktiknya
Perintah paling dasar adalah git fetch origin, yang menyalin semua branch dari remote ke namespace lokal refs/remotes/origin/:
git fetch origin
Setelah fetch, kamu bisa memeriksa apa yang baru. Misalnya, commit lokal yang belum ada di remote:
git log origin/main..HEAD
Atau melihat perbedaan file antara state lokal dan remote:
git diff HEAD origin/main
Dengan dua perintah ini, kamu bisa mengevaluasi perubahan sebelum memutuskan apakah ingin menggabungkannya. Pola "fetch dulu, periksa, baru gabung" ini adalah salah satu best practice yang paling direkomendasikan.
Apa Itu git pull?
Pull = fetch + integrasi
Dari dokumentasi resmi: "Integrate changes from a remote repository into the current branch. First, git pull runs git fetch with the same arguments … Then it integrates that branch into the current branch."
Artinya, git pull sebenarnya dua operasi dalam satu perintah: fetch lalu integrasi. Kalau kamu menjalankan git pull origin main, Git pertama-tama mengambil data dari origin/main, lalu menggabungkannya ke branch saat ini.
Tanpa argumen, git pull default ke upstream branch dari branch yang sedang kamu pakai. Kalau tidak ada upstream, fallback ke origin. Upstream ditentukan oleh konfigurasi branch.<name>.remote dan branch.<name>.merge.
Tiga cara integrasi
Inilah yang membedakan git pull dari git fetch: setelah data diambil, pull harus mengintegrasikannya. Ada tiga cara integrasi utama, dan pemilihannya tergantung konfigurasi atau flag yang kamu gunakan.
Fast-forward adalah default saat memungkinkan. Branch lokal bergerak maju mengikuti branch remote tanpa membuat merge commit. Ini hanya terjadi kalau local history belum divergen dari remote — artinya tidak ada commit lokal yang tidak ada di remote.
Merge dilakukan secara tradisional saat history sudah divergen. Pull membuat merge commit yang menggabungkan kedua garis history. Di sinilah merge commit "tiba-tiba muncul" yang sering bikin kaget.
Rebase dipicu oleh flag --rebase atau konfigurasi pull.rebase=true. Daripada membuat merge commit, commit lokal diputar di atas commit remote sehingga history tetap linear.
Opsi lain yang tersedia: --no-rebase (memaksa merge), --squash (merge dengan mode squash), dan --ff-only (hanya fast-forward, gagal bila divergen).
git pull
git pull origin main
git pull --rebase
git pull --no-rebase
git pull --ff-only
Untuk mengatur rebase sebagai default secara global:
git config pull.rebase true
Perbandingan Langsung: Fetch vs Pull
| Aspek | git fetch | git pull |
|---|---|---|
| Menyentuh working tree | Tidak | Ya, melalui integrasi |
| Membuat merge commit | Tidak | Bisa, saat history divergen / --no-ff |
| Bisa menimbulkan konflik | Tidak | Bisa |
| Memperbarui remote-tracking branch | Ya | Ya (karena menjalankan fetch di dalamnya) |
| Aman untuk sekadar cek | Ya | Tidak (selalu mengintegrasikan) |
Intinya sangat sederhana: git pull = git fetch + integrasi. Perbedaannya bukan di pengambilan data, tapi di apa yang terjadi setelah data diambil. Fetch berhenti setelah remote-tracking branch diperbarui. Pull melangkah lebih jauh dan mengintegrasikan perubahan ke branch yang sedang kamu pakai — dan integrasi itulah yang bisa membuat merge commit, memicu konflik, atau mengubah working tree.
Kalau kamu pernah mengalami surprise merge commit atau konflik tak terduga saat git pull, itu bukan bug — itu integrasi yang berjalan sesuai desain. Pertanyaannya adalah apakah kamu memang menginginkan integrasi itu terjadi saat itu juga.
Kapan Memakai git fetch?
Memeriksa dulu sebelum menggabungkan
Best practice yang paling direkomendasikan adalah pola "fetch dulu, periksa, baru gabung." Alih-alih langsung git pull, fetch dulu untuk memperbarui remote-tracking branch, lalu tinjau perubahannya sebelum memutuskan cara menggabungkan:
git fetch origin
git log origin/main..HEAD
git diff HEAD origin/main
git log origin/main..HEAD menampilkan commit lokal yang belum ada di remote — artinya kamu tahu apakah kamu punya pekerjaan yang belum di-push. git diff HEAD origin/main menunjukkan perbedaan file antara state lokal dan remote, sehingga kamu bisa memperkirakan apakah akan ada konflik.
Baru setelah yakin, jalankan git pull atau git merge origin/main sesuai kebutuhan. Pola ini sangat berguna saat kamu sedang mengerjakan fitur dan tidak ingin tiba-tiba kehilangan fokus karena konflik yang muncul di tengah-tengah pekerjaan.
Menjaga remote-tracking branch tetap bersih
Beberapa flag git fetch yang berguna untuk pemeliharaan:
Membersihkan branch remote yang sudah dihapus:
git fetch --prune
Alias -p juga tersedia. Ini menghapus remote-tracking branch yang sudah tidak ada di remote. Misalnya, kalau partner sudah menghapus branch feature/old-fix di remote, --prune akan membersihkan origin/feature/old-fix dari local repository-mu. Tanpa --prune, branch usang itu akan terus menumpuk.
Mengambil dari semua remote:
git fetch --all
berguna kalau repository-mu punya beberapa remote (misalnya origin dan upstream).
Mengintip branch remote tanpa mengonfigurasi remote:
git fetch git://github.com/example/repo.git feature-branch
git log FETCH_HEAD
git fetch <url> <branch> mengambil branch tertentu dari URL langsung tanpa menambahkan remote baru. Hasilnya ditulis ke .git/FETCH_HEAD, dan kamu bisa membacanya dengan git log FETCH_HEAD.
Kapan Memakai git pull?
Update langsung ke branch saat ini
Kalau kamu memang ingin mengintegrasikan perubahan ke branch saat ini — misalnya kamu di main dan ingin segera update — git pull adalah pilihan yang tepat. Tanpa argumen:
git pull
Atau eksplisit:
git pull origin main
Tapi perlu diingat: pull selalu mengintegrasikan. Kalau ada commit lokal yang belum di-push atau history sudah divergen, pull akan membuat merge commit (atau rebase tergantung config). Kalau kamu tidak ingin itu terjadi, fetch dulu dan periksa.
Pull yang aman dengan --ff-only
--ff-only membatasi integrasi hanya pada fast-forward. Kalau branch lokal sudah divergen dari remote — artinya ada commit lokal yang tidak ada di remote — perintah akan gagal, bukan diam-diam membuat merge commit.
git pull --ff-only origin main
Dari dokumentasi resmi: "git pull --ff-only will only do 'fast-forward' updates: it fails if your local branch has diverged from the remote branch."
Ini sangat penting untuk CI/automation. Di skrip, kamu tidak ingin git pull membuat merge commit diam-diam yang mengubah history. Dengan --ff-only, skrip akan gagal secara eksplisit kalau kondisinya tidak memungkinkan fast-forward — dan kamu bisa menanganinya secara terprogram.
Pull dengan --rebase untuk history linear
Kalau tim ingin menjaga history tetap rapi tanpa merge commit, git pull --rebase adalah jawabannya. Commit lokal diputar di atas commit remote, sehingga hasilnya linear seolah-olah kamu mulai mengerjakan fitur setelah commit remote terakhir.
git pull --rebase
Untuk mengatur ini sebagai default di repository-mu:
git config pull.rebase true
Beberapa tim yang memilih rebase sebagai default karena history yang lebih mudah dibaca dan di-blame. Tapi perlu diingat: rebase rewrite commit (membuat SHA baru), jadi pastikan commit yang di-rebase belum di-push ke shared branch.
Kesalahan Umum yang Harus Dihindari
Mengira git fetch memperbarui file di working directory. Tidak. Fetch hanya memperbarui remote-tracking branch (origin/main). File di working directory tidak berubah sama sekali. Kamu mungkin terlihat "tertinggal" dari remote, tapi kondisi itu justru aman — tidak ada yang berubah tanpa persetujuanmu.
Langsung git pull tanpa cek dulu. Kamu tidak tahu apa yang datang sampai kamu lihat isinya. Merge commit yang tidak diduga atau konflik bisa mengganggu alur kerja. Fetch dulu, periksa, baru putuskan.
Mengira git pull selalu hanya "update biasa." Pull mengintegrasikan, dan integrasi bisa berarti merge commit saat history divergen. Kalau kamu punya commit lokal yang belum di-push, pull akan menggabungkannya — dan kalau ada perbedaan, merge commit akan muncul.
Memakai git pull di CI tanpa --ff-only. Di pipeline otomasi, merge commit yang dibuat diam-diam oleh pull bisa mengubah output yang diharapkan. Pakai --ff-only agar operasi gagal secara eksplisit kalau kondisi tidak memungkinkan fast-forward.
Melupakan bahwa remote-tracking branch baru hasil fetch bukan branch lokal editable. Setelah fetch, kamu melihat origin/feature-baru muncul di daftar branch. Tapi itu bukan branch yang bisa langsung kamu edit. Buat branch lokal dulu dari sana.
Lupa menggabungkan dengan git stash saat ada perubahan lokal. Kalau working directory sedang kotor tapi kamu harus pull sekarang, stash perubahanmu terlebih dahulu. Polanya:
git stash push -m "WIP: export laporan"
git pull origin main
git stash pop
Cara ini memastikan perubahan lokalmu aman sebelum integrasi berjalan. Tanpa stash, pull akan menolak atau memicu konflik karena working directory tidak bersih. Kamu bisa membahas lebih lanjut tentang cara kerja stash di artikel Cara Menggunakan git stash.
Penutup
Ringkasnya: git fetch mengunduh data dan memperbarui remote-tracking branch tanpa menyentuh working tree. git pull melakukan fetch lalu mengintegrasikan hasilnya ke branch saat ini — bisa fast-forward (tanpa merge commit), merge (dengan merge commit), atau rebase (history linear) tergantung konfigurasi.
Saran praktis yang bisa kamu bawa ke aktivitas sehari-hari:
- Fetch dulu saat ragu. Pola "fetch, periksa, baru gabung" memberimu kendali penuh.
--ff-onlyuntuk update paling aman, terutama di CI/automation — gagal eksplisit daripada diam-diam membuat merge commit.--rebaseuntuk history linear kalau timmu menginginkan riwayat yang rapi.--pruneuntuk membersihkan branch usang yang sudah dihapus di remote.
Coba praktekkan langsung di repository-mu. Buat branch percobaan, jalankan fetch dan pull secara bergantian, dan amati perbedaannya pada remote-tracking branch dan working directory. Pemahaman tentang perbedaan ini akan menyelamatkanmu dari banyak kejutan yang tidak perlu.
Untuk pendalaman, dokumentasi resmi adalah rujukan terbaik: git-fetch, git-pull, dan bab Remote Branches di Pro Git Book. Kalau kamu penasaran soal merge commit yang terlanjur terbuat atau ingin memahami bagaimana cara mengubah history yang sudah ada, cek juga artikel Git Reset vs Git Revert untuk memahami kapan waktu yang tepat menulis ulang history versus menambah commit baru.
Fitur komentar belum diaktifkan oleh administrator.