Chapter Three-Way Merge menutup satu keadaan yang familiar: main maju selagi fitur dikerjakan, dan penggabungannya melahirkan commit merge berparent dua. Riwayat hasilnya jujur — percabangan terlihat apa adanya — tetapi graf yang terus bertambah percabangan juga makin sulit dibaca, apalagi saat git log dipakai untuk menelusuri satu baris fitur menembus belasan merge. Ada satu jalan lain: rebase. Alih-alih menggabungkan dua sejarah, rebase memindahkan serangkaian commit ke basis baru — commit-commit fitur “dipelajari ulang” satu per satu di atas ujung main seolah-olah fitur baru mulai dikerjakan kemarin. Chapter ini membuktikan mekanisme itu dengan mata telanjang: hash lama disimpan, rebase dijalankan, hash baru dibandingkan.

Skenario: main Maju Selagi fitur Dikerjakan #

Repository latihan sengaja dibuat menyimpang — bentuk yang sama dengan skenario three-way merge, hanya saja jalannya kita belokkan dari merge:

bash
mkdir latihan-konsep && cd latihan-konsep
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Catatan\nhalo\n' > catatan.md
git add catatan.md
git commit -m "Tulis catatan pertama"
git switch -c fitur
printf 'langkah 1\n' > langkah.md
git add langkah.md
git commit -m "Catat langkah pertama"
printf 'langkah 1\nlangkah 2\n' > langkah.md
git add langkah.md
git commit -m "Catat langkah kedua"
git switch main
printf '# Catatan\nhalo\ndunia\n' > catatan.md
git add catatan.md
git commit -m "Tambah salam dunia"
git switch fitur

Kedua branch sama-sama maju satu langkah dari titik percabangan. Graf sebelum rebase terlihat seperti ini:

bash
git log --oneline --graph --all

Output yang Dihasilkan:

text
* 37c5134 Tambah salam dunia
| * 2ce0d9b Catat langkah kedua
| * 0b9cdd8 Catat langkah pertama
|/  
* 896c706 Tulis catatan pertama

Baris teratas adalah ujung main — “Tambah salam dunia”; di bawahnya dua commit milik fitur masih menempel pada “Tulis catatan pertama”. Inilah dasar lama tempat commit fitur berdiri.

Menjalankan Rebase dan Membuktikan Hash Berubah #

Sebelum menyentuh apa pun, kita simpan dulu hash kedua commit fitur ke sebuah berkas — bukti yang akan diadu sesudah rebase:

bash
git rev-parse HEAD HEAD~1 > hash-lama.txt

Lalu perintah intinya — dijalankan dari branch fitur, menyebut basis barunya main:

bash
git rebase main

Output yang Dihasilkan:

text
Successfully rebased and updated refs/heads/fitur.

Satu baris, tetapi di baliknya Git barusan menyalin ulang dua commit fitur ke atas ujung main. Buktinya: isi hash-lama.txt dibandingkan dengan hash yang sekarang ditunjuk fitur:

bash
cat hash-lama.txt

Output yang Dihasilkan:

text
2ce0d9b973e771e0aea114f5cfdf4572ad75a219
0b9cdd89582f279813c2c147995c656889c0e633
bash
git rev-parse HEAD HEAD~1

Output yang Dihasilkan:

text
7d6fd42463615e9b59a6973a4dcdb8c8b39fb6fb
31c02fb84f546468348e9eab6f15024c2e48f288

Kedua hash berubah total — padahal tidak ada satu baris pun berkas yang kita sunting. Rebase tidak “memindahkan” objek commit lama; ia membuat commit baru yang berisi snapshot yang sama lalu menuntun rantai parent-nya ke basis baru. Commit lama (0b9cdd8 dan 2ce0d9b) masih tersimpan di database objek, hanya saja tidak lagi dijangkau branch mana pun. Prinsip ini adalah kunci seluruh section: rebase adalah alat menulis ulang riwayat, bukan sekadar memindah label.

Riwayat fitur Kini Berdiri di Atas main #

Graf setelah rebase menunjukkan hasil akhirnya:

bash
git log --oneline --graph --all

Output yang Dihasilkan:

text
* 7d6fd42 Catat langkah kedua
* 31c02fb Catat langkah pertama
* 37c5134 Tambah salam dunia
* 896c706 Tulis catatan pertama

Dua jalur menyatu menjadi satu garis lurus: “Tambah salam dunia” kini menjadi parent dari “Catat langkah pertama”. Kedudukan itu bisa diperiksa langsung — kakek dari ujung fitur harus tepat berada di ujung main:

bash
git rev-parse HEAD~2 main

Output yang Dihasilkan:

text
37c5134b93ef0fbe889d88aaaff8b8eb1cdd833d
37c5134b93ef0fbe889d88aaaff8b8eb1cdd833d

Dua nama berbeda, satu hash sama: fitur~2 adalah main. Sedangkan isi pekerjaan tidak tersentuh — langkah.md utuh dua barisnya:

bash
cat langkah.md

Output yang Dihasilkan:

text
langkah 1
langkah 2

Sebelum dan sesudahnya dapat dilihat berdampingan di bawah ini; perhatikan hash fitur yang berubah sementara hash main tidak:

Hash pada diagram milik mesin uji dan akan berbeda di mesin pembaca, tetapi aksinya identik: dua commit fitur dipindahkan dari dasar lama ke dasar baru dengan identitas hash baru.

Rebase Menulis Ulang, Merge Menggabungkan #

Beda fundamental dua alat ini perlu ditegakkan sejak awal. Merge bekerja pada dua sejarah sekaligus: ia membaca ujung kedua sisi, membuat satu commit penggabung berparent dua, dan kedua sejarah asli tetap utuh tanpa diubah — tidak ada hash yang berubah. Rebase bekerja pada satu sejarah saja: sejarah fitur disalin ulang commit demi commit ke basis baru, hash lama diganti hash baru, dan sejarah main tidak tersentuh. Merge menghasilkan graf yang jujur bercabang; rebase menghasilkan graf yang seolah-olah percabangan tak pernah terjadi.

Dokumentasi resmi Pro Git memperlihatkan diagram konsep yang sama pada bab Git Branching – Rebasing . Konsepnya sudah di tangan; chapter berikutnya membahas perintahnya secara penuh — sintaks inti, basis origin/main, hingga --onto: git rebase .