Hapus file dari repositori Git tanpa menghapusnya dari sistem file lokal

3048

Komit awal saya berisi beberapa file log. Saya telah menambahkan *logke saya .gitignore, dan sekarang saya ingin menghapus file log dari repositori saya.

git rm mylogfile.log

akan menghapus file dari repositori, tetapi juga akan menghapusnya dari sistem file lokal.

Bagaimana saya bisa menghapus file ini dari repo tanpa menghapus salinan file lokal saya?

mveerman
sumber
14
Perlu dicatat bahwa jawaban yang paling banyak dipilih berbahaya bagi sebagian orang. Jika Anda menggunakan repo jarak jauh daripada ketika Anda mendorong lokal Anda maka tarik file lain yang Anda hapus dari git saja AKAN DIHAPUS . Ini disebutkan dalam salah satu balasan tetapi tidak dikomentari.
RichieHH

Jawaban:

4355

Dari file man :

Ketika --cacheddiberikan, konten yang dipentaskan harus cocok dengan ujung cabang atau file pada disk, yang memungkinkan file untuk dihapus dari hanya indeks.

Jadi, untuk satu file:

git rm --cached mylogfile.log

dan untuk satu direktori:

git rm --cached -r mydirectory
omong kosong
sumber
151
Mudah terjawab karena tidak begitu jelas svn rm --keep-local.
Martin
114
Tapi bagaimana cara menjaga file di server jauh? Ini membuat lokal saya, tetapi jika saya mendorong dan menarik dari server lain, file akan dihapus. Saya juga menambahkan .gitignore untuk file, tetapi masih bisa dihapus
spankmaster79
6
Ini masih menghapus file pada git pulljika Anda berada di belakang komit setelahgit rm
Petr Peller
9
Perlu dicatat bahwa, setelah menjalankan perintah dalam jawaban, Anda harus menggunakan git commit -m "Commit message"dan git push. Jika Anda memiliki perubahan bertahap lainnya (periksa dengan git status), mereka juga akan berkomitmen saat ini.
Sinjai
9
Karena ini adalah jawaban yang paling diterima dan tidak dilakukan, apa yang diminta, saya akan memberi tahu apa yang saya lakukan. Saya menggunakan perintah git rm --cached mylogfile.logdan menghapus file dari repositori. Untuk menghindari kehilangan file pada sistem produktif saya melakukan backup file dan tarik setelah ini. File dihapus seperti yang disebutkan sebelumnya dan perlu disalin kembali dari cadangan Anda. Ini cukup menyakitkan, tetapi saya tidak menemukan solusi yang lebih baik untuk masalah ini.
Marcel Grolms
275

Untuk menghapus seluruh folder dari repo (seperti file Resharper), lakukan ini:

git rm -r --cached folderName

Saya telah melakukan beberapa file resharper, dan tidak ingin itu bertahan untuk pengguna proyek lainnya.

Sam Tyson
sumber
13
Hanya catatan tambahan untuk pengunjung masa depan: Jangan gunakan GUI untuk "Sinkronkan" komit kembali ke repo. Itu akan menarik file kembali ke repo lokal Anda. Anda harus melakukan Git Push repo branchuntuk benar-benar menghapus file dari remote.
RubberDuck
211

Anda juga dapat menghapus file dari repositori berdasarkan .gitignore Anda tanpa menghapusnya dari sistem file lokal:

git rm --cached `git ls-files -i -X .gitignore`

Atau, sebagai alternatif, pada Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)
batal
sumber
7
Tidak berfungsi di Windows. git ls-files -i -X ​​.gitignore berfungsi, tapi saya tidak tahu cara mengirim file ke 'git rm'. Apakah Anda tahu bagaimana melakukan hal itu?
Erik Z
17
Bekerja pada Windows jika Anda menggunakan Git Bash dan bukannya cmd-console
Andreas Zita
17
Suka ini. Bekerja kecuali bahwa saya memiliki beberapa file yang akhirnya memiliki spasi dalam nama file. Aku diubah solusi di sini untuk ini: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Silakan pertimbangkan untuk memodifikasi atau menambahkan solusi ini ke jawaban di sini, karena ini adalah alat yang hebat untuk memiliki ...
mpettis
Saya tidak mencoba tetapi harus diuji apakah akan menghapus juga file seperti .gitkeepyang menyimpan folder kosong di repositori. Misalnya. .gitignoreberisi folder uploadsdan repo dipaksa untuk melacak .gitkeep. Dengan menghapus semua dari repo di uploadsbawahnya akan menghapus juga .gitkeep.
Vladimir Vukanac
Saran ini berfungsi sempurna di PowerShell: git rm --cached $ (git ls-files -i -X ​​.gitignore)
geekandglitter
89

Sesuai Jawaban saya di sini: /programming/6313126/how-to-remove-a-directory-in-my-github-repository

Untuk menghapus folder / direktori atau file hanya dari repositori git dan bukan dari lokal coba 3 langkah sederhana.


Langkah-langkah untuk menghapus direktori

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Langkah-langkah untuk mengabaikan folder itu di commit berikutnya

Untuk mengabaikan folder itu dari commit selanjutnya, buat satu file di root bernama .gitignore dan masukkan nama folder itu ke dalamnya. Anda dapat menempatkan sebanyak yang Anda inginkan

File .gitignore akan terlihat seperti ini

/FolderName

hapus direktori

eirenaios
sumber
@gaurav senang itu membantu!
eirenaios
69

Juga, jika Anda telah melakukan data sensitif (misalnya file yang berisi kata sandi), Anda harus menghapusnya sepenuhnya dari sejarah repositori. Berikut panduan yang menjelaskan cara melakukannya: http://help.github.com/remove-sensitive-data/

Direksi
sumber
13
Jawaban ini harus mencakup perintah yang diperlukan untuk menyelesaikan tugas ini alih-alih menautkan ke situs web lain.
Florian Lemaitre
1
Saya juga mencatat bahwa saya menemukan menggunakan alat pembersih repo git bfg lebih mudah dan lebih cepat.
Lubed Up Slug
64

Solusi yang lebih umum:

  1. Edit .gitignorefile.

    ECHO mylogfile.log >> .gitignore

  2. Hapus semua item dari indeks.

    git rm -r -f --cached .

  3. Buat kembali indeks.

    git add .

  4. Buat komit baru

    git commit -m "Removed mylogfile.log"

mAsT3RpEE
sumber
2
Apakah ini benar-benar menghapus file?
Mr_and_Mrs_D
6
Dari GitHub? TIDAK. Jika Anda sudah mendorong ke github, itu tidak akan menghapusnya dari situs. Tetapi itu akan memperbarui repositori git lokal Anda.
mAsT3RpEE
5
Komentar yang Anda hapus sebenarnya lebih banyak dihilangkan :) Masalah dengan solusinya rm --cashedadalah bahwa pada akhirnya akan menghapus file ketika orang menarik - bukan? Dan ini bukan yang diinginkan orang ketika mereka mengatakan "Hapus file dari repositori tanpa menghapusnya dari sistem file lokal ". Sekarang mengapa solusi di atas diterima di luar saya - mungkin OP bekerja sendiri dan tidak pernah menarik? Tidak tahu Saya memahami masalah github "sekali didorong selalu ada" ofc
Mr_and_Mrs_D
Saya tidak berpikir ada solusi 100% kecuali Anda bertanya pada github sendiri. Untuk saat ini berpegang teguh pada ini. Salin file, Tambahkan ke gitignore, lakukan git rm aktual - r, komit, tekan, pulihkan file. Apakah Anda berhasil menemukan solusi lain?
mAsT3RpEE
9
Masalah saya bukan github - itu adalah bahwa file tersebut sebenarnya akan dihapus dari rekan kerja ketika mereka menarik . Saya tidak ingin file dihapus. Ini telah menyebabkan saya masalah besar di masa lalu. Jadi saya bertanya-tanya apakah memang ada solusi yang benar-benar tidak menghapus file. Lihat juga di komentar di jawaban yang diterima: stackoverflow.com/questions/1143796/…
Mr_and_Mrs_D
24

Git memungkinkan Anda mengabaikan file-file itu dengan menganggap mereka tidak berubah. Ini dilakukan dengan menjalankan git update-index --assume-unchanged path/to/file.txtperintah. Setelah menandai file seperti itu, git akan sepenuhnya mengabaikan perubahan apa pun pada file itu; mereka tidak akan muncul ketika menjalankan status git atau git diff, juga tidak akan pernah dilakukan.

(Dari https://help.github.com/articles/ignoring-files )

Karenanya, tidak menghapusnya, tetapi mengabaikan perubahan untuk selamanya. Saya pikir ini hanya berfungsi secara lokal, jadi rekan kerja masih dapat melihat perubahan kecuali jika mereka menjalankan perintah yang sama seperti di atas. (Namun masih perlu memverifikasi ini.)

Catatan: Ini tidak menjawab pertanyaan secara langsung, tetapi didasarkan pada pertanyaan tindak lanjut di komentar dari jawaban lain.

Rystraum
sumber
2
Hm, saya melakukan ini tetapi saya melihat bahwa file tersebut dapat ditimpa jika orang lain membuat perubahan pada repo.
AlxVallejo
17

Jika Anda ingin membuka arsip file dan tidak menghapus dari repo lokal dan jauh kemudian gunakan perintah ini:

git update-index --assume-unchanged  file_name_with_path
Afraz Ahmad
sumber
2
Walaupun ini adalah jawaban yang baik, penting untuk dicatat bahwa ini tidak "membuka kembali" file dalam arti bahwa orang biasanya menggunakan kata itu dengan Git, di mana file yang tidak dilacak adalah yang tidak ada dalam sejarah repositori dan tidak pernah ada . Apa yang dilakukan jawaban ini adalah menyimpan file dalam repositori tetapi mencegah Git dari memperhatikan bahwa telah dilakukan perubahan padanya. Itu memiliki beberapa perbedaan signifikan - yang paling penting, file tersebut masih ada untuk orang lain, dan jika orang lain mengubahnya dan Anda menarik, salinan lokal Anda dapat ditimpa tanpa konfirmasi.
Soren Bjornstad
8

Jawaban di atas tidak bekerja untuk saya. Saya dulu filter-branchmenghapus semua file yang dikomit.

Hapus file dari repositori git dengan:

git filter-branch --tree-filter 'rm  file'

Hapus folder dari repositori git dengan:

git filter-branch --tree-filter 'rm -rf directory'

Ini menghapus direktori atau file dari semua komit.

Anda dapat menentukan komit dengan menggunakan:

git filter-branch --tree-filter 'rm -rf directory' HEAD

Atau rentang:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

Untuk mendorong semuanya ke jarak jauh, Anda dapat melakukan:

git push origin master --force
Martijn Mellens
sumber
2
Ini dikombinasikan dengan git rm -r --cached NAMEadalah trik untuk menghapusnya dari repo git lokal Anda dan mencegahnya memengaruhi siapa pun yang menarik nanti (dengan menghapus riwayat file atau direktori dari git.)
notbad.jpeg
1
Penulisan ulang ini sejarah git dan Anda perlu mendorong --force setelah, ini sedikit keluar dari ruang lingkup dengan pertanyaan saya kira. Pada repo terkenal publik, Anda tidak bisa hanya mengubah garis sejarah seperti itu karena semua orang yang sudah mengkloning repo akan mendapatkan masalah saat menarik.
Guillaume Perrot
0

Abaikan file, hapus file dari git, perbarui git (untuk penghapusan).

Catatan: ini tidak berhubungan dengan riwayat untuk informasi sensitif.

Proses ini pasti membutuhkan beberapa upaya dari apa yang terjadi dengan git. Seiring waktu, setelah mendapatkan itu, saya telah belajar untuk melakukan proses seperti:

1) Abaikan file

  • Tambahkan atau perbarui proyek .gitignoreuntuk mengabaikannya - dalam banyak kasus seperti milik Anda, direktori induk, misalnya log/akan menjadi regex yang digunakan.
  • komit dan dorong .gitignoreperubahan file itu (tidak yakin jika push perlu diingatkan, tidak ada salahnya jika dilakukan).

2) Hapus file dari git (hanya).

  • Sekarang hapus file dari git (hanya) dengan git remove --cached some_dir/
  • Periksa apakah mereka masih tetap lokal (seharusnya!).

3) Tambahkan dan komit perubahan itu (pada dasarnya ini adalah perubahan untuk "menambahkan" menghapus hal-hal, meskipun perintah "tambahkan" membingungkan!)

  • git add .
  • git commit -m"removal"
Michael Durrant
sumber