Ups Salah Commit di Git? Jangan Panik, Gini Caranya Balik Lagi

Ups Salah Commit di Git? Jangan Panik, Gini Caranya Balik Lagi
Photo by Yancy Min / Unsplash

Pernah nggak sih lagi asyik-asyiknya ngoding, terus buru-buru git add . dan git commit -m "Fix bug" eh pas dilihat lagi, ternyata ada file yang belum selesai diubah, atau pesan commit-nya typo, atau bahkan salah nge-commit sesuatu yang nggak seharusnya? Tenang, kamu nggak sendirian. Itu kejadian yang super umum di dunia per-Git-an. Rasanya kayak udah lari kenceng terus nabrak tembok, panik dikit, tapi untungnya Git itu kayak mesin waktu mini buat kode kita. Ada cara buat balik lagi kok.

Intinya, kamu nggak perlu langsung nge-clone ulang repository dari awal atau nangis di pojokan. Git punya beberapa "tombol undo" yang bisa kamu pakai, tergantung situasinya. Yuk, kita bedah satu per satu cara paling ampuh buat ngatasin "salah commit" ini.

Situasi 1: Salah Commit Terakhir, Belum Sempat git push

Ini skenario paling ideal. Kamu baru aja bikin commit, tapi sadar ada yang salah sebelum commit itu dikirim ke repository remote (kayak GitHub, GitLab, atau Bitbucket). Kesalahan ini bisa macem-macem:

  • Ada file yang lupa di-add.
  • Ada perubahan yang belum selesai atau malah nggak seharusnya ada di commit itu.
  • Pesan commit-nya (commit message) salah ketik atau kurang informatif.
  • Mau menggabungkan perubahan terakhir yang belum di-commit ke commit sebelumnya.

Nah, buat ngatasin ini, jurus pamungkasnya adalah git commit --amend.

Apa itu git commit --amend?

Secara harfiah, amend artinya memperbaiki atau mengubah. Jadi, git commit --amend itu perintah buat mengubah commit terakhir yang kamu bikin. Git akan mengambil snapshot dari staging area kamu saat ini, lalu menggabungkannya dengan commit terakhir. Commit terakhir yang lama nggak dihapus, tapi digantikan sama commit baru yang udah diperbaiki ini. Buat Git, commit yang diperbaiki ini dianggap commit yang berbeda meskipun hash ID-nya mirip atau bahkan berubah total.

Cara Pakai git commit --amend:

  1. Perbaiki filenya: Lakukan perubahan yang perlu kamu perbaiki atau tambahkan. Misalnya, tambahkan file yang lupa, hapus baris kode yang nggak perlu, dll.
  2. git add file yang diubah: Pastikan perubahan yang mau masuk ke commit perbaikan udah di-add ke staging area. Gunakan git add nama_file atau git add . kalau mau menambahkan semua perubahan.
  3. Jalankan perintah: Buka terminal/command prompt di folder project kamu, lalu ketik:

bash
    git commit --amend
  1. Edit pesan commit (opsional): Setelah menjalankan perintah di atas, Git akan membuka editor teks default kamu. Di sana, kamu bisa mengubah pesan commit kalau memang itu yang salah. Kalau pesan commit-nya udah benar atau kamu cuma mau menambahkan file/perubahan aja, kamu bisa simpan dan tutup editornya tanpa mengubah apa-apa. Git akan otomatis menggunakan pesan commit yang lama kalau kamu nggak ngedit.
  2. Selesai! Commit terakhir kamu sekarang sudah diperbaiki. Cek dengan git log --oneline. Kamu akan lihat commit terakhir sekarang mencakup perubahan yang baru kamu tambahkan dan/atau pesan commit yang baru.

Contoh Skenario amend:

Kamu commit "Tambah fitur A", tapi ternyata ada satu file konfigurasi penting kelupaan di-add.

bash
Kamu udah terlanjur commit
git commit -m "Tambah fitur A"Eh, baru sadar ada file_konfigurasi.yaml yang lupa di-add
Lakukan penambahan file atau perubahan lain kalau perlu
git add file_konfigurasi.yamlSekarang perbaiki commit terakhir
git commit --amend
Git akan buka editor, kamu bisa biarkan pesan commit "Tambah fitur A" atau ganti

Sekarang commit "Tambah fitur A" yang baru udah termasuk file_konfigurasi.yaml. History Git kamu jadi lebih rapi, seolah-olah kamu nggak pernah lupa file itu di awal.

Penting: git commit --amend hanya bekerja dengan aman kalau commit terakhir belum kamu push ke repository remote. Kenapa? Karena amend itu mengganti commit lama dengan commit baru. Kalau commit lama itu sudah ada di repository remote dan orang lain sudah menarik (pull) perubahanmu, menggantinya akan mengacaukan history mereka dan bisa bikin konflik yang ribet. Jadi, ingat ya, amend buat commit lokal terakhir.

Situasi 2: Salah Commit, Tapi Commitnya Bukan Yang Terakhir Atau Perubahannya Mau Dibuang Total

Kadang commit yang salah itu udah beberapa commit yang lalu, atau kamu sadar bahwa semua perubahan di commit terakhir itu benar-benar salah dan mau dibuang aja, bukan diperbaiki. Dalam kasus ini, amend nggak cukup. Kamu butuh git reset.

Apa itu git reset?

git reset adalah perintah yang kuat untuk "memundurkan" kondisi repository kamu ke commit tertentu. Perintah ini akan menggeser pointer HEAD (penanda commit terakhir di branch saat ini) ke commit yang kamu tuju. Efeknya terhadap file-file dan staging area kamu tergantung pada opsi yang kamu pakai (--soft, --mixed, --hard).

Memahami Opsi git reset:

Sebelum pakai git reset, penting banget tahu bedanya --soft, --mixed, dan --hard. Ketiga opsi ini menentukan apa yang terjadi pada file-file di working directory (folder project kamu) dan di staging area (tempat file yang siap di-commit) setelah HEAD dipindahkan.

  1. git reset --soft

* Memindahkan HEAD ke . * Tidak mengubah working directory (file-file kamu tetap sama). * Tidak mengubah staging area (perubahan dari commit yang di-reset masih ada di staging area, siap di-commit ulang). * Ini berguna kalau kamu mau "membatalkan" commit terakhir (atau beberapa commit terakhir) tapi tetap mempertahankan semua perubahannya di staging area, siap untuk di-commit ulang dengan pesan yang berbeda atau digabungkan dengan commit lain.

bash
    # Contoh: Batalkan 1 commit terakhir, perubahan tetap di staging
    git reset --soft HEAD~1
    # HEAD~1 artinya 1 commit sebelum HEAD (commit terakhir)
    # Kamu bisa cek status dengan git status, semua perubahan ada di "Changes to be committed"
  1. git reset --mixed(Ini default kalau nggak pakai opsi)

* Memindahkan HEAD ke . * Tidak mengubah working directory (file-file kamu tetap sama). Mengubah staging area (perubahan dari commit yang di-reset dipindahkan keluar* dari staging area, kembali ke working directory sebagai "Changes not staged for commit"). * Ini opsi default. Berguna kalau kamu mau membatalkan commit tapi ingin menata ulang perubahanmu sebelum di-commit lagi. Perubahan ada, tapi belum siap di-commit.

bash
    # Contoh: Batalkan 1 commit terakhir, perubahan dipindahkan ke working directory
    git reset HEAD~1
    # Sama dengan git reset --mixed HEAD~1
    # git status akan menunjukkan perubahan ada di "Changes not staged for commit"
  1. git reset --hard

* Memindahkan HEAD ke . Mengubah working directory (semua perubahan di file-file kamu yang setelah* commit tujuan akan dihapus permanen!). * Mengosongkan staging area. Ini opsi paling berbahaya! Gunakan dengan SANGAT hati-hati. Ini seperti mesin waktu yang benar-benar mengembalikan kondisi file dan history ke commit tujuan, menghapus jejak semua commit dan perubahan setelah itu. Gunakan kalau kamu benar-benar yakin* mau membuang semua perubahan yang ada di commit yang salah dan commit setelahnya.

bash
    # Contoh: Batalkan 1 commit terakhir dan buang SEMUA perubahannya
    git reset --hard HEAD~1
    # PERINGATAN: SEMUA perubahan di commit terakhir AKAN HILANG PERMANEN!

Cara Pakai git reset Untuk Membuang Commit Terakhir:

Seringkali, kamu mau membuang commit terakhir karena isinya benar-benar salah dan nggak mau diambil sama sekali perubahannya. Dalam kasus ini, git reset --hard HEAD~1 adalah caranya.

  1. Pastikan kamu ada di branch yang benar.
  2. Pastikan working directory kamu bersih (git status menunjukkan "nothing to commit, working tree clean"). Kalau ada perubahan lokal yang belum di-commit, simpan dulu (git stash) atau commit sementara di branch lain, karena reset --hard akan menghapusnya.
  3. Jalankan perintah:

bash
    git reset --hard HEAD~1

HEAD~1 artinya satu commit sebelum commit HEAD saat ini (yaitu, commit terakhir). Kalau mau membatalkan dua commit terakhir, pakai HEAD~2, dan seterusnya.

  1. Selesai! Commit terakhir kamu sekarang sudah hilang dari history branch ini, dan kondisi file-file kamu kembali ke keadaan pada commit sebelumnya.

Kapan Pakai git reset?

Ketika commit yang salah adalah commit terakhir (atau beberapa commit terakhir) dan belum* dipush. Ketika kamu mau membuang commit dan semua* perubahannya (reset --hard).

  • Ketika kamu mau membatalkan commit tapi tetap mempertahankan perubahannya untuk di-commit ulang (reset --soft atau --mixed).

Lagi-lagi, Peringatan Keras: Jangan pernah menggunakan git reset --hard pada commit yang sudah dipush ke repository remote, terutama jika branch tersebut dipakai bersama orang lain. Sama seperti amend, reset mengubah history. Melakukan reset lalu memaksa push (git push --force) akan membuat pusing tim kamu karena history mereka jadi beda dengan history remote.

Situasi 3: Salah Commit, DAN Commitnya Sudah Sempat Dipush!

Oke, ini skenario yang butuh penanganan lebih hati-hati, terutama kalau kamu kerja dalam tim dan commit yang salah itu sudah dipush ke branch main atau branch shared lainnya. Seperti yang dijelaskan sebelumnya, amend dan reset itu mengubah history, dan mengubah history yang sudah dibagikan itu tabu di dunia Git (karena bikin history orang lain jadi "kadaluarsa").

Jurus yang aman di sini adalah git revert.

Apa itu git revert?

Berbeda dengan reset yang "memutar balik" history, git revert tidak mengubah history sama sekali. Sebaliknya, git revert membuat commit baru yang isinya kebalikan dari perubahan yang ada di commit yang ingin kamu batalkan.

Misalnya, commit A menambahkan baris kode. Kalau kamu git revert commit A, Git akan membuat commit B yang isinya menghapus baris kode yang ditambahkan oleh commit A. History asli (termasuk commit A yang salah) tetap ada, tapi efeknya dinetralisir oleh commit baru (commit B).

Keuntungan git revert:

  • Aman untuk history yang dibagikan: Karena tidak mengubah history, kamu bisa dengan aman revert commit yang sudah dipush. Anggota tim lain hanya perlu git pull seperti biasa untuk mendapatkan commit "pembatal" ini.
  • Merekam pembatalan: Tindakan pembatalan itu sendiri terekam sebagai commit baru di history, yang bisa berguna untuk audittrail.

Cara Pakai git revert:

  1. Identifikasi commit yang salah: Cari hash ID dari commit yang ingin kamu batalkan. Kamu bisa pakai git log untuk melihat history dan mencari hash ID-nya (serangkaian karakter unik, contoh: a1b2c3d).
  2. Jalankan perintah:

bash
    git revert 

Ganti dengan hash ID commit yang ingin kamu batalkan.

  1. Edit pesan commit (opsional): Git akan membuka editor teks untuk membuat pesan commit baru untuk commit "pembatalan" ini. Git biasanya sudah memberikan pesan default yang jelas (misalnya, "Revert 'Pesan commit asli'"). Kamu bisa tambahkan penjelasan kalau perlu, lalu simpan dan tutup editornya.
  2. Selesai! Git akan membuat commit baru di atas HEAD kamu yang berisi kebalikan dari perubahan di commit yang kamu revert. Sekarang kamu bisa git push commit pembatalan ini ke remote repository dengan aman.

Contoh Skenario revert:

Kamu push commit f7e8d9c dengan pesan "Implementasi fitur X" yang ternyata menyebabkan bug kritis di produksi.

bash
Lihat history untuk cari hash commit yang salah
git log --oneline
Output:
abcdef0 (HEAD -> main) Commit terakhir yang lain
f7e8d9c Implementasi fitur X # <--- INI commit yang salah
... commit-commit sebelumnya ...Batalkan commit f7e8d9c
git revert f7e8d9cGit akan buka editor. Pesan default mungkin "Revert 'Implementasi fitur X'"
Simpan dan tutup editor.Sekarang ada commit baru di atas abcdef0 yang membatalkan f7e8d9c
git log --oneline
Output:
1a2b3c4 (HEAD -> main) Revert "Implementasi fitur X"
abcdef0 Commit terakhir yang lain
f7e8d9c Implementasi fitur X
...Push commit pembatalan ini dengan aman
git push origin main

Sekarang, meskipun commit f7e8d9c masih ada di history, perubahannya sudah dinetralkan oleh commit 1a2b3c4, dan rekan tim kamu bisa menarik perubahan ini tanpa masalah.

Reverting Beberapa Commit:

Kamu juga bisa revert lebih dari satu commit sekaligus, tapi hati-hati dengan urutannya dan potensi konflik. Kalau kamu mau revert rentang commit, misalnya dari commit A sampai commit B (termasuk A dan B), kamu bisa pakai git revert A..B. Git akan revert commit satu per satu, mulai dari commit B (yang paling baru) sampai commit A (yang paling lama) dalam rentang itu.

bash
Revert semua commit dari hashlama sampai hashbaru
git revert hashlama..hashbaru

Setiap revert akan menghasilkan commit baru. Kalau ada konflik saat reverting commit tertentu, Git akan berhenti dan kamu harus menyelesaikannya secara manual sebelum melanjutkan proses revert (biasanya dengan git revert --continue).

Situasi 4: Salah Commit di Tengah History Lokal (Belum Dipush), Perlu Perbaikan yang Lebih Kompleks

Bagaimana kalau commit yang salah itu bukan yang terakhir, tapi juga belum dipush, dan kamu nggak mau pakai reset --hard (karena perubahannya nggak mau dibuang semua), atau revert (karena mau history yang rapi seolah kesalahan itu nggak pernah terjadi)? Di sini, git rebase -i bisa jadi pilihan, meskipun ini tools yang lebih advance dan butuh kehati-hatian ekstra.

Apa itu git rebase -i?

git rebase -i (interactive rebase) memungkinkan kamu untuk mengubah history commit di branch kamu dari commit tertentu ke HEAD. "Interactive" artinya Git akan membuka editor dan membiarkan kamu memutuskan apa yang mau dilakukan dengan setiap commit dalam rentang tersebut.

Beberapa hal yang bisa kamu lakukan dengan git rebase -i:

  • Mengubah pesan commit (dengan perintah reword atau r).
  • Menggabungkan beberapa commit menjadi satu (dengan perintah squash atau s, fixup atau f).
  • Mengubah urutan commit.
  • Menghapus commit (dengan menghapus barisnya dari daftar).
  • Mengedit commit (dengan perintah edit atau e) - ini yang berguna kalau kamu mau memperbaiki commit yang salah di tengah history.

Cara Pakai git rebase -i Untuk Memperbaiki Commit Lama:

  1. Identifikasi commit yang salah dan commit sebelum commit yang salah itu. Kamu akan menjalankan rebase interaktif dari commit sebelum commit yang salah.
  2. Jalankan perintah:

bash
    git rebase -i 

Atau kalau kamu mau memperbaiki commit ke-N dari yang terakhir, bisa pakai HEAD~N. Contoh, mau perbaiki commit ketiga dari terakhir: git rebase -i HEAD~3.

  1. Git akan membuka editor dengan daftar commit dari commit yang kamu tentukan sampai HEAD. Di samping setiap hash commit, ada perintah default pick.
  2. Temukan baris commit yang salah dan ubah perintah pick menjadi edit (atau e).
  3. Simpan dan tutup editornya.
  4. Git akan "menghentikan" proses rebase tepat setelah menerapkan commit sebelum commit yang kamu tandai edit, dan memberitahu kamu bahwa sekarang kamu berada dalam mode "editing commit".
  5. Sekarang, perbaiki commit yang salah:

* Perubahan dari commit yang salah itu sudah ada di working directory kamu. Lakukan perbaikan yang diperlukan pada file-file. * git add file yang sudah diperbaiki. Jalankan git commit --amend. Ini akan meng-amend commit yang sedang diedit* (yaitu, commit yang salah tadi). Kamu juga bisa sekalian mengubah pesan commit-nya di sini.

  1. Lanjutkan proses rebase: Setelah selesai meng-amend commit, jalankan:

bash
    git rebase --continue
  1. Selesai! Git akan melanjutkan menerapkan commit-commit berikutnya (kalau ada). History kamu sekarang sudah rapi, seolah-olah commit yang salah itu tidak pernah terjadi, tapi dengan perubahan yang sudah diperbaiki.

Peringatan Keras Lagi: git rebase -i juga mengubah history! Jangan pernah melakukan rebase (interaktif maupun tidak) pada branch yang sudah dipush dan dibagikan. Rebase akan membuat history baru, dan kalau kamu push setelah rebase (butuh git push --force), ini akan mengacaukan repository lokal anggota tim lain. Gunakan rebase interaktif hanya di branch lokal kamu yang belum dipush.

Jadi, Kapan Pakai Yang Mana?

Ini dia ringkasan singkat buat panduanmu:

  • git commit --amend: Commit yang salah adalah terakhir dan belum dipush. Kamu mau memperbaiki isinya (tambah/ubah file) atau pesan commitnya. Mengubah history lokal.
  • git reset --soft/--mixed/--hard: Commit yang salah adalah terakhir (atau beberapa terakhir) dan belum dipush.

* --soft: Mau membatalkan commit tapi mempertahankan perubahan di staging. * --mixed (default): Mau membatalkan commit tapi mempertahankan perubahan di working directory (belum di-staging). * --hard: Mau membatalkan commit dan membuang SEMUA perubahannya permanen. Mengubah history lokal. Sangat hati-hati dengan --hard.

  • git revert: Commit yang salah sudah dipush atau berada di branch yang dibagikan. Kamu mau membatalkan efek dari commit tersebut dengan membuat commit baru. Tidak mengubah history lama, hanya menambah history baru. Ini cara paling aman untuk history yang sudah dibagikan.
  • git rebase -i: Commit yang salah ada di tengah history lokal dan belum dipush. Kamu mau memperbaiki commit tersebut (atau melakukan manipulasi history kompleks lainnya) seolah-olah kesalahan itu tidak pernah ada. Tools yang powerful tapi berisiko jika dipakai di history yang sudah dipush.

Apa yang Terjadi Kalau Terlanjur git push --force Setelah reset Atau rebase?

Kalau kamu terpaksa banget (misalnya, kamu satu-satunya orang yang pakai branch itu, atau kamu yakin semua orang di tim bisa handle) dan kamu melakukan git reset atau git rebase lalu git push --force atau git push -f, ini akan menimpa history di repository remote dengan history lokal kamu yang baru.

Konsekuensinya:

  1. History orang lain jadi "outdated": Rekan tim yang sebelumnya sudah menarik (pull) commit lama kamu akan memiliki history yang berbeda dengan repository remote.
  2. Mereka akan kesulitan pull: Saat mereka mencoba git pull, Git akan memberitahu bahwa history remote berbeda dan menolak operasi pull biasa. Mereka mungkin perlu melakukan git pull --rebase atau git fetch lalu git reset --hard origin/nama-branch-mereka (yang juga berbahaya karena bisa menghapus perubahan lokal mereka yang belum di-push).
  3. Potensi kehilangan pekerjaan: Kalau mereka tidak hati-hati, mereka bisa kehilangan perubahan lokal mereka saat mencoba menyinkronkan history.

Intinya, hindari force push di branch yang dipakai bersama kalau bukan keadaan darurat dan sudah dikomunikasikan dengan jelas ke seluruh tim. Gunakan git revert untuk memperbaiki kesalahan di history yang sudah dibagikan.

Pentingnya Paham Status Git Kamu

Sebelum melakukan undo atau rollback apapun di Git, selalu cek status Git kamu:

  • git status: Lihat file apa saja yang sudah dimodifikasi, di-add (di staging), atau belum terlacak. Ini penting supaya kamu tahu apakah ada perubahan lokal yang belum di-commit dan perlu diselamatkan sebelum melakukan reset --hard misalnya.
  • git log --oneline: Lihat history commit kamu dalam format singkat. Ini bantuin kamu nyari hash commit mana yang mau di-reset atau di-revert.
  • git reflog: Ini adalah "log referensi". Git merekam setiap kali HEAD kamu berubah. Ini seperti jaring pengaman! Kalau kamu nggak sengaja melakukan reset --hard terlalu jauh atau melakukan kesalahan fatal lainnya, git reflog bisa menunjukkan state-state HEAD sebelumnya. Kamu bisa pakai hash dari reflog untuk kembali ke state sebelumnya dengan git reset --hard. Ini penyelamat hidup!

Kesimpulan

Membuat commit yang salah di Git itu bukan akhir dunia. Git menyediakan tools yang powerful untuk "undo" atau memperbaiki kesalahan tersebut. Pilihan terbaik tergantung pada dua hal utama:

  1. Apakah commit sudah dipush atau belum?
  2. Apakah kamu mau memperbaiki commit, membatalkannya tapi menyimpan perubahannya, atau membuang perubahannya sama sekali?

Ingat prinsip utamanya: Jangan mengubah history yang sudah dibagikan (amend, reset, rebase). Gunakan git revert untuk history yang sudah dipush. Latihan dan hati-hati adalah kunci. Selalu cek git status dan git log sebelum menjalankan perintah "undo" yang kuat. Dan kalau panik, ingat ada git reflog sebagai penyelamat terakhirmu. Selamat ngoding dengan lebih tenang!