Jika sebuah commit lama berisi perubahan yang tidak diinginkan pada satu file, Anda dapat membalikkan (reverse) perubahan file tersebut terhadap branch saat ini dan menyimpan hasilnya dalam commit baru. Cara ini tetap mempertahankan commit-commit setelahnya dan menjaga editan di dalamnya selama patch pembalik masih cocok. Di macOS, gunakan Terminal dari repositori; tinjau patch terlebih dahulu, terutama jika pekerjaan setelahnya menyentuh baris yang sama.

Pilih perubahan riwayat yang tepat

Prosedur ini menambahkan sebuah commit yang membatalkan perubahan pada satu path dari commit target. Prosedur ini tidak menghapus file tersebut dari commit lama, sehingga versi lama tetap ada dalam riwayat. Pendekatan ini menghindari penulisan ulang riwayat branch dan biasanya tepat digunakan ketika commit sudah dibagikan atau commit setelahnya bergantung padanya. Git menjelaskan git revert sebagai pencatatan commit baru yang membalikkan commit sebelumnya, tetapi Git tidak menawarkan opsi bawaan untuk me-revert hanya satu path dari commit yang ada. Sebagai gantinya, langkah-langkah di bawah ini menghasilkan patch dari path tersebut dan menerapkannya secara terbalik. Git: Dokumentasi git-revert

Jika perubahan file harus dihapus dari commit historis itu sendiri, itu adalah tugas penulisan ulang riwayat (history-rewrite), yang biasanya ditangani dengan rebase interaktif. Menulis ulang riwayat akan mengubah identitas commit dan dapat mengganggu kolaborator yang mendasarkan pekerjaannya pada commit lama. Panduan ini membahas pendekatan aditif yang lebih aman.

Balikkan perubahan commit target pada satu file

Buka Terminal, buka repositori, dan periksa working tree sebelum mengubah apa pun. Ganti TARGET dengan ID commit dan path/to/file dengan path relatif terhadap root repositori. Contoh ini menggunakan file patch sementara di direktori /tmp macOS; pilih nama sementara lain jika file tersebut sudah ada.

git status --short
git show --stat --oneline TARGET
git diff TARGET^ TARGET -- "path/to/file" > /tmp/remove-file-change.patch

Perintah diff membandingkan commit target dengan parent pertamanya dan membatasi hasilnya pada path yang ditentukan. Untuk commit normal non-merge, ini mewakili perubahan commit tersebut pada file yang bersangkutan. Pastikan ringkasan mengidentifikasi commit yang dimaksud dan file patch tidak kosong. Anda dapat memeriksanya dengan less /tmp/remove-file-change.patch; tekan q untuk keluar. Git mendokumentasikan diff antarkomite dengan pembatasan path opsional. Git: Dokumentasi git-diff

Sebelum menerapkannya, pastikan Anda tidak memiliki editan yang tidak terkait, baik yang di-stage maupun un-staged, pada file target. Patch pembalik mengubah salinan kerja (working copy), jadi working tree yang bersih adalah titik awal yang paling sederhana. Jika Anda memiliki pekerjaan lokal yang berguna, lakukan commit atau simpan dengan aman terlebih dahulu; jangan menimpanya dengan perintah restore.

Periksa apakah patch pembalik cocok, lalu terapkan:

git apply --reverse --check /tmp/remove-file-change.patch
git apply --reverse /tmp/remove-file-change.patch

--reverse menerapkan diff secara terbalik, sedangkan --check memeriksa apakah patch dapat diterapkan tanpa mengubah file. Secara default, git apply menggagalkan seluruh patch jika beberapa potongan (hunk) tidak cocok, alih-alih menerapkan bagian yang cocok saja. Jika pemeriksaan gagal, hentikan dan periksa file beserta patch-nya. Editan setelahnya mungkin tumpang tindih dengan perubahan target, sehingga Git tidak dapat menentukan dengan aman apa yang harus dihapus. Selesaikan konten yang diinginkan secara manual, atau gunakan alur kerja penulisan ulang riwayat jika mempertahankan urutan historis yang diedit secara presisi sangat penting. Jangan sembarangan menambahkan --reject: opsi ini dapat menerapkan bagian yang cocok saja dan meninggalkan potongan yang ditolak. Git: Dokumentasi git-apply

Tinjau dan commit hasilnya

Periksa secara tepat apa yang berubah sebelum melakukan staging. git diff menampilkan editan working-tree; gunakan path lagi untuk memfokuskan peninjauan. Jika hasilnya sudah benar, stage file tersebut dan periksa diff yang telah di-stage sebelum membuat commit baru.

git diff -- "path/to/file"
git add -- "path/to/file"
git diff --cached -- "path/to/file"
git status --short
git commit -m "Remove file change from earlier commit"

Tanda kutip melindungi path dari interpretasi shell, dan -- menandai akhir dari opsi. Keduanya sangat berguna untuk nama file yang mengandung spasi atau karakter khusus shell (metacharacters). Commit mencatat indeks yang telah di-stage; meninjau git diff --cached memverifikasi konten persis yang akan di-commit. Git: Dokumentasi git-commit

Setelah melakukan commit, periksa git status --short dan amati commit baru dengan git show --stat --oneline HEAD. Jika commit asli menambahkan file tersebut, membalikkan patch-nya dapat menghapus file tersebut—ini normal jika tidak ada konten berikutnya yang perlu dipertahankan. Jika commit-commit setelahnya menambahkan konten yang berguna pada file tersebut, penambahan tersebut akan tetap ada saat patch pembalik diterapkan dengan bersih; tinjau file akhir dan diff untuk memastikannya.

Kasus yang memerlukan kehati-hatian ekstra

Sebuah merge commit memiliki beberapa parent, dan perubahannya bergantung pada parent mana yang Anda bandingkan. TARGET^ merujuk pada parent pertama; ini mungkin tidak mewakili perubahan yang ingin Anda hapus. Identifikasi parent yang benar dan bandingkan dengannya secara eksplisit sebelum menerapkan apa pun. Pengubahan nama (rename), file biner, dan file yang telah dipindahkan sejak saat itu juga dapat membuat patch dengan batasan path tidak cocok; periksa diff dan hentikan jika tidak menggambarkan perubahan file yang diinginkan. Untuk pembalikan khusus merge, dokumentasi revert Git menjelaskan pilihan mainline parent beserta konsekuensinya. Git: Dokumentasi git-revert

Titik pemeriksaan yang andal adalah patch yang telah ditinjau: patch tersebut hanya boleh menampilkan perubahan commit target pada path yang dituju. Jika patch tidak dapat diterapkan secara bersih pada file saat ini, jangan memaksanya. Rekonstruksi file saat ini yang diinginkan dengan cermat, lalu stage dan commit hanya setelah meninjau seluruh hasilnya.

Sumber