Chapter sebelumnya meninggalkan satu keadaan terbuka: fitur-latihan sudah selesai dikerjakan, tetapi main masih tertinggal dua commit. Menggabungkan pekerjaan kembali ke jalur utama itulah merge. Ada dua wujud merge di Git, dan nasib sebuah penggabungan ditentukan oleh satu pertanyaan geometris: apakah kedua penunjuk masih berada pada satu garis lurus? Chapter ini mengupas jawaban “ya” — kondisi fast-forward, ketika merge bahkan tidak membuat commit baru, hanya menarik penunjuk ke depan — lengkap dengan bukti nyatanya, termasuk bagaimana --ff-only menolak keras ketika syaratnya tidak terpenuhi.
Skenario: main Diam, fitur Maju #
Repository latihan menempuh pola yang sama dengan workflow fitur sesungguhnya: cabang dari main, kerjakan sampai tuntas, sementara main tidak menerima commit apa pun:
mkdir latihan-ff && cd latihan-ff
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Situs\nberanda\n' > situs.md
git add situs.md
git commit -m "Buat halaman beranda"
printf '# Situs\nberanda\ntentang\n' > situs.md
git add situs.md
git commit -m "Tambah halaman tentang"
git switch -c fitur-kontak
printf '# Situs\nberanda\ntentang\nkontak\n' > situs.md
git add situs.md
git commit -m "Tambah halaman kontak"
printf '[email protected]\n' > email.txt
git add email.txt
git commit -m "Tambah alamat email"
git switch mainOutput yang Dihasilkan (perintah git switch main):
Switched to branch 'main'Posisi kedua penunjuk sebelum penggabungan:
git branch -vOutput yang Dihasilkan:
fitur-kontak 0cac5e8 Tambah alamat email
* main 1fc8151 Tambah halaman tentangBentuknya persis diagram penunjuk chapter Branch dan Commit
: satu rantai lurus, fitur-kontak dua commit di depan main, tidak ada satu pun commit di sisi main sejak percabangan. Inilah prasyarat fast-forward.
Merge Tanpa Commit Baru #
Dari main — branch yang ingin menerima pekerjaan — kita jalankan merge:
git merge fitur-kontakOutput yang Dihasilkan:
Updating 1fc8151..0cac5e8
Fast-forward
email.txt | 1 +
situs.md | 1 +
2 files changed, 2 insertions(+)
create mode 100644 email.txtBaris Updating 1fc8151..0cac5e8 menyatakan rentang yang dilalui: dari posisi lama main ke posisi fitur-kontak. Kata Fast-forward adalah pengumuman strateginya: tidak ada commit penggabung yang dibuat, karena tidak diperlukan. Baris-baris berikutnya adalah diffstat rangkuman — satu suntingan pada situs.md dan satu berkas baru email.txt — keluaran standar yang sudah akrab dari chapter git log
.
Bukti Tiada Commit Merge #
Klaim “hanya penunjuk yang bergerak” wajib dibuktikan, dan buktinya tiga lapis. Pertama, riwayat main kini identik dengan fitur-kontak:
git log --oneline mainOutput yang Dihasilkan:
0cac5e8 Tambah alamat email
286d33b Tambah halaman kontak
1fc8151 Tambah halaman tentang
da9030a Buat halaman berandagit log --oneline fitur-kontakOutput yang Dihasilkan:
0cac5e8 Tambah alamat email
286d33b Tambah halaman kontak
1fc8151 Tambah halaman tentang
da9030a Buat halaman berandaKedua daftar itu salinan kata-demi-kata; tidak ada baris tambahan bertuliskan “Merge …” di mana pun. Kedua, kedua penunjuk kini berdiri di hash yang persis sama:
git rev-parse main fitur-kontakOutput yang Dihasilkan:
0cac5e8b99a74e6ed1c7c79a1c5ba19c2afa9d5c
0cac5e8b99a74e6ed1c7c79a1c5ba19c2afa9d5cKetiga, git branch -v dan graf riwayat menutup pembuktian:
git branch -vOutput yang Dihasilkan:
fitur-kontak 0cac5e8 Tambah alamat email
* main 0cac5e8 Tambah alamat emailgit log --oneline --graphOutput yang Dihasilkan:
* 0cac5e8 Tambah alamat email
* 286d33b Tambah halaman kontak
* 1fc8151 Tambah halaman tentang
* da9030a Buat halaman berandaGraf tetap garis lurus — tidak ada huruf | percabangan yang menjadi tanda khas merge commit, karena memang tidak ada commit baru yang lahir. Sebelum dan sesudah merge, perbedaannya hanya posisi satu berkas kecil:
Hash pada diagram milik mesin uji dan akan berbeda di mesin pembaca, tetapi aksinya sama: main ditarik maju mengikuti rantai yang sudah tersedia. Merge semurah itu karena tidak ada objek yang digandakan — fast-forward sesungguhnya adalah pemindahan satu penunjuk 41 byte.
–ff-only: Menolak Ketika Riwayat Menyimpang #
Fast-forward hanya mungkin pada garis lurus. Sekarang kita rusak syaratnya dengan sengaja: cabang baru dari main yang sudah maju, lalu kedua sisi sama-sama maju:
git switch -c fitur-galeri
printf '# Situs\nberanda\ntentang\nkontak\ngaleri\n' > situs.md
git add situs.md
git commit -m "Tambah halaman galeri"
git switch main
printf '# Situs\nberanda\ntentang\nkontak\nfaq\n' > situs.md
git add situs.md
git commit -m "Tambah halaman faq"Output yang Dihasilkan (perintah git switch main):
Switched to branch 'main'Kedua penunjuk kini sama-sama maju dari titik percabangan — riwayat menyimpang. Perintah yang sama sekalian dengan syarat eksplisit:
git merge --ff-only fitur-galeriOutput yang Dihasilkan:
hint: Diverging branches can't be fast-forwarded, you need to either:
hint:
hint: git merge --no-ff
hint:
hint: or:
hint:
hint: git rebase
hint:
hint: Disable this message with "git config advice.diverging false"
fatal: Not possible to fast-forward, aborting.Git menolak: fatal: Not possible to fast-forward, aborting. Nasihat di atasnya menyebut dua jalan keluar resmi — git merge --no-ff yang tetap menggabungkan (materi chapter berikutnya), atau git rebase yang merapikan posisi commit sebelum digabungkan, dibahas di chapter Rebase vs Merge
. Tanpa --ff-only, git merge di kondisi menyimpang memilih sendiri jalannya: membuat commit penggabung — dan itulah topik chapter berikutnya.
Fast-forward menjawab kasak-kusuk garis lurus. Namun tim sungguhan jarang seberuntung itu — main terus bergerak selagi fitur dikerjakan, dan pertemuan dua riwayat yang menyimpang menuntut jenis merge yang membuat commit baru dengan dua parent. Mekanisme itu bernama three-way merge: Three-Way Merge
.