Menghapus berkas dari proyek terdengar seperti urusan satu perintah rm — sampai git status memprotes dengan baris deleted yang terus menggantung tanpa pernah tercatat ke riwayat. Persoalannya: penghapusan adalah perubahan juga, dan setiap perubahan harus melewati index agar masuk commit. Perintah git rm mengerjakan dua lapisan itu sekaligus — menghapus berkas dari disk sekaligus mencatat penghapusannya di index. Chapter ini membedah perintahnya opsi per opsi, kontrasnya dengan rm biasa, jaring pengaman yang menolak menghapus pekerjaan yang belum ter-commit, hingga resep mengeluarkan berkas dari commit terakhir.
git rm: Dua Lapisan Sekaligus #
Repository latihan memuat enam berkas yang sudah ter-commit:
mkdir latihan-rm && cd latihan-rm
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 'daftar galeri produk\n' > galeri.md
printf 'catatan diskusi tim\n' > catatan.txt
mkdir aset
printf 'logo toko v1\n' > aset/logo.txt
printf 'draf konten belum final\n' > draf.txt
printf 'berkas kerja v1\n' > berkas.txt
git add situs.md galeri.md catatan.txt aset/logo.txt draf.txt berkas.txt
git commit -m "Susun awal situs toko"Kita hapus galeri.md dengan git rm:
git rm galeri.mdOutput yang Dihasilkan:
rm 'galeri.md'Baris rm 'galeri.md' adalah konfirmasi dua lapisan: berkas lenyap dari disk dan penghapusannya kini duduk di staging area. Dua pemeriksaan singkat membuktikannya:
git status
ls galeri.mdOutput yang Dihasilkan:
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: galeri.mdls: cannot access 'galeri.md': No such file or directoryStatus menampilkan deleted: galeri.md di bagian Changes to be committed — siap menjadi bagian commit berikutnya tanpa langkah tambahan, dan ls gagal karena berkas memang tidak lagi ada di disk.
Kontras: rm Biasa Mencatat Sebelah Sisi Saja #
rm biasa hanya menyentuh disk. Git melihat hasilnya sebagai perubahan belum staged:
rm catatan.txt
git statusOutput yang Dihasilkan:
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: galeri.md
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: catatan.txtPenghapusan catatan.txt muncul di bagian Changes not staged for commit — Git tahu berkasnya hilang, tetapi keadaan itu belum dicatat ke index. Dari dua jalur penyelesaian — git add catatan.txt pun sah — kita pakai bentuk yang konsisten dengan topik:
git rm catatan.txtOutput yang Dihasilkan:
rm 'catatan.txt'git statusOutput yang Dihasilkan:
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: catatan.txt
deleted: galeri.mdKini kedua penghapusan (catatan.txt dan galeri.md) berdampingan di staging. Inilah inti perbedaannya: rm adalah perintah sistem berkas yang kebetulan dipantau Git, sedangkan git rm adalah perintah Git yang mengoordinasikan index dan disk dalam satu langkah.
Opsi -r: Menghapus Direktori #
Penghapusan satu direktori beserta seluruh isinya butuh opsi rekursif — Git menolak git rm aset tanpa -r agar tidak menghapus massal tanpa sengaja:
git rm -r aset
ls asetOutput yang Dihasilkan:
rm 'aset/logo.txt'ls: cannot access 'aset': No such file or directorySeluruh isi aset/ — dalam hal ini aset/logo.txt — dihapus dari index dan disk sekaligus. Kita bekukan ketiga penghapusan ini ke riwayat:
git commit -m "Hapus galeri, catatan, dan aset"Output yang Dihasilkan:
[main c26c6e0] Hapus galeri, catatan, dan aset
3 files changed, 3 deletions(-)
delete mode 100644 aset/logo.txt
delete mode 100644 catatan.txt
delete mode 100644 galeri.mdOpsi –cached: Tanpa Sentuhan Fisik #
Sudah kita pakai pada chapter Mengabaikan File yang Terlanjur Dilacak
: --cached menghapus dari index saja, berkas fisik dibiarkan. Resep lengkapnya — pola dulu, --cached kemudian — kita ulang pada draf.txt:
printf 'draf.txt\n' > .gitignore
git add .gitignore
git rm --cached draf.txt
git status
ls draf.txtOutput yang Dihasilkan:
rm 'draf.txt'On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .gitignore
deleted: draf.txtdraf.txtPenghapusan tercatat staged, .gitignore ikut ter-commit nanti, dan draf.txt tetap hidup di disk — bebas dari pandangan Git selamanya setelah commit ini:
git commit -m "Hentikan pelacakan draf.txt"Output yang Dihasilkan:
[main 82518a2] Hentikan pelacakan draf.txt
2 files changed, 1 insertion(+), 1 deletion(-)
create mode 100644 .gitignore
delete mode 100644 draf.txtJaring Pengaman dan Opsi -f #
git rm tidak sembarangan menghapus. Berkas yang isi disknya berbeda dari HEAD dan dari index berarti menyimpan pekerjaan yang belum ter-commit di dua arah; Git menolak dan menawarkan jalan keluar:
printf 'berkas kerja v2\n' > berkas.txt
git add berkas.txt
printf 'berkas kerja v3\n' > berkas.txt
git rm berkas.txtOutput yang Dihasilkan:
error: the following file has staged content different from both the
file and the HEAD:
berkas.txt
(use -f to force removal)Penolakan ini menyelamatkan kedua versi suntingan — v2 yang staged dan v3 yang hanya ada di disk — dari kepunahan. Bila memang sudah diputuskan untuk membuangnya semua, opsi -f melangkahi jaring pengaman:
git rm -f berkas.txt
ls berkas.txtOutput yang Dihasilkan:
rm 'berkas.txt'ls: cannot access 'berkas.txt': No such file or directoryBentuk penolakan lain yang sering muncul: berkas yang diubah tanpa staging menghasilkan pesan has local modifications dengan saran --cached atau -f. Keduanya sengaja dibuat “berisik” supaya penghapusan destruktif selalu disadari.
Menghapus dari Commit Terakhir #
Skenario penutup: berkas salah masuk pada commit terakhir yang belum sempat di-push. Alih-alih commit pembersih baru, kita sunting commit itu — pola amend yang dibahas tuntas pada chapter Amend Commit
. sementara.txt kita commit lebih dulu sebagai “kecelakaan”:
printf 'catatan sementara tidak sengaja\n' > sementara.txt
git add sementara.txt
git commit -m "Tambah catatan sementara"Keluarkan dari index tanpa menghapus fisiknya, tambahkan polanya, lalu lebur ulang commit terakhir:
git rm --cached sementara.txt
printf 'sementara.txt\n' >> .gitignore
git add .gitignore
git commit --amend --no-editOutput yang Dihasilkan:
[main d1a6fc0] Tambah catatan sementara
Date: Mon Oct 26 11:10:00 2026 +0700
2 files changed, 1 insertion(+), 1 deletion(-)
delete mode 100644 berkas.txtBaris Date: menandakan tanggal penulis asli dipertahankan oleh amend. Hasil akhirnya simetris dengan tujuan kita:
git ls-files
ls sementara.txtOutput yang Dihasilkan:
.gitignore
situs.mdsementara.txtgit ls-files hanya memuat dua berkas yang memang dilacak — sementara.txt sudah tidak tercatat, meski berkasnya masih ada di disk dan status kini bersih:
git statusOutput yang Dihasilkan:
On branch main
nothing to commit, working tree cleanPerintah git rm menguasai ujung hidup berkas; perintah sejenis menunggu di ujung lainnya — ketika berkas tidak dihapus, hanya berpindah nama atau direktori. Lanjut ke git mv
.