Jangan Sampai Salah Pake Git Squash Kalau Kamu Mau History Git Rapi
Pernah nggak sih lagi lihat-lihat history Git di sebuah proyek, eh malah pusing sendiri? Isinya cuma commit-commit kecil kayak "fix typo", "coba lagi", "add console log", atau bahkan yang paling parah: "asdasd"? Jujur deh, pasti pernah kan nemu atau bahkan bikin history yang kayak gitu.
Git itu kan tujuannya buat nyimpen jejak perubahan kode kita secara rapi dan terorganisir. Nah, history yang berantakan itu justru bikin tujuan utama Git jadi nggak tercapai. Mau cari tahu kapan sebuah fitur ditambahkan? Bingung. Mau nyari tahu kenapa ada bug muncul setelah commit tertentu? Makin bingung. Mau balikin ke versi stabil sebelumnya? Makin ribet lagi nyari commit mana yang bener-bener stabil.
Di sinilah git squash
jadi pahlawan tanpa jubah. Git squash
itu intinya adalah cara kita buat ngegabungin beberapa commit yang berdekatan di history kita jadi satu commit tunggal yang lebih bersih dan punya arti. Bayangin aja kamu ngerjain satu fitur, tapi selama proses itu kamu bikin 10 commit kecil-kecil: "mulai bikin A", "lanjutin A", "fix bug di A", "nambahin B", "tes B", "fix lagi B", dst. Dengan git squash
, semua 10 commit itu bisa kamu gabungin jadi satu commit aja, misalnya: "feat: Implementasi fitur A dan B". Jauh lebih enak dibaca, kan?
Kenapa History Git yang Rapi Itu Penting?
Mungkin ada yang mikir, "Ah, history Git kan cuma buat saya aja, yang penting kodenya jalan." Eits, tunggu dulu. History Git yang rapi itu punya banyak manfaat, lho:
- Mempermudah Code Review: Saat teman satu tim kamu nge-review kode kamu lewat Pull Request (PR) atau Merge Request (MR), mereka akan lihat commit history kamu. Kalau history-nya berantakan, reviewer jadi susah ngikutin alur kerja kamu. Commit yang bersih dan punya makna jelas bikin reviewer lebih gampang memahami perubahan apa aja yang kamu lakukan.
- Debugging Jadi Lebih Mudah: Kalau ada bug baru muncul, kamu bisa pakai tool kayak
git bisect
. Tool ini ngebantu kamu nyari commit mana yang pertama kali memperkenalkan bug itu. Nah,git bisect
ini kerjanya nge-cek commit satu per satu. Bayangin kalau history-nya isinya commit "fix typo" semua,git bisect
jadi nggak efektif karena setiap "langkah" yang dicek itu bukan perubahan fitur yang signifikan, tapi cuma perubahan kecil yang mungkin nggak relevan sama bug-nya. History yang rapi dengan commit-commit yang merepresentasikan fitur atau perbaikan bug yang utuh bikingit bisect
jadi tool yang ampuh banget. - Mempermudah Revert: Kalau ternyata ada fitur yang baru di-merge tapi bikin masalah, kamu mungkin perlu nge-revert atau balikin perubahan itu. Kalau fitur itu diwakili oleh satu commit hasil squash, proses revert-nya gampang banget, tinggal
git revert
. Bayangin kalau fitur itu tersebar di puluhan commit, kamu harus nge-revert satu per satu, atau nyari rentang commit-nya, itu PR banget kan? - Dokumentasi Perubahan: Setiap commit itu adalah "catatan harian" project kamu. Commit message yang bagus dan history yang rapi itu jadi semacam dokumentasi informal tentang gimana project itu berkembang. Ini penting banget, apalagi kalau ada anggota tim baru yang join, mereka bisa ngikutin jejak perkembangan project lewat history Git yang rapi.
- Proyek Kelihatan Lebih Profesional: History Git yang bersih dan terorganisir mencerminkan tim yang teliti dan peduli sama kualitas, nggak cuma di kodenya tapi juga di proses pengembangannya. Ini penting kalau kamu kerja dalam tim atau bahkan di proyek open source.
Gimana Cara Pakai git squash
? Ini Dia Intinya!
Oke, sekarang kita masuk ke bagian teknisnya. Git squash
itu biasanya dilakuin barengan sama git rebase
dengan mode interaktif (-i
). Kenapa interaktif? Karena kita perlu "ngasih tahu" Git, commit mana aja yang mau kita gabungin dan gimana cara ngegabunginnya.
Perintah dasarnya gini:
bash
git rebase -i HEAD~N
Atau:
bash
git rebase -i
Penjelasannya:
git rebase -i
: Ini perintah buat memulai rebase interaktif.HEAD~N
: Artinya kamu mau nge-rebaseN
commit terakhir dari posisiHEAD
kamu sekarang. Misalnya, kalau kamu mau nge-squash 5 commit terakhir, kamu pakaiHEAD~5
.
: Kamu mau nge-rebase commit mulai dari commit setelah commit dengan hash ini, sampai posisi HEAD
kamu sekarang. Ini lebih fleksibel karena kamu bisa milih titik awal rebase-nya di commit mana aja, nggak cuma dari HEAD
. Cara paling umum adalah nyari hash commit sebelum* rentang commit yang mau kamu squash.
Setelah kamu jalanin perintah itu, Git bakal nampilin editor teks (tergantung setting Git kamu, bisa Nano, Vim, VS Code, atau yang lain) yang isinya daftar commit yang bakal di-rebase, dari yang paling tua di atas sampe yang paling baru di bawah. Contoh tampilannya kira-kira kayak gini:
pick a1b2c3d commit pertama (yang paling tua di rentang ini)
pick e4f5g6h commit kedua
pick i7j8k9l commit ketiga
pick m0n1o2p commit keempat (yang paling baru)Rebase a1b2c3d..m0n1o2p onto a1b2c3d (4 commands)
# Commands:
p, pick = use commit
r, reword = use commit, but edit the commit message
e, edit = use commit, but stop for amending
s, squash = use commit, but meld into previous commit
f, fixup = like "squash", but discard this commit's log message
x, exec = run command (the rest of the line) using shell
d, drop = remove commit
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Di bagian atas itu daftar commit-nya. Setiap baris diawali dengan kata kunci (pick
secara default), diikuti hash commit, dan commit message-nya. Di bagian bawah ada penjelasan tentang perintah-perintah yang bisa kamu pakai.
Nah, di sini kita akan fokus ke pick
, squash
(s
), dan fixup
(f
).
pick
: Artinya "ambil" commit ini apa adanya. Commit pertama di daftar wajib* kamu biarin pick
. Commit inilah yang nantinya bakal jadi dasar atau tempat commit-commit lain digabungin. squash
(s
): Artinya "gabungkan" commit ini ke commit sebelumnya. Commit message dari commit ini akan* dimunculkan di editor nanti, barengan sama commit message dari commit yang di-squash ke dalamnya. Kamu bisa gabungin atau edit commit messagenya. fixup
(f
): Sama kayak squash
, artinya "gabungkan" commit ini ke commit sebelumnya. Bedanya, commit message dari commit ini akan dibuang*. Ini cocok buat commit-commit kecil kayak "fix typo" yang commit message-nya nggak perlu disimpan.
Contoh Skenario:
Misal kamu punya history kayak gini (dari yang terbaru ke terlama):
m0n1o2p add validation on form
i7j8k9l fix button alignment
e4f5g6h refactor form component
a1b2c3d initial form structure
Kamu mau ngegabungin fix button alignment
dan add validation on form
ke commit refactor form component
, karena ketiganya masih related sama pengerjaan form.
- Kamu perlu tahu commit sebelum rentang yang mau kamu squash. Dalam contoh ini, commit
initial form structure
(hasha1b2c3d
) adalah commit sebelumrefactor form component
. Jadi, perintah rebase-nya:
bash
git rebase -i a1b2c3d
Atau kalau kamu mau nge-squash 3 commit terakhir, kamu bisa pakai git rebase -i HEAD~3
. Hasil di editor akan sama (mulai dari refactor form component
).
- Editor bakal muncul. Daftar commit-nya (dari atas ke bawah, paling tua ke paling baru) akan kayak gini:
pick e4f5g6h refactor form component
pick i7j8k9l fix button alignment
pick m0n1o2p add validation on form
- Kamu mau ngegabungin commit kedua (
fix button alignment
) dan ketiga (add validation on form
) ke commit pertama (refactor form component
). Caranya, ganti kata kuncipick
di baris kedua dan ketiga jadisquash
ataufixup
. Kalau kamu mau commit messagenya ikut digabungin (nanti bisa diedit), pakaisquash
. Kalau commit message-nya nggak penting (misal cuma "fix doang"), pakaifixup
. Anggap kita pakaisquash
untuk kedua-duanya:
pick e4f5g6h refactor form component
s i7j8k9l fix button alignment
s m0n1o2p add validation on form
- Simpan dan tutup editor. Git akan mulai proses rebase. Karena kamu pakai
squash
, Git akan nampilin editor lain buat kamu nulis commit message baru untuk commit hasil squash. Editor itu bakal ngasih template yang isinya gabungan commit message dari ketiga commit tadi:
# This is a combination of 3 commits.
# The first commit's message is:refactor form component# This is the 2nd commit message:fix button alignment# This is the 3rd commit message:add validation on form
- Sekarang tugas kamu adalah edit pesan ini jadi satu commit message yang representatif untuk gabungan ketiga commit tersebut. Hapus baris-baris yang nggak perlu (yang diawali
#
itu otomatis diabaikan, tapi bagusnya dirapihin). Misalnya, kamu bisa ganti isinya jadi gini:
refactor: Refactor form component and add validation
Ini jauh lebih informatif daripada tiga commit terpisah, kan?
- Simpan dan tutup editor commit message. Git akan menyelesaikan rebase-nya.
Sekarang, kalau kamu lihat history Git kamu, tiga commit yang tadi (refactor, fix button, add validation) sudah hilang, digantikan oleh satu commit baru dengan hash yang berbeda dan commit message yang baru kamu tulis. History kamu jadi lebih rapi!
Kapan Sebaiknya Pakai git squash
?
Ada beberapa skenario ideal buat pakai git squash
:
- Sebelum Membuat Pull Request/Merge Request: Ini waktu yang paling umum dan disarankan. Sebelum kamu minta tim kamu nge-review dan nge-merge cabang fitur kamu ke cabang utama (misal
develop
ataumain
), rapihin dulu history di cabang fitur kamu. Gabungin commit-commit kecil yang related jadi satu atau beberapa commit yang lebih besar dan punya makna. Ini bikin reviewer lebih gampang paham apa yang kamu lakukan. - Membersihkan History Lokal: Kalau kamu lagi ngerjain sesuatu di cabang lokal kamu sendiri dan bikin banyak commit "work-in-progress" atau "just trying things", kamu bisa nge-squash commit-commit itu jadi satu atau beberapa commit yang lebih rapi sebelum kamu publish (push) cabang itu.
Menggabungkan Perbaikan Kecil ke Commit Sebelumnya: Kalau kamu baru push commit yang isinya fitur, eh nggak lama sadar ada typo atau bug kecil yang perlu diperbaiki segera* dan perbaikannya cuma 1-2 baris. Kamu bisa bikin commit perbaikannya, lalu pakai rebase interaktif dan fixup
commit perbaikan itu ke commit fitur sebelumnya. Hasilnya, seolah-olah perbaikan itu sudah ada di commit fitur dari awal. Caranya: bikin commit perbaikan -> cari hash commit fitur sebelumnya -> git rebase -i^
(tanda ^
artinya parent dari commit itu) -> ganti pick
commit perbaikan jadi f
atau fixup
di bawah commit fitur -> simpan.
- Merapikan History Hasil Kerja Sama: Kalau kamu kerja bareng di cabang yang sama dengan orang lain, dan kalian bikin banyak commit, kadang history-nya bisa campur aduk.
git squash
bisa membantu merapikan ini, tapi hati-hati ya, ada risikonya kalau branch-nya sudah di-push dan di-pull sama orang lain (akan dibahas di bagian "Jangan Sampai Salah Pake").
Kapan Sebaiknya Tidak Pakai git squash
?
Ini penting banget! Ada situasi di mana nge-squash itu malah bikin masalah:
Di Commit yang Sudah Dipublikasikan dan Dipakai Orang Lain: Ini aturan emas dalam Git: Jangan pernah mengubah history yang sudah di-push ke remote dan sudah di-pull sama anggota tim lain, kecuali kamu benar-benar tahu apa yang kamu lakukan dan sudah komunikasi dengan tim. git rebase -i
(yang dipakai buat squash) itu mengubah history (hash commit-nya berubah). Kalau kamu push perubahan history ini (git push --force
atau git push --force-with-lease
), anggota tim lain yang sudah punya history lama bakal bingung. Mereka perlu melakukan langkah-langkah pemulihan yang kadang ribet. Jadi, kalau branch-nya sudah dipakai ramai-ramai, pikir dua kali. Squash paling aman dilakukan di branch lokal kamu sebelum di-push, atau di branch fitur yang baru di-push tapi belum* di-pull sama siapa-siapa (risikonya lebih kecil).
- Di Cabang Utama (main/develop): Jangan pernah nge-rebase atau nge-squash commit yang sudah ada di cabang utama (seperti
main
,master
,develop
). Cabang ini adalah "kebenaran" history proyek. Mengubah history di sini bisa bikin kacau balau bagi semua orang yang kerja di proyek itu. - Kalau Setiap Commit Punya Makna Historis Independen: Kadang ada kasus di mana setiap langkah dalam history itu penting untuk didokumentasikan sebagai commit terpisah. Contoh: commit yang menambahkan fitur, commit yang menambahkan test untuk fitur itu, commit yang memperbaiki bug critical yang baru ditemukan. Kalau setiap commit punya makna penting yang berdiri sendiri dan kamu ingin history merekam langkah-langkah itu secara detail, maka jangan di-squash.
Tips dan Best Practices Saat Menggunakan git squash
Supaya proses nge-squash kamu lancar dan efektif, perhatikan tips ini:
- Squash Dini, Squash Sering (di Cabang Lokal): Jangan nunggu sampai 50 commit di branch lokal baru dirapiin. Biasain nge-squash secara berkala saat ngerjain fitur. Begitu ngerasa ada serangkaian commit kecil yang bisa digabungin jadi satu langkah logis, langsung rebase interaktif dan squash.
- Pilih Titik Awal Rebase yang Tepat: Gunakan
git log
untuk melihat history dan cari hash commit sebelum commit pertama yang mau kamu sertakan dalam rebase. Ini penting supaya kamu nggak salah nge-rebase terlalu jauh atau terlalu dekat. - Gunakan
squash
vsfixup
dengan Bijak:squash
kalau kamu mau menggabungkan commit message-nya dan bikin pesan baru yang lebih komprehensif.fixup
kalau commit message-nya nggak penting sama sekali (misal: "fix typo", "lagi", "hapus console log"). Ini bikin proses editing commit message baru nanti jadi lebih cepet. - Buat Commit Message yang Bagus: Ini krusial! Commit message dari commit hasil squash harus menggambarkan keseluruhan perubahan yang kamu lakukan. Jangan cuma ngambil salah satu commit message dari yang digabungin. Tulis dengan jelas fitur apa yang ditambahin, bug apa yang diperbaiki, atau refactor apa yang dilakukan. Gunakan format yang konsisten (misalnya Conventional Commits) kalau tim kamu punya standar.
- Preview Sebelum Push: Setelah rebase dan squash selesai, cek lagi history-nya pakai
git log --oneline --graph
. Pastikan hasilnya sesuai sama yang kamu mau sebelum di-push ke remote. - Hati-hati dengan Conflicts: Proses rebase bisa menimbulkan konflik kalau perubahan yang kamu lakukan di commit-commit yang di-rebase itu tumpang tindih. Kalau muncul konflik, Git akan berhenti dan minta kamu menyelesaikan konfliknya secara manual, sama kayak waktu
git merge
konflik. Selesaikan konfliknya,git add
file yang konfliknya udah beres, lalu lanjutin rebase-nya pakaigit rebase --continue
. Kalau nyerah, bisagit rebase --abort
. - Pahami
git push --force-with-lease
: Kalau memang terpaksa harus nge-force push history yang sudah di-publish (misal: baru push branch fitur, eh langsung sadar history-nya berantakan dan belum di-pull orang lain), pakaigit push --force-with-lease
bukangit push --force
.force-with-lease
itu lebih aman karena dia akan gagal kalau ternyata history remote sudah berubah sejak terakhir kamu pull, menandakan ada orang lain yang mungkin sudah push ke branch itu. Ini mencegah kamu menimpa kerjaan orang lain secara nggak sengaja. Tapi tetap aja, cara terbaik adalah komunikasi! - Manfaatkan Fitur Platform Git (GitHub, GitLab, Bitbucket): Kebanyakan platform Git modern punya opsi merge yang bisa otomatis nge-squash semua commit dari branch fitur jadi satu commit di branch target saat Pull Request/Merge Request di-merge. Ini juga cara yang efektif, tapi bedanya, proses squashingnya dilakuin saat merge, bukan saat kamu ngerapihin branch fitur kamu. Kamu bisa diskusikan dengan tim mana strategi yang paling cocok. Ada tim yang lebih suka history di branch fitur rapi dulu baru di-merge (manual squash + merge --no-ff), ada yang prefer otomatis di-squash saat merge.
Alternatif Singkat: git merge --squash
Selain pakai git rebase -i
, ada juga cara lain buat nge-squash, yaitu pakai git merge --squash
. Perintahnya gini:
bash
Pastikan kamu ada di branch target (misal: develop)
git checkout developJalankan merge dengan opsi --squash dari branch fitur
git merge --squash nama-branch-fiturGit akan menggabungkan semua perubahan dari branch fitur
ke working directory kamu, tapi belum bikin commit.Lakukan commit manual
git commit -m "feat: Nama fitur yang di-merge"
Bedanya apa sama git rebase -i
? git rebase -i
mengubah history commit di branch fitur* kamu. Commit-commit lamanya hilang diganti commit baru. git merge --squash
tidak mengubah history di branch fitur kamu. Dia cuma mengambil perubahan akhir dari branch fitur, menaruhnya di working directory branch target, dan kamu bikin satu commit baru* di branch target yang berisi semua perubahan itu. History di branch fitur tetap utuh.
git merge --squash
ini kadang dipakai kalau kamu mau nge-merge branch fitur tapi history-nya memang nggak perlu dirapihin di branch fiturnya, atau kalau history branch fiturnya terlalu kompleks untuk di-rebase interaktif, atau kalau kamu memang mau history di branch fitur tetap ada apa adanya tapi di branch utama cuma ada satu commit summary. Tapi, untuk membersihkan history di branch kamu sendiri sebelum di-merge, git rebase -i
adalah tool utamanya.
Kesimpulan
Menggunakan git squash
melalui git rebase -i
itu skill penting banget buat setiap developer yang kerja dalam tim atau di proyek yang punya history panjang. Ini bukan cuma soal "rapi-rapiin" history, tapi lebih ke bikin history Git kamu jadi bermanfaat sebagai alat bantu kerja: mempermudah review, debugging, revert, dan dokumentasi.
Memang awalnya mungkin terasa agak ribet atau bahkan sedikit menakutkan karena kamu mengubah history. Tapi percaya deh, setelah terbiasa, ini bakal jadi salah satu tool favorit kamu di Git. Mulai dari mencoba di branch lokal yang nggak penting, atau di branch fitur kamu sebelum dipush. Biasakan diri dengan editor rebase-nya, pahami bedanya squash
dan fixup
, dan yang paling penting, jangan pernah ragu untuk git rebase --abort
kalau kamu merasa ada yang salah atau bingung.
Ingat aturan emasnya: jangan nge-squash history yang sudah di-publish dan kemungkinan sudah di-pull sama orang lain. Lakukan squash di branch lokal atau branch fitur kamu sebelum proses review/merge. Dengan latihan dan pemahaman yang benar, git squash
bakal bantu kamu (dan tim kamu) punya history Git yang nggak cuma rapi, tapi juga informatif dan fungsional. Selamat mencoba dan semoga history Git kamu selalu bersih kayak baru dicuci!