Web Artisan
Chapter 05 · Git

Bedah Sejarah:
Rebase & Undo Aman

Dua kemampuan yang membuatmu tenang menghadapi history: merapikannya dengan rebase agar enak dibaca, dan membatalkan perubahan dengan alat yang tepat agar tidak ada kerja keras yang hilang.

Rebase & interactiveUndo aman~24 menit baca

Chapter ini satu busur “bedah sejarah”: dua operasi yang sama-sama menyentuh masa lalu repo, tapi dengan tujuan berbeda. Rebase menata ulang commit agar history bercerita rapi; undo (restore, reset, revert, stash) membatalkan langkah yang keliru. Benang merah keduanya adalah satu aturan emas yang kamu pelajari di Chapter 4: jangan menulis ulang sejarah yang sudah dibagikan. Kuasai itu, dan kamu bisa membongkar-pasang history tanpa takut merusak kerja tim.

01

Rebase: Merapikan Sejarah

Linear history, merge vs rebase, dan interactive rebase

Rebase memindahkan commit branch-mu ke atas base terbaru, menulis ulang sejarah agar menjadi garis lurus yang mudah dibaca.

Saat kamu bekerja di branch feature/checkout, branch main tidak diam. Rekanmu terus merge fitur lain ke sana. Kalau nanti kamu merge balik, sejarah jadi rumit: garis bercabang, merge commit di mana-mana, dan git log terlihat seperti peta kereta bawah tanah. Rebase menawarkan jalan lain: alih-alih menyatukan dua cabang dengan merge commit, ia mengangkat commit-commitmu dan menanamnya ulang satu per satu di atas ujung main yang terbaru.

Dokumen GitHub menyebut rebasing sebagai cara “menulis ulang riwayat commit”, yang membuat riwayat lebih bersih namun harus dipakai dengan hati-hati karena commit lama digantikan oleh commit baru dengan hash berbeda.

Terminal
git switch feature/checkout git fetch origin git rebase origin/main
Rebase menulis ulang feature di atas main terbaru Sebelum rebase feature main git rebase main Sesudah rebase (linear) main feature
Rebase memindahkan basis. Commit feature ditulis ulang di atas main terbaru sehingga histori menjadi linear.

Secara teknis, git rebase origin/main melakukan ini: Git mencari commit nenek moyang bersama antara feature/checkout dan origin/main, “melepas” tiap commit milikmu sejak titik itu, memindahkan HEAD ke ujung origin/main, lalu memutar ulang (replay) commit-commitmu satu demi satu. Karena induknya berubah, setiap commit mendapat hash baru. Isinya sama, identitasnya berbeda. Inilah inti dari “menulis ulang sejarah” yang harus kamu pahami benar sebelum melangkah lebih jauh.

🧶Analogi: mencabut dan menanam ulang

Bayangkan commit-mu sebagai tanaman di pot. Merge menyambung dua pot dengan selang. Rebase mencabut tanamanmu dan menanamnya ulang di tanah main yang baru, seolah ia tumbuh di sana sejak awal.

Merge versus rebase

Keduanya menggabungkan kerja dari dua branch, tetapi menghasilkan sejarah yang berbeda secara mendasar. Merge jujur apa adanya: ia menyimpan fakta bahwa dua jalur paralel pernah ada lalu bertemu di satu merge commit. Rebase memilih kerapian: ia berpura-pura kerjamu memang dibangun di atas base terbaru, menghasilkan garis lurus tanpa merge commit.

AspekMergeRebase
SejarahBercabang, ada merge commitLinear, tanpa merge commit
Hash commitTetap (tidak berubah)Ditulis ulang (hash baru)
Kejujuran riwayatMenyimpan jejak paralelMenyembunyikan jejak paralel
Aman untuk branch shared?YaTidak, jangan
flowchart LR
  subgraph Merge
    A1[main] --> M[merge commit]
    B1[feature] --> M
  end
  subgraph Rebase
    A2[main] --> C1[feature']
    C1 --> C2[feature'']
  end

Dua hasil akhir. Merge menyatu di satu titik; rebase memanjang lurus.

⚠️Jangan rebase branch publik

Bila commit sudah di-push dan dipakai orang lain, rebase menulis ulang hash-nya. Saat rekanmu menarik, Git melihat dua sejarah berbeda dan repo mereka kacau dengan commit ganda. Rebase hanya pada commit yang masih lokal dan belum dibagikan. Inilah aturan emas yang menghubungkan chapter ini dengan larangan force push ke branch bersama di Chapter 4.

💡Setel pull.rebase agar history tetap lurus

Banyak tim menyetel git config —global pull.rebase true supaya git pull menumpuk commit lokal di atas perubahan remote alih-alih membuat merge commit “Merge branch main” yang berisik. Tambah git config —global rebase.autoStash true agar Git otomatis memarkir perubahan working tree saat rebase dan mengembalikannya setelah selesai.

Konflik saat rebase

Karena rebase memutar ulang commit satu per satu, konflik bisa muncul di commit mana pun di tengah jalan. Saat itu terjadi, rebase berhenti dan menunggu. Pola penyelesaiannya berbeda dari merge: kamu tidak commit, melainkan melanjutkan rebase.

Resolve konflik

Buka file bertanda, sunting, lalu git add file yang sudah beres.

Lanjutkan

Jalankan git rebase —continue, Git memutar commit berikutnya.

Atau mundur total

Bila ingin batal, git rebase —abort mengembalikan branch ke kondisi sebelum rebase.

Interactive rebase: poles sebelum PR

Inilah use-case rebase yang paling sering kamu pakai di tim nyata: merapikan branch draft sebelum dibaca reviewer, apalagi di tim yang memakai squash merge. git rebase -i membuka editor berisi daftar todo: tiap commit satu baris dengan kata kunci di depannya. Tiga commit “wip”, “fix typo”, dan “beneran fix” bisa dilebur jadi satu commit bersih yang menceritakan satu perubahan utuh, sehingga history main tetap terbaca rapi.

Kata kunciArti
pickPakai commit apa adanya
rewordPakai commit, tapi ubah pesannya
squashLebur ke commit di atasnya, gabung kedua pesan
fixupLebur ke commit di atasnya, buang pesannya
editBerhenti di commit ini untuk diubah
dropBuang commit sepenuhnya
Terminal
git rebase -i HEAD~3 # editor terbuka: # pick a1b2c3d add product handler # fixup d4e5f6a fix typo # fixup 9z8y7x6 wip # simpan & tutup → tiga commit jadi satu
🪄Reorder dengan memindah baris

Mengubah urutan baris di editor todo akan mengubah urutan commit saat replay. Pindahkan commit dokumentasi ke bawah, atau dekatkan fixup ke commit asalnya, lalu simpan.

🌉Jembatan: seperti menyunting draft

Saat menulis artikel, kamu tidak menerbitkan setiap coretan. Kamu menggabung paragraf, menghapus catatan, lalu publish versi rapi. Interactive rebase adalah penyuntingan akhir itu untuk riwayat commit-mu.

02

Reset, Restore, Revert, dan Stash

Membatalkan perubahan dengan aman

Git punya beberapa cara membatalkan perubahan, dan salah memilih bisa menghapus kerja keras secara permanen.

Pertanyaan “bagaimana cara undo di Git?” tidak punya satu jawaban, karena tergantung kamu ingin membatalkan apa: perubahan file yang belum di-commit, staging yang keliru, atau commit yang sudah masuk sejarah. Empat perintah menangani kasus yang berbeda, dan memahami batas masing-masing menyelamatkanmu dari kehilangan data.

git restore: buang perubahan working tree

git restore menangani file yang sudah kamu ubah tapi belum di-commit. Ada dua arah: mengembalikan isi file ke versi terakhir, atau mengeluarkannya dari staging area.

Terminal
git restore internal/product/service.go # buang edit, kembali ke HEAD git restore --staged internal/product/service.go # unstage, edit tetap ada
🌉Jembatan: undo editor vs undo repo

Ctrl+Z di editor membatalkan ketikan terakhir di satu file. git restore bekerja di level snapshot repo, mengembalikan file ke kondisi commit terakhir sekaligus, bahkan setelah editor ditutup.

git reset: memindahkan HEAD

reset menggeser pointer HEAD ke commit lain, dan tiga modenya menentukan area mana yang ikut berubah. Inilah perintah yang paling sering disalahpahami, dan --hard adalah yang paling berbahaya.

Tiga mode git reset HEAD (commit) Index (staging) Working tree git reset --soft dipindah git reset --mixed (default) di-reset git reset --hard semua dibuang --soft menyimpan perubahan (tetap staged), --mixed meng-unstage, --hard membuang semua di working tree.
Tiga mode reset. —soft, —mixed, dan —hard berbeda pada area mana yang ikut diubah.
ModeHEADIndex (staging)Working tree
—softPindahTetap (perubahan tetap staged)Tetap
—mixed (default)PindahDi-reset (unstage)Tetap
—hardPindahDi-resetDitimpa (perubahan hilang)
Terminal
git reset --soft HEAD~1 # batalkan commit terakhir, isinya tetap tersimpan & staged git reset HEAD~1 # (--mixed) batalkan commit, isi jadi unstaged di working tree git reset --hard HEAD~1 # batalkan commit DAN buang semua perubahannya

--soft berguna saat kamu ingin menyusun ulang commit terakhir tanpa kehilangan apa pun. --mixed mengembalikan perubahan ke working tree untuk dipilah ulang. --hard membuang semuanya tanpa ampun.

⚠️git reset --hard membuang permanen

Mode —hard menimpa working tree dan perubahan yang belum di-commit lenyap. Untuk commit yang sempat ada, git reflog masih merekam pergerakan HEAD dan bisa dipakai memulihkan (dibahas di Chapter 7), tapi file yang belum pernah di-commit sama sekali tidak terselamatkan.

git revert: undo aman untuk sejarah publik

reset cocok untuk commit lokal, tapi berbahaya bila commit sudah di-push. Untuk membatalkan commit yang sudah dibagikan, pakai git revert. Alih-alih menghapus, ia membuat commit baru yang isinya kebalikan dari commit target. Sejarah tetap utuh, hash lama tetap ada, dan rekanmu tidak terganggu.

flowchart LR
  A[C1] --> B[C2 buggy] --> C[C3] --> D[C4 revert C2]

Revert menambah, bukan menghapus. C4 membalik efek C2 tanpa menyentuh sejarah yang sudah dipush.

Terminal
git revert a1b2c3d # buat commit baru yang membalik a1b2c3d
💡Reset untuk lokal, revert untuk publik

Aturan praktis: commit belum di-push? reset boleh. Commit sudah di-push dan dipakai orang lain? Selalu revert, karena ia tidak menulis ulang sejarah yang sudah dimiliki orang. Ini cerminan aturan emas rebase di section sebelumnya.

git stash: simpan sementara

Kadang kamu sedang setengah jalan mengerjakan sesuatu lalu harus pindah branch untuk perbaikan mendesak. git stash menyimpan perubahan yang belum di-commit ke tumpukan terpisah, membersihkan working tree, lalu bisa kamu kembalikan nanti.

Simpan

git stash push -m “wip checkout” menyimpan dan memberi label.

Pindah & kerjakan

Working tree bersih, bebas git switch ke branch lain.

Kembalikan

git stash pop menerapkan lalu menghapus dari tumpukan, atau git stash apply menerapkan tanpa menghapus.

Terminal
git stash push -m "wip checkout" git stash list # lihat semua stash git switch hotfix/price-bug # ... perbaiki, commit ... git switch feature/checkout git stash pop # lanjutkan kerja sebelumnya
03

Ringkasan

Membongkar-pasang history tanpa takut

Rebase menata sejarah agar rapi, empat alat undo membatalkan langkah keliru, dan satu aturan emas menjaga semuanya tetap aman.

Kamu kini bisa membedah history dengan percaya diri. Rebase memindahkan commit ke base terbaru dan, lewat mode interaktif, melebur draft jadi commit bersih sebelum PR, asal tidak pada sejarah yang sudah dibagikan. Untuk membatalkan, pilih alat sesuai sasaran: restore untuk file working tree, reset untuk menggeser HEAD (hati-hati --hard), revert untuk membatalkan commit publik dengan aman, dan stash untuk memarkir kerja sementara. Di Chapter 6 kita beralih dari operasi ke konvensi: tag, gitignore, hooks, Conventional Commits, dan workflow tim yang menata semua kemampuan ini untuk banyak orang.

Yang Wajib Menempel

  • git rebase main memindahkan commit branch ke atas base terbaru, hasilnya linear; setiap commit dapat hash baru.
  • Konflik rebase diselesaikan lalu git rebase —continue, atau batalkan dengan —abort.
  • Aturan emas: jangan rebase (atau reset) commit publik yang sudah dipakai orang lain; pakai revert untuk itu.
  • git rebase -i dengan squash/fixup/reword merapikan draft commit sebelum PR.
  • Undo: restore (file), reset —soft/—mixed/—hard (geser HEAD), revert (publik aman), stash (parkir sementara).
  • reflog adalah jaring pengaman saat reset —hard tak sengaja, commit jarang benar-benar hilang.