Git: Bagaimana cara menghapus file dari komit historis?

113

Saya telah berkomitmen dengan id 56f06019 (misalnya). Dalam komit itu saya secara tidak sengaja melakukan file besar (50Mb). Di komit lain saya menambahkan file yang sama tetapi dalam ukuran yang tepat (kecil). Sekarang repo saya ketika saya mengkloning terlalu berat :( Bagaimana cara menghapus file besar itu dari riwayat repo untuk mengurangi ukuran repo saya?

marioosh
sumber
dalam kasus saya, ini bukan file besar, tetapi file konfigurasi yang berisi kredit database. Saya sedang mempelajari git, pada saat itu saya tidak menyadari .gitignore.
Rashi
1
help.github.com/articles/…
Trevor Boyd Smith

Jawaban:

165

Bab 9 dari buku Pro Git memiliki bagian tentang Menghapus Objek .

Izinkan saya menjelaskan langkah-langkahnya secara singkat di sini:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Seperti opsi rebasing yang dijelaskan sebelumnya, filter-branchadalah operasi penulisan ulang. Jika Anda telah menerbitkan sejarah, Anda harus --forcemendorong ref baru.

The filter-branchPendekatan jauh lebih kuat daripada rebasependekatan, karena

  • memungkinkan Anda untuk bekerja di semua cabang / referensi sekaligus,
  • mengganti nama tag apa pun dengan cepat
  • beroperasi dengan bersih bahkan jika ada beberapa komit penggabungan sejak penambahan file
  • beroperasi dengan bersih bahkan jika file itu (kembali) ditambahkan / dihapus beberapa kali dalam sejarah (a) branch (es)
  • tidak membuat komit baru yang tidak terkait, melainkan menyalinnya saat memodifikasi struktur yang terkait dengannya. Ini berarti bahwa hal-hal seperti komit yang ditandatangani, catatan komit, dll. Dipertahankan

filter-branch menyimpan cadangan juga, sehingga ukuran repo tidak akan langsung berkurang kecuali Anda mengakhiri reflog dan pengumpulan sampah:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger
lihat
sumber
1
Perlu dicatat bahwa ini sepertinya tidak berfungsi di bawah windows cmd.exe. Tampaknya bekerja di bawah cygwin baik-baik saja.
Nama Palsu
2
Saya mendapatkan git filter-branch di atas untuk bekerja dengan menggunakan tanda kutip ganda daripada tanda kutip tunggal (di Windows Server 2012 cmd.exe)
JCii
1
Yang berhasil bagi saya adalah baris perintah cabang-filter ini. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Kemudian rm --recursive --force .git/refs/originaldan rm --recursive --force .git/logs Kemudian saya menggunakan git prune --expire now dan git gc --aggressive Ini bekerja lebih baik untuk saya daripada langkah-langkah tepat Anda yang tercantum di atas. Terima kasih telah menyertakan tautan ke buku Git Pro karena sangat berharga.
dacke.geo
Setelah perintah filter-branch, satu-satunya cara saya bisa menurunkan ukuran folder .git adalah dengan mengikuti perintah yang ditemukan di sini: stackoverflow.com/questions/1904860/… git -c gc.reflogExpire = 0 -c gc. reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = sekarang gc "$ @"
Steve Ardis
Untuk memperkecil repo, saya menggunakan perintah yang terdaftar di git filter-branch doc: git-scm.com/docs/…
Ludovic Reckles
0

Anda perlu melakukan git rebase dalam mode interaktif, lihat contoh di sini: Bagaimana cara menghapus komit di GitHub? dan cara menghapus komit lama .

Jika komit Anda ada di HEAD dikurangi 10 komit:

$ git rebase -i HEAD~10

Setelah edisi riwayat Anda, Anda perlu mendorong riwayat "baru", Anda perlu menambahkan +ke gaya (lihat referensi dalam opsi dorong ):

$ git push origin +master

Jika orang lain telah mengkloning repositori Anda, Anda harus memberi tahu mereka, karena Anda baru saja mengubah histori.

Loïc d'Anterroches
sumber
3
Itu tidak menghapus file besar dari sejarah. Juga, cara kanonik untuk memaksa mendorong adalah git push --forceatau git push -f(yang tidak mengharuskan orang untuk mengetahui target dorong cabang)
lihat
Berdasarkan pertanyaan tersebut, file baru tersebut sama persis dengan file lama, yaitu path yang sama. Inilah mengapa Anda tidak bisa langsung menggunakan git rmdi jalan.
Loïc d'Anterroches
2
@sehe, jika Anda melakukan rebase menghilangkan komit dengan file besar, itu hilang untuk selamanya.
vonbrand
@vonbrand hanya dari cabang yang Anda rebased. Saya tidak berasumsi bahwa cabang 'dari' akan dihapus. Tapi ya, jika Anda menghapus cabang pohon revisi, itu akan membantu: _
lihat
@sehe, tentu, Anda harus mengejar semua cabang yang berisi komit yang melanggar. Jika sebelum beberapa semak dalam repo, Anda akan memiliki banyak reorganisasi yang harus dilakukan. Tapi rebase adalah alat untuk ini.
vonbrand
0

Saya mencoba menggunakan jawaban berikut di windows https://stackoverflow.com/a/8741530/8461756

Kutipan tunggal tidak berfungsi di windows, Anda perlu tanda kutip ganda.

Mengikuti berhasil untuk saya.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --all

Setelah menghapus file besar, saya dapat memasukkan perubahan saya ke master github.

Sandeep Dixit
sumber
0

Anda dapat menggunakan Perintah sederhana untuk menghapus

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
pengembang mini
sumber