- Karena di Git sulit mencari solusi jika tidak tahu nama situasi kesalahannya, materi ini merangkum perintah berdasarkan skenario pemulihan yang umum agar bisa langsung ditemukan dan digunakan
- Saat repositori rusak parah atau ingin membatalkan kesalahan penghapusan/merge, Anda bisa mencari riwayat pekerjaan dengan
git reflog lalu kembali ke keadaan sebelumnya dengan git reset HEAD@{index}
- Perbaikan kecil pada commit terakhir atau perubahan pesan bisa ditangani cepat dengan
git commit --amend, tetapi tidak boleh digunakan pada commit yang sudah di-push ke branch publik/bersama
- Jika commit dilakukan di branch yang salah, commit bisa dipindahkan melalui alur
reset, stash, checkout, stash pop atau dengan cherry-pick, tetapi cara yang aman berbeda tergantung apakah sudah di-push atau belum
reset --hard dan git clean -d --force, yang memulihkan paksa ke keadaan repositori remote, dapat menghapus bahkan file yang tidak dilacak, sehingga perlu diperiksa sebelum dijalankan
Mengapa kesalahan Git sulit dipulihkan
- Git mudah membuat orang melakukan kesalahan, dan untuk memperbaiki masalah, sering kali Anda harus sudah tahu nama konsep yang diperlukan agar bisa mencarinya
- Materi ini merangkum situasi buruk yang sering dialami di Git dalam bahasa Inggris sederhana dan contoh perintah
- Ini bukan referensi lengkap, dan mungkin ada cara lain untuk menangani pekerjaan yang sama
Mengembalikan repositori ke keadaan masa lalu
- Saat repositori rusak parah atau Anda ingin memulihkan sesuatu yang terhapus, periksa riwayat pekerjaan dengan
git reflog
git reflog
# Anda bisa melihat daftar operasi Git di semua branch
# Setiap entri memiliki indeks dalam bentuk HEAD@{index}
git reset HEAD@{index}
reflog bisa digunakan dalam situasi berikut
- Memulihkan konten yang tidak sengaja dihapus
- Menghapus percobaan yang merusak repositori
- Memulihkan setelah merge yang buruk
- Kembali ke titik ketika semuanya benar-benar berfungsi
Cara memperbaiki commit terakhir
- Jika perlu menambahkan perbaikan kecil tepat setelah commit terakhir, gunakan
git commit --amend --no-edit
# Setelah melakukan perubahan
git add . # atau tambahkan file satu per satu
git commit --amend --no-edit
- Perintah ini memasukkan perubahan baru ke commit terakhir
- Anda juga bisa membuat perubahan yang sama sebagai commit baru lalu menggabungkannya dengan
rebase -i, tetapi amend jauh lebih cepat
- Jangan gunakan
amend pada commit yang sudah di-push ke branch publik/bersama
- Untuk hanya mengubah pesan commit terakhir, gunakan perintah berikut
git commit --amend
# Ubah pesan commit sesuai instruksi
Saat commit dilakukan di branch yang salah
- Jika Anda tidak sengaja melakukan commit ke
master padahal seharusnya berada di branch baru, buat branch baru dari keadaan saat ini lalu hapus commit terakhir dari master
git branch some-new-branch-name
git reset HEAD~ --hard
git checkout some-new-branch-name
- Cara ini tidak cocok untuk commit yang sudah di-push ke branch publik/bersama
- Jika Anda sudah mencoba hal lain terlebih dahulu, mungkin perlu memakai bentuk
HEAD@{number-of-commits-back} alih-alih HEAD~
- Jika commit benar-benar dilakukan di branch yang salah, Anda bisa memindahkannya dengan alur
reset --soft, stash, checkout, stash pop
git reset HEAD~ --soft
git stash
git checkout name-of-the-correct-branch
git stash pop
git add . # atau tambahkan file satu per satu
git commit -m "your message here"
- Dalam situasi yang sama, Anda juga bisa menggunakan
cherry-pick
git checkout name-of-the-correct-branch
git cherry-pick master
git checkout master
git reset HEAD~ --hard
Membatalkan perubahan dan commit lama
- Jika Anda mengubah file tetapi
git diff kosong, perubahan mungkin sudah di-staging, jadi perlu flag --staged
git diff --staged
- Untuk membatalkan perubahan dari beberapa commit sebelumnya, cari hash dengan
git log lalu jalankan git revert
git log
git revert [saved hash]
git revert membuat commit baru yang membatalkan commit tersebut
- Jika ingin membatalkan hanya file tertentu, bukan seluruh commit, gunakan alur menaikkan versi lama file ke index lalu melakukan commit
git log
git checkout [saved hash] -- path/to/file
git commit -m "Wow, you don't have to copy-paste to undo"
Memulihkan paksa ke keadaan repositori remote
- Alih-alih menghapus repositori lalu melakukan clone ulang, Anda bisa menggunakan perintah Git untuk menyamakannya dengan keadaan repositori remote
git fetch origin
git checkout master
git reset --hard origin/master
git clean -d --force
git reset --hard origin/master menyamakan branch dengan keadaan master remote
git clean -d --force menghapus file dan direktori yang tidak dilacak
- Untuk setiap branch yang rusak, Anda harus mengulangi
checkout, reset, dan clean
- Operasi ini destruktif dan tidak dapat dipulihkan, jadi berhati-hatilah sebelum menjalankannya
Cakupan dan kontribusi
- Materi ini bukan referensi Git lengkap, melainkan kumpulan prosedur pemulihan praktis yang ditemukan lewat trial and error
- Jika ingin membantu menambahkan terjemahan, Anda bisa mengirim PR di GitHub
1 komentar
Komentar Hacker News
Ada beberapa hal yang ingin saya ubah: selalu memakai
git switchalih-alihgit checkout, dan sebisa mungkin menghindarireset --hardMisalnya, untuk kasus “tidak sengaja membuat commit di master padahal seharusnya di branch baru”, bisa ditangani dengan urutan
git branch some-new-branch-name,git switch -d HEAD~,git switch -C master,git switch some-new-branch-nameUntuk kasus “commit di branch yang salah” juga bisa ditangani dengan
git switchke branch yang benar, lalugit cherry-pick master,git switch -d master~,git switch -C masterUntuk “menyerah saja dan kembali ke state remote” pun bisa disusun seperti
git fetch origin,git restore -WS .,git clean -d --force,git switch -d origin/master,git switch -C masterBahkan jika memahami model Git dengan baik, resep-resep seperti ini tidak intuitif, dan kita juga harus tahu perilaku khas tiap perintah
Misalnya
git switch -c some-new-branch-namememang sudah ada, tetapi perintah sepertigit move-branch master HEAD~untuk hanya memindahkan branch ke commit lain tampaknya akan lebih intuitifgit switchdangit restoresebagai penggantigit checkout, tetapi perintah-perintah ini diperkenalkan di Git v2.23, dan rilis itu sekitar 5 tahun laluHalaman bantuannya masih memuat peringatan
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.Tentu saja peringatan ini sudah ada nyaris sejak perintah tersebut pertama muncul, dan setelah 5 tahun rasanya sudah waktunya tidak lagi disebut eksperimental
Meski begitu,
git checkoutlebih kompatibel ke versi lama, dan bisa dianggap mencerminkan cara memakai Git pada masa ketika situs web ini awalnya dibuathttps://github.com/git/git/blob/757161efcca150a9a96b312d9e78...
https://github.com/git/git/releases/tag/v2.23.0
https://github.com/git/git/commit/4e43b7ff1ea4b6f16b93a432b6...
git add .sebagai default saat memasukkan perubahan ke staging area kurang bagusMenambahkan file tertentu secara eksplisit membuat kemungkinan nanti berkata “aduh, kacau” jadi lebih kecil
Saya ingin tahu alasan
switchlebih baik daripadacheckout, dan alasan tidak seharusnya memakaireset --hardreset --hard”Saya penasaran kenapa itu sebenarnya tidak cukup, dan saya cukup sering memakainya bersama
alias git-restore-file='git restore --source=HEAD --', rasanya bekerja dengan baikSaat belajar Git, kita seharusnya mulai merekomendasikan klien GUI sebagai jalur dasar
Dengan begitu sepertiga masalah seperti ini akan terselesaikan, dan sepertiga lainnya bahkan tidak akan muncul sejak awal
Kalau nanti menilai command line lebih cepat, silakan pakai saat itu; yang penting orang-orang perlu melihat secara visual dulu cara berinteraksi dengan tree
Secara pribadi saya suka fork.dev, tetapi klien-klien sekarang umumnya mirip
Dengan Magit, tindakan seperti “membatalkan cherry-pick” bisa ditemukan di dalam antarmuka, dan memakai shortcut yang sama dengan operasi “batalkan X” lainnya
Kalau saya harus memakai command line Git saja, mungkin saya tidak akan tahu harus mulai dari mana
Saya juga pernah menghapus commit yang tidak boleh dihapus saat interactive rebase, tetapi setiap kali rebase dimulai, ada snapshot yang bisa diakses dari reflog sehingga aman untuk membatalkan rebase yang salah
UI reflog Magit sama seperti UI log, jadi saya tidak tersesat saat pertama melihatnya, tetapi kalau memakai Git CLI mungkin saya tidak akan tahu apa yang sedang terjadi
Saya suka bahwa ketika
jjdijalankan tanpa argumen, ia menampilkan bagian relevan dari commit tree dan posisi saat iniKita bisa melihat sekilas commit yang sedang dikerjakan, branch yang terhubung dan historinya, branch aktif lain di repositori, pesan tiap commit, dan apakah ada perubahan, sehingga sangat bagus untuk kembali menemukan arah
Namun hampir tidak ada yang mendengarkan, lalu akhirnya tersiksa di CLI, merusak branch, tertinggal dari main, dan takut pada rebase
Banyak hal yang di UI bisa diselesaikan dengan drag-and-drop atau cara serupa; terlihat seperti semacam penyiksaan diri
Walaupun antarmukanya buruk, memakai antarmuka yang sama dengan orang lain di tim membuat komunikasi lebih mudah, dan materi pemecahan masalah online umumnya mengasumsikan “cara biasa”, sehingga lebih mudah dimanfaatkan
Rasanya cukup aneh bahwa pada April 2025 Git sudah berusia 20 tahun
Saya ada di lapangan saat itu, dan ingat sempat bingung harus belajar yang mana di antara git, darcs, atau bazaar untuk menggantikan SVN atau CVS
Entah apakah saya juga sempat mencoba Mercurial
Saya penasaran apakah “efek GitHub” secara praktis telah mematikan kebutuhan akan pendatang baru di bidang sistem kontrol versi
Mungkin pada suatu titik kegiatan mencukur bulu yak itu sudah cukup selesai
Saya sudah sepenuhnya beralih ke jj, dan karena kompatibel dengan Git, saya tidak perlu menunggu orang lain ikut beralih
Saya makin frustrasi dengan berbagai aspek GitHub, jadi suatu hari saya berharap semua orang juga bisa melampauinya, tetapi jalan ke arah itu tampaknya tidak sesederhana itu
SVN itu intuitif dan berjalan cukup baik untuk 99% kasus, sehingga orang tidak perlu “diajari” secara khusus
Saya berharap kita semua berhenti berpura-pura menjadi hacker 1337, dan mengakui bahwa Git adalah alat yang berlebihan bagi kebanyakan orang
Saya rasa saya punya model mental yang cukup baik tentang apa yang dilakukan Git, tetapi begitu perintahnya sedikit saja rumit, saya tidak bisa mengingat argumennya
Perintah-perintahnya tidak mudah ditemukan dan tidak mudah dihafal
Entah apakah UI teksnya yang buruk, atau memang pekerjaan memanipulasi tree sulit dijelaskan lewat teks
Memanipulasi tree yang kompleks lewat teks itu tidak mudah, dan UI teksnya juga secara objektif buruk: https://stevelosh.com/blog/2013/04/git-koans/
Senang melihat hasil pencarian untuk hg dan Mercurial muncul di thread ini
Saya masih tidak percaya Mercurial kalah dalam perang distributed version control, dan menurut saya itu alat yang lebih baik
Bisa dipakai, stabil, sudah teruji di dunia nyata, dan masih aktif didukung
Ini dekat dengan “jadilah perubahan yang ingin kamu lihat”, jadi pakai saja
Ungkapan bahwa ia kalah justru sangat kontraproduktif, dan hambatan implisit dari kata-kata seperti itu membuat adopsi Mercurial tetap rendah
Hosting setidaknya tersedia di Sourcehut dan heptapod.host
Saya juga menjalankan instance Heptapod pribadi, yaitu fork Gitlab dengan dukungan langsung untuk Mercurial, dan itu berjalan baik-baik saja
Git adalah salah satu teknologi yang dalam banyak hal tidak mengikuti intuisi, sehingga akhirnya sulit benar-benar masuk ke kepala
Jika belum lama menggunakannya, kemungkinan besar untuk hampir setiap pekerjaan harus mencari di Google atau melihat halaman man
Terutama setelah mengalami horor mengelola codebase besar di SVN dengan banyak branch lalu mencoba menggabungkannya kembali, terlihat bahwa Git jauh, jauh lebih baik untuk bagian itu
Bagi orang yang masuk langsung dari awal dengan Git, learning curve-nya mungkin jauh lebih besar, tetapi kadang saya masih sulit memahami di mana orang-orang tersangkut
Jika memakai cara bawaan,
filter-branch, muncul peringatan setelah jeda panjang yang menyuruh menekan Control+C dan mengunduh skrip Python pihak ketiga bernamafilter-repoTidak bangga mengakuinya, tetapi operasi Git “sudah kacau” yang paling sering saya pakai adalah menghapus repository lokal, clone lagi, lalu menerapkan ulang perubahan
95% berhasil dengan sangat baik, sisanya saya minta bantuan orang DevOps
cp -R .git ../git-backupKarena kalau kerusakannya terlalu besar, saya cukup mengganti seluruh direktori
.gitdengan salinan lamaItu jauh lebih cepat daripada mencari cara mengembalikan operasi tertentu atau sekumpulan operasi dengan benar
Hal yang saya harap benar-benar diinternalisasi orang tentang Git adalah bahwa Git merupakan penyimpanan data append-only
Jika ingin memasukkan pekerjaan ke repository, lakukan commit, dan pekerjaan yang sudah masuk tidak bisa dihapus dengan perintah Git
reflog juga bekerja berdasarkan prinsip ini
Apa pun yang Anda lakukan, Anda bisa kembali ke keadaan branch sebelumnya dan memulihkan pekerjaan dari penyimpanan data
Namun jika belum di-commit, Git tidak bisa membantu, jadi commit saja
Selalu commit, dan jika bebannya terlalu besar atau Anda terus lupa, maka alatnya yang perlu diperbaiki
Jika menulis kode sepanjang hari, secara umum setidaknya Anda harus commit sekali setiap jam
Ini hal sepele, tetapi setiap kali melihat
git reflog, saya membacanya seperti re-flogMungkin itu sebabnya saya sulit menghafal perintah ini, dan sepertinya secara bawah sadar tidak menganggapnya sebagai “reference log”
Alih-alih, rasanya seperti menyuruh Git menjual sesuatu lagi dengan harga murah
Saya bukan pengguna Git, tetapi ketika melihat hal seperti ini, saya makin merasa bahwa
git commititu sendiri tidak bermakna; yang penting hanyalah saat commit itu di-push atau di-mergeMirip seperti menyimpan file teks
Kita tidak menulis pesan singkat setiap kali menyimpan file, jadi bisa dilewati saja
Bukan berarti harus singkat; semakin kecil perubahannya, penjelasannya kadang justru semakin panjang
Saya pernah menulis 2–3 paragraf untuk perubahan 2–3 baris yang berdampak besar
Commit lokal adalah cara membuat checkpoint pada titik ketika semuanya berhasil dikompilasi dan berjalan
Dengan begitu, ketika perlu melakukan stash pada perubahan atau saat membuat kekacauan, kita bisa kembali ke kondisi yang masih berjalan
Sebelum push, lakukan reset lalu pecah menjadi commit-commit yang sesuai, maka histori remote tetap rapi dan tidak menjadi tumpukan dummy
wipAtau bisa juga melakukan squash merge pada PR agar mendapatkan kelebihan dari keduanya
Namun tidak perlu memasukkan pesan yang tidak bermakna seperti
more fixesBiasanya buat commit awal seperti
(WIP) nama fitur, lalu ulangi amend commit sampai puas, dan terakhir hapus(WIP)dari pesannyaSaya melihat log revisi Git juga mirip dengan diari semacam itu
Ia lebih terstruktur daripada dokumen TODO terpisah, dan mendorong kita menjelaskan pekerjaan yang sudah dilakukan dengan cara yang mudah dibaca
Saat menilai seberapa jauh harus melakukan revert, mengetahui apa yang dipikirkan pada commit saat itu bisa berguna, dan jika pendekatannya ternyata salah, itu juga membantu postmortem
Jika pekerjaan yang belum di-merge atau di-push tersusun sebagai perubahan terpisah yang punya tujuan, ketika sebagian bagus dan sebagian buruk, akan jauh lebih mudah mempertahankan hanya bagian yang bagus
Meski begitu, secara teknis commit bukanlah sesuatu yang tidak bermakna
Tanpa commit, tidak ada yang bisa di-push atau di-merge
Secara nonteknis pun, mencatat dalam teks biasa mengapa sesuatu diubah itu sangat berguna
Jika penjelasan seperti itu harus ditulis terlalu sering, berarti unit “perubahan” perlu dipersempit, atau pekerjaan yang disentuh secara bersamaan perlu diseleksi lebih ketat
Jika tidak memakai Git, saya penasaran apa yang digunakan untuk version control dan change management