Belajar Memakai Git Rebase


Fasilitas rebase di Git dapat dipakai untuk memodifikasi riwayat commit yang sudah ada. Sebagai contoh, rebase dapat dipakai untuk menggantikan merge. Walaupun memberikan hasil yang sama, keduanya memiliki ‘efek samping’ yang berbeda. Operasi merge akan menghasilkan commit baru sementara rebase tidak! Dengan demikian, rebase menghasilkan riwayat yang lebih rapi tanpa percabangan. Walaupun demikian, rebase sebaiknya tidak dipakai bila branch sudah dipublikasikan dan dipakai oleh orang lain. Operasi rebase biasanya hanya untuk merapikan branch yang masih di komputer lokal dan belum dipublikasikan ke server Git.

Untuk menunjukkan penggunaan rebase, anggap saja saya sedang mengerjakan sebuah proyek yang sudah mencapai versi 0.8 dimana isi branch master terlihat seperti pada gambar berikut ini:

Kondisi awal riwayat commit

Kondisi awal riwayat commit

Setelah merilis versi tersebut, saya kemudian membuat sebuah branch baru yang mewakili versi 0.9. Tidak lupa saya juga melakukan merge untuk branch lama ke master. Setelah itu, saya melakukan beberapa perubahan baru untuk versi terbaru (0.9) seperti yang terlihat pada gambar berikut ini:

Membuat branch baru dari master

Membuat branch baru dari master

Pada saat sedang mengembangkan fitur yang dijadwalkan untuk 0.9, saya memperoleh permintaan untuk menyelesaikan kesalahan yang ada di versi 0.8. Karena proritasnya sangat tinggi, saya harus menyelesaikan perubahan pada versi 0.8.1 dan menunda perubahan pada versi 0.9. Saya melakukan cukup banyak perubahan sehingga alur history saya terlihat seperti berikut ini:

Melakukan perubahan pada branch lama

Melakukan perubahan pada branch lama

Sekarang, setelah satu minggu berlalu, saya ingin lanjut mengerjakan apa yang tertunda di branch untuk versi 0.9. Tapi saya sudah melakukan banyak perubahan di versi 0.8 yang sudah di-merge ke branch master. Sementara itu, branch untuk versi 0.9 saat ini masih tetap berisi kode program lama sebelum perubahan versi 0.8.1 ke atas. Untuk memperbaharui branch versi 0.9 agar merujuk pada kode program terbaru di master, saya dapat menggunakan perintah seperti berikut ini:

$ git checkout develop_0.9
Switched to branch 'develop_0.9'

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Set versions to 0.9
Using index info to reconstruct a base tree...
M       application.properties
Falling back to patching base and 3-way merge...
Auto-merging application.properties
CONFLICT (content): Merge conflict in application.properties
Failed to merge in the changes.
Patch failed at 0001 Set versions to 0.9
The copy of the patch that failed is found in:
   c:/test/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

Pesan kesalahan di atas adalah jenis pesan kesalahan yang umum muncul bila terjadi konflik file yang tidak dapat diselesaikan secara otomatis. Yang perlu saya lakukan adalah mengubah file yang bermasalah dan melanjutkan proses rebase seperti yang terlihat pada perintah berikut ini:

$ vi application.properties

$ git add application.properties

$ git rebase --continue
Applying: Set versions to 0.9
Applying: Use c3p0 connection pool.

Sekarang, riwayat akan terlihat seperti pada gambar berikut ini:

Riwayat commit setelah rebase

Riwayat commit setelah rebase

Seluruh perubahan yang saya lakukan di master kini juga muncul di branch untuk versi 0.9. Riwayat terlihat kembali lurus sehingga terlihat rapi.

Sebagai perbandingan, selain memakai rebase, saya juga dapat memakai merge untuk mencapai hasil yang sama, misalnya dengan perintah seperti berikut ini:

$ git merge master
Auto-merging application.properties
CONFLICT (content): Merge conflict in application.properties
Automatic merge failed; fix conflicts and then commit the result.

$ vi application.properties

$ git commit -a -m 'Setelah perubahan 0.8.1'
[develop_0.9 e61a379] Setelah perubahan 0.8.1

Hasil dari merge adalah history seperti pada gambar berikut ini:

Riwayat commit setelah merge

Riwayat commit setelah merge

Terlihat bahwa bila saya memakai merge, commit yang sudah ada untuk branch 0.9 tidak berubah sama sekali. Yang ada adalah commit baru ditambahkan pada branch ini kemudian selisihnya (delta perubahan atau diff) diberikan sebagai sebuah commit baru. Terlihat bahwa penggunaan merge membuat history menjadi tidak rapi lagi, tapi tepat dipakai bila commit yang sudah ada tidak boleh diubah lagi (misalnya telah digunakan oleh developer lagi).

Fungsi lain dari rebase adalah merapikan riwayat commit yang ada, misalnya menghapus commit yang sudah dibuat. Karena Git menyimpan setiap commit sebagai delta dari commit sebelumnya dalam bentuk tree, maka tentu saja saya tidak bisa leluasa menghapus sebuah commit di posisi mana saja sesuka hati (karena setiap commit selalu berhubungan dengan commit sesudahnya). Sebagai contoh, saya memiliki riwayat seperti yang terlihat pada gambar berikut ini:

Kondisi awal riwayat history

Kondisi awal riwayat history

Bila saya ingin menggabungkan 9 commit terakhir menjadi sebuah commit tunggal, maka saya dapat memberikan perintah seperti berikut ini:

$ git rebase -i HEAD~10

Saya kemudian mengubah isi file yang muncul menjadi seperti yang terlihat pada gambar berikut ini:

reword f64b06f Set versions to 0.8.2
fixup 6b5e3cb Change invoice's layout.
fixup 368e0af Add sales report for every products.
fixup 494c91f Add vertical stretch when overflow for product's name.
fixup 0fd37c0 Allow filtering receivable report by invoice periods and region.
fixup 5036f32 Fixes product's quantity with zero value was displayed.
fixup eabcf75 Add warehouse name to report.
fixup 830e5f9 Minor changes to layout.
fixup b46d934 Add line separator.
fixup 68384e9 Sort report data.

Pada file tersebut, saya memilih reword untuk mengubah pesan commit dan fixup untuk menggabungkan sebuah commit dengan commit di atasnya. Selain kedua perintah tersebut, saya juga dapat memberikan perintah lain seperti pick untuk tidak melakukan perubahan, edit untuk mengubah perubahan yang dilakukan oleh commit tersebut, squash yang bekerja seperti fixup dimana saya bisa mengisi pesan commit baru, dan exec untuk mengerjakan perintah shell. Saya juga bisa menghapus sebuah commit dengan menghapus baris yang mewakili commit tersebut.

Setelah menyimpan file di atas, proses rebase akan dimulai. Karena saya mengisi reword pada commit terakhir, maka sebuah editor kembali muncul untuk menanyakan pesan commit terbaru. Saya pun mengisi nama pesan commit baru dan menyimpan file. Setelah proses rebase selesai, saya akan menemukan riwayat seperti yang terlihat seperti pada gambar berikut ini:

Kondisi riwayat commit setelah rebase interaktif yang memakai perintah reword dan fixup

Kondisi riwayat commit setelah rebase interaktif yang memakai perintah reword dan fixup

Seluruh perubahan yang saya lakukan sudah digabungkan menjadi sebuah commit tunggal.

Bagaimana bila saya membuat kesalahan pada saat melakukan rebase? Salah satu fasilitas dari Git adalah setiap kali terdapat perubahan posisi terakhir dari sebuah branch, posisi tersebut akan disimpan pada reflog. Secara default, perintah git gc hanya akan menghapus reflog yang sudah lebih dari 90 hari. Jadi, terdapat peluang sangat besar untuk memperbaiki kesalahan rebase yang baru saja dilakukan.

Untuk melihat informasi reflog, saya memberikan perintah seperti berikut ini:

$ git reflog

Setelah menentukan posisi branch yang benar (seperti HEAD@{1} dan sebagainya), saya kemudian memberikan perintah berikut ini untuk mengembalikan branch tersebut ke kondisi yang diharapkan:

$ git reset --hard HEAD@{1}

Perintah di atas akan mengembalikan posisi branch saat ini ke posisi yang telah ditentukan. Commit yang sudah dihapus dan digabungkan tetap akan dikembalikan seperti semula.

Perihal Solid Snake
I'm nothing...

One Response to Belajar Memakai Git Rebase

  1. Nurul Huda Mustaqim mengatakan:

    amazing, ini yang saya cari

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: