Chapter sebelumnya menutup dengan posisi yang jujur: kredensial dirotasi dulu, sebaran riwayat dipetakan — sekarang repository itu sendiri yang harus dibereskan supaya clone baru tidak lagi mewarisi secret. Tiga jalur pembersihan tersedia, dipilih berdasarkan seberapa dalam secret tertanam: amend untuk kasus paling ringan, penulisan ulang riwayat untuk kasus yang sudah terdorong jauh, dan repository baru untuk saat riwayat tak layak diselamatkan. Ketiganya berakhir dengan pekerjaan yang sama dan tak bisa dilewati: force-push, koordinasi tim, dan kesadaran bahwa rotasi tetap satu-satunya penutup insiden yang sungguh menyeluruh.

Kasus Ringan: Commit Terakhir, Belum Dipush #

Kasus terbaik terjadi saat kita sadar segera: secret ada di commit terakhir, dan commit itu belum pernah dipush — tidak ada clone lain yang memegangnya. Sandbox menyiapkan keadaannya, dengan .env terlanjur masuk:

bash
git show --stat --oneline HEAD

Output yang Dihasilkan:

text
d4973cc Tambah konfigurasi
 .env | 1 +
 1 file changed, 1 insertion(+)

Perbaikan tiga langkah: keluarkan .env dari staging, siapkan .gitignore supaya tidak terulang, lalu tulis ulang commit terakhirnya dengan --amend:

bash
git rm --cached .env
printf '.env\n' > .gitignore
git add .gitignore
git commit --amend -m "Tambah gitignore untuk berkas lingkungan"

Perintah git rm --cached melepaskan .env dari index tanpa menghapus berkas di working directory — rahasia tetap ada di disk lokal, hanya tidak lagi dilacak. Status antara perbaikan menunjukkan keduanya:

bash
git status --short

Output yang Dihasilkan:

text
D  .env
A  .gitignore

Hasil akhirnya — commit “Tambah konfigurasi” yang memuat .env sudah tidak ada di riwayat:

bash
git log --oneline
git show --stat --oneline HEAD

Output yang Dihasilkan:

text
c6b3718 Tambah gitignore untuk berkas lingkungan
04e15f0 Commit awal proyek
text
c6b3718 Tambah gitignore untuk berkas lingkungan
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

git cat-file -e HEAD:.env gagal — .env tidak lagi menjadi bagian snapshot HEAD. Hash di mesin pembaca berbeda, pola keluarannya yang sama. Dasar perilakunya dibedah di Amend Commit : --amend tidak “mengedit” commit, melainkan membuat commit baru yang menggantikan tempatnya — riwayat ditulis ulang.

Satu kejujuran teknis perlu dicatat: commit lama d4973cc tidak langsung musnah. Ia masih hidup sebagai objek yang terjangkau lewat reflog — jangkar keselamatan yang biasa menyelamatkan kita dari kesalahan, sebagaimana dibahas di git reflog :

bash
git reflog

Output yang Dihasilkan:

text
c6b3718 HEAD@{0}: commit (amend): Tambah gitignore untuk berkas lingkungan
d4973cc HEAD@{1}: commit: Tambah konfigurasi
04e15f0 HEAD@{2}: commit (initial): Commit awal proyek

Karena belum dipush, satu-satunya pemegang objek itu adalah repository lokal kita sendiri. Memusnahkannya tuntas adalah urusan internal: git reflog expire --expire=now --all melepas jangkar reflog, lalu git gc --prune=now memangkas objek tak terjangkau — setelah itu git cat-file -t d4973cc menjawab fatal: git cat-file: could not get object info. Batas pentingnya: opsi ini hanya sah karena belum ada push. Bila commit sudah pernah sampai ke remote, amend akan ditolak saat push — penolakan non-fast-forward dan jalan keluarnya dibedah di Non-Fast-Forward Push .

Riwayat Dalam: Tulis Ulang dengan Alat #

Secret di commit ke-40 dari 400, sudah dipush, sudah di-clone tim — amend tidak menyentuh ini. Pekerjaannya adalah menulis ulang seluruh riwayat, dan dua alat siap: git filter-repo — alat resmi yang direkomendasikan bahkan oleh dokumentasi git filter-branch karena cepat dan aman dari jebakan klasiknya — dan BFG Repo-Cleaner. filter-repo membuang berkas atau mengganti teks di seluruh riwayat dengan satu perintah semacam git filter-repo --path .env --invert-paths; bedah lengkapnya menjadi chapter berikutnya. BFG adalah alat berbasis Java dengan falsafah “hapus, jangan edit”: diberi daftar berkas atau pola teks untuk dimusnahkan dari seluruh commit, BFG menulis ulang riwayat dengan cepat namun menolak mengubah pesan commit. Sandbox tidak mendemokan keduanya secara langsung — keduanya bukan bagian Git inti dan BFG membutuhkan Java — sehingga keduanya dijelaskan dari dokumentasinya; pemakaian nyata filter-repo menjadi pokok bahasan git filter-repo .

Apa pun alatnya, hasilnya sama: sebagian besar (atau seluruh) hash commit berubah, karena objek yang dibangun ulang berantai hingga ke atas. Riwayat baru, isi bersih, hash lain.

Opsi Nuklir: Repository Baru #

Jalur ketiga dipilih bila riwayat memang tidak bernilai: repository kecil sebelum rilis pertama, proyek latihan, atau insiden yang membuat seluruh riwayat terasa tercemar. Resepnya: git init repository baru, salin isi working directory yang bersih (tanpa .git lama), commit awal, lalu ganti remote — atau buat repository platform baru sama sekali. Yang tertinggal di belakang: hash lama seluruhnya, dan — bila memakai repository platform yang sama — issues, pull request, serta pengaturan yang tetap terikat pada repository lama. Berat jalur ini bukan pada Git-nya, melainkan pada keputusan membuang sejarah.

Wajib Setelah Pembersihan #

Tiga pekerjaan menutup setiap jalur pembersihan. Pertama, force-push seluruh branch dan tag yang berubah — git push --force-with-lease origin per branch, atau git push --force-with-lease --tags --all untuk semuanya sekaligus; --force-with-lease menjaga agar tidak menimpa pekerjaan orang lain yang masuk di antara waktu kita mem-fetch dan menulis ulang, sebagaimana dibedah di Non-Fast-Forward Push . Branch yang diproteksi platform perlu dilonggarkan sementara oleh admin. Ketiga, rotasi tetap wajib: fork dan clone lama di luar kendali kita tetap memegang secret berapa pun bersihnya repository pusat.

Pekerjaan kedua — koordinasi tim — paling sering diremehkan:

Urutan lengkapnya, dari penemuan sampai penutupan:

LangkahTindakanKriteria selesai
1. Deteksitemukan secret, catat berkas dan tanggal masuknyadaftar kredensial yang terbocor
2. Rotasicabut/ganti setiap kredensial di penyedianyaakses lama mati
3. Evaluasigit log --all --source -- <berkas>peta sebaran per ref
4. Bersihkanamend / filter-repo / BFG / repo baruriwayat bersih di lokal
5. Terbitkanforce-push semua branch + tag (--force-with-lease)remote bersih
6. Koordinasitim meninggalkan clone lama, re-clonetak ada merge dari riwayat lama
7. Auditperiksa log platform untuk pemakaian tokentak ada aktivitas asing
8. Cegah ulang.gitignore, secret scanning, review berkas rahasiapola berulang tertutup

Pilihan jalur keempat dirangkum dalam satu alur keputusan:

Setiap ujung jalur bermuara ke kotak yang sama — force-push, re-clone, audit — karena pembersihan Git hanyalah separuh pekerjaan; separuh lainnya berada di luar repository. Jalur tengahnya, filter-repo, adalah alat paling sering dipakai untuk kasus nyata, dan pembahasan tuntasnya — instalasi, perintah, hingga verifikasi hasil — menjadi chapter berikutnya.