Kebiasaan buruk yang hampir semua orang alami: .env berisi kredensial di-commit lebih dulu, barulah kemudian .gitignore ditulis — urutannya terbalik. Pasalnya, .gitignore hanya menyamarkan berkas untracked; sekali sebuah berkas masuk riwayat, Git terus mengawasinya apa pun kata pola. Chapter ini membuktikan perilaku itu dengan suntingan nyata, lalu menempuh prosedur resminya: git rm --cached mengeluarkan berkas dari index tanpa menyentuh disk, sehingga pola .gitignore akhirnya bekerja. Konsekuensi terakhirnya tidak kalah penting — berkas yang berhenti dilacak tetap tergantung di riwayat lama.
Bukti: .gitignore Tidak Menghentikan Pelacakan #
Repository latihan sengaja memuat kecelakaan itu sejak commit pertama — situs.md dan .env dilacak bersamaan, lalu .gitignore menyusul di commit kedua:
mkdir latihan-terlanjur && cd latihan-terlanjur
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Situs Toko Berkah\nberanda toko\n' > situs.md
printf 'KUNCI_API=contoh-rahasia\n' > .env
git add situs.md .env
git commit -m "Buat beranda dan konfigurasi"
printf '.env\n' > .gitignore
git add .gitignore
git commit -m "Abaikan berkas .env"Sekarang kita sunting .env seolah nilai kuncinya berganti:
printf 'KUNCI_API=contoh-rahasia-baru\n' > .env
git statusOutput yang Dihasilkan:
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: .env
no changes added to commit (use "git add" and/or "git commit -a").env muncul sebagai modified meski pola .env tercantum di .gitignore sejak commit sebelumnya. Dengan git diff, suntingannya bahkan terbaca utuh:
git diffOutput yang Dihasilkan:
diff --git a/.env b/.env
index c3266a8..7b26e64 100644
--- a/.env
+++ b/.env
@@ -1 +1 @@
-KUNCI_API=contoh-rahasia
+KUNCI_API=contoh-rahasia-baruMekanismenya sudah kita kenal dari chapter Untracked dan Tracked Files
: status membandingkan index dengan disk, dan index masih memuat entri .env. Pengecekan .gitignore hanya berlaku pada berkas yang belum dikenal Git — pelacakannya harus kita hentikan secara eksplisit.
Urutan kejadian di sandbox ini meniru kecelakaan dunia nyata: aturan .gitignore ditulis setelah berkas terlanjur masuk riwayat, sehingga aturan itu kehilangan kesempatan bekerja sejak awal.
git rm –cached: Keluar dari Index, Tetap di Disk #
Perintah git rm --cached menghapus entri dari index — snapshot berikutnya tidak lagi memuat .env — tanpa menghapus berkas fisiknya:
git rm --cached .envOutput yang Dihasilkan:
rm '.env'Baris rm '.env' menandakan penghapusan dicatat di index, bukan di disk. Status dan isi folder memastikan keduanya sekaligus:
git status
ls .envOutput yang Dihasilkan:
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: .env.envBagian Changes to be committed memuat deleted: .env — itulah perubahan yang akan dicatat commit berikutnya. Berkasnya sendiri masih ada di disk (ls berhasil), dan kini berstatus untracked yang tersamarkan pola, sehingga tidak muncul di daftar untracked. Kita selesaikan transaksinya:
git commit -m "Hentikan pelacakan .env"Output yang Dihasilkan:
[main 4edb8c1] Hentikan pelacakan .env
1 file changed, 1 deletion(-)
delete mode 100644 .envHash 4edb8c1 milik sandbox — nilai pembaca menyesuaikan. Status pun kini sunyi sepenuhnya:
git statusOutput yang Dihasilkan:
On branch main
nothing to commit, working tree cleanSejak commit ini, pola .env benar-benar memegang kendali: suntingan .env berikutnya tidak akan pernah muncul di status, dan git add . pun tak akan menangkapnya.
Berkasnya Tetap Tergantung di Riwayat Lama #
Berhenti dilacak bukan berarti terhapus dari sejarah. Commit lama masih menyimpan salinan .env apa adanya:
git log --oneline -- .env
git show HEAD~1:.envOutput yang Dihasilkan:
4edb8c1 Hentikan pelacakan .env
a9d8e11 Buat beranda dan konfigurasiKUNCI_API=contoh-rahasiaRiwayat path .env memuat dua commit, dan git show HEAD~1:.env mengeluarkan isi berkas pada commit sebelum “Hentikan pelacakan .env” — kuncinya masih terbaca. Siapa pun yang men-clone repository bisa menelusuri jalur yang sama; menulis ulang .gitignore tidak menutup pintu itu.
Direktori Terlanjur: git rm -r –cached #
Masalah yang sama sering datang dalam ukuran lebih besar — seluruh direktori terlanjur ter-commit. Skenario kita melanjutkan repo yang sama: direktori hasil/ sempat dilacak, lalu pola hasil/ menyusul:
mkdir hasil
printf 'laporan uji v1\n' > hasil/laporan.md
git add hasil
git commit -m "Tambah laporan hasil uji"
printf 'hasil/\n' >> .gitignore
git add .gitignore
git commit -m "Abaikan direktori hasil"Opsi -r membuat --cached bekerja rekursif pada seluruh isi direktori:
git rm -r --cached hasil/Output yang Dihasilkan:
rm 'hasil/laporan.md'git status
ls hasil/Output yang Dihasilkan:
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: hasil/laporan.mdlaporan.mdSatu berkas di dalamnya tercatat sebagai deleted di staging, sementara ls membuktikan isi hasil/ masih utuh di disk — perilaku yang sama dengan kasus .env, hanya dikerjakan berlapis. Commit penutupnya identik:
git commit -m "Hentikan pelacakan direktori hasil"Output yang Dihasilkan:
[main 322e6c3] Hentikan pelacakan direktori hasil
1 file changed, 1 deletion(-)
delete mode 100644 hasil/laporan.mdgit statusOutput yang Dihasilkan:
On branch main
nothing to commit, working tree cleanPola lengkapnya kini tertutup: pencegahan lewat .gitignore
, penghentian pelacakan lewat git rm --cached. Sisanya — git rm itu sendiri beserta jaring pengaman dan kaitannya dengan rm biasa — menjadi fokus chapter berikutnya. Lanjut ke git rm
.