Bagaimana membuat Git "lupa" tentang file yang dilacak tetapi sekarang ada di .gitignore?

5403

Ada file yang sedang dilacak git, tetapi sekarang file tersebut ada dalam .gitignoredaftar.

Namun, file itu terus muncul git statussetelah diedit. Bagaimana Anda memaksa gituntuk sepenuhnya melupakannya?

Ivan
sumber
16
git clean -Xterdengar mirip, tetapi tidak berlaku dalam situasi ini (ketika file masih dilacak oleh Git). Saya menulis ini untuk siapa saja yang mencari solusi agar tidak mengikuti rute yang salah.
imz - Ivan Zakharyaschev
35
Satu-satunya jawaban nyata untuk ini ada di bawah, lihat git update-index --assume-unchanged. Solusi ini 1) menyimpan file di server (indeks), 2) memungkinkan Anda memodifikasinya secara bebas.
Qwerty
8
Anda perlu menggunakan --skip-worktree, lihat: stackoverflow.com/questions/13630849/…
Doppelganger
77
Sebuah pertanyaan penting adalah: haruskah file tetap di repositori atau tidak? Misal, jika seseorang baru mengkloning repo, haruskah mereka mendapatkan file atau tidak? Jika YA maka git update-index --assume-unchanged <file>sudah benar dan file akan tetap di repositori dan perubahan tidak akan ditambahkan dengan git add. Jika TIDAK (misalnya itu adalah beberapa file cache, file yang dihasilkan dll), maka git rm --cached <file>akan menghapusnya dari repositori.
Martin
9
@Martin @Qwerty Setiap orang harus berhenti untuk memberi saran tentang --assume-unchangedkinerja untuk mencegah git memeriksa status file-file besar yang dilacak tetapi lebih memilih --skip-worktreeyang untuk file-file terlacak yang dimodifikasi yang tidak ingin dilakukan lagi oleh pengguna. Lihat stackoverflow.com/questions/13630849/…
Philippe

Jawaban:

5706

.gitignoreakan mencegah file yang tidak terlacak ditambahkan (tanpa a add -f) ke set file yang dilacak oleh git, namun git akan terus melacak file apa pun yang sudah dilacak.

Untuk berhenti melacak file, Anda harus menghapusnya dari indeks. Ini dapat dicapai dengan perintah ini.

git rm --cached <file>

Jika Anda ingin menghapus seluruh folder, Anda harus menghapus semua file di dalamnya secara rekursif.

git rm -r --cached <folder>

Penghapusan file dari revisi kepala akan terjadi pada komit berikutnya.

PERINGATAN: Meskipun ini tidak akan menghapus file fisik dari lokal Anda, itu akan menghapus file dari mesin pengembang lain di selanjutnya git pull.

CB Bailey
sumber
55
proses yang berhasil bagi saya adalah 1. melakukan perubahan yang ditangguhkan terlebih dahulu 2. git rm --cached <file> dan melakukan lagi 3. menambahkan file ke .gitignore, periksa dengan status git dan komit lagi
mataal
117
Menambahkan sangat penting. Jika file yang diabaikan akan diubah (tetapi meskipun ini tidak boleh dilakukan), setelah memodifikasi dan mengeksekusi git add .akan ditambahkan ke indeks. Dan commit selanjutnya akan mengkomitnya ke repositori. Untuk menghindari eksekusi ini setelah semua itu mataal mengatakan satu perintah lagi:git update-index --assume-unchanged <path&filename>
Dao
32
Metode @AkiraYamamoto bekerja dengan baik untuk saya juga. Dalam kasus saya, saya menekan output karena repositori saya memiliki ribuan file:git rm -r -q --cached .
Aaron Blenkush
85
Ini akan menghapus file git pull.
Petr Peller
22
git rm --cached <file> cukup hapus file dari repositori, git update-index --assume-unchangeed <file> tidak ditampilkan file dalam perubahan yang tidak dipentaskan dan tidak membuat perubahan baru. Tapi saya ingin GIT JUST IGNORE ISI FILE PLEEEEEASE
Igor Semin
2610

Serangkaian perintah di bawah ini akan menghapus semua item dari Git Index (bukan dari direktori kerja atau repo lokal), dan kemudian memperbarui Git Index, sementara menghormati git mengabaikan. PS. Indeks = Cache

Pertama:

git rm -r --cached . 
git add .

Kemudian:

git commit -am "Remove ignored files"

Atau satu-liner:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"
Matt Frear
sumber
197
Untuk menyoroti perbedaan antara jawaban ini dan yang diterima: Menggunakan perintah ini Anda tidak perlu benar-benar mengetahui file yang terpengaruh. (Bayangkan direktori sementara dengan banyak file acak yang harus dihapus dari indeks).
Ludwig
53
Sama seperti jawaban yang diterima. File akan dihapus pada git pull.
Petr Peller
73
Akan menyenangkan untuk memiliki ini sebagai perintah standar git. Sesuatu seperti git rmignored.
Berik
12
@gudthing -r adalah singkatan dari "recursive"
Mark
14
Dengan ini, Anda dapat menambahkan file tidak berguna lainnya yang saat ini tidak ada .gitignore. Yang mungkin sulit untuk diketahui jika tergantung pada seberapa berisik Anda git statussetelah perintah ini. Perintah yang hanya menghapus file yang baru saja diabaikan akan lebih baik. Itu sebabnya saya lebih suka jawaban Microsoft
KurzedMetal
1122

git update-index melakukan pekerjaan untuk saya:

git update-index --assume-unchanged <file>

Catatan: Solusi ini sebenarnya independen .gitignorekarena gitignore hanya untuk file yang tidak dilacak.

sunting: Karena jawaban ini diposting, sebuah opsi baru telah dibuat dan itu harus lebih disukai. Anda harus menggunakan --skip-worktreeyang untuk file yang dilacak dimodifikasi yang pengguna tidak ingin melakukan lagi dan menjaga --assume-unchangedkinerja untuk mencegah git memeriksa status file yang dilacak besar. Lihat https://stackoverflow.com/a/13631525/717372 untuk rincian lebih lanjut ...

git update-index --skip-worktree <file>
Konstantin
sumber
173
Ini IS jawaban yang sebenarnya. Luar biasa sebenarnya, sangat sederhana, tidak mencemari git statusdan sebenarnya sangat intuitif. Terima kasih.
Pablo Olmos de Aguilera C.
4
Saya mencari rm [...] .solusi yang cukup baik , karena setidaknya saya bisa mengerti cara kerjanya. Saya tidak menemukan dokumentasi yang besar pada apa update-index& --assume-unchangedlakukan. Adakah yang bisa menambahkan bagaimana ini dibandingkan dengan yang lain, karena saya ingin menghapus semua file yang akan diabaikan? (Atau tautan ke penjelasan yang jelas?)
Brady Trainor
25
git update-index --assume-unchanged <path> …akan menyebabkan git mengabaikan perubahan pada jalur yang ditentukan, terlepas dari .gitignore. Jika Anda menarik dari jarak jauh dan bahwa jarak jauh memiliki perubahan ke jalur ini, git akan gagal menggabungkan dengan konflik dan Anda harus menggabungkan secara manual. git rm --cached <path> …akan menyebabkan git berhenti melacak jalur itu. Jika Anda tidak menambahkan path ke .gitignoreAnda akan melihat path di masa depan git status. Opsi pertama memiliki lebih sedikit noise dalam sejarah git commit dan memungkinkan perubahan pada file "diabaikan" untuk didistribusikan di masa depan.
ManicDee
26
Saya cukup bingung bagaimana ini bukan jawaban yang diterima. Jawaban yang diterima di sini jelas tidak menjawab pertanyaan aktual yang diajukan. Jawaban ini mengabaikan perubahan pada file yang ada di repositori sementara tidak menghapusnya dari repositori.
Dave Cooper
11
Jawaban ini akan jauh lebih berguna jika menjelaskan apa yang dilakukan oleh perintah yang diberikan, misalnya bagaimana perbedaannya dari solusi yang disarankan lainnya.
LarsH
283
git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

Ini mengambil daftar file yang diabaikan dan menghapusnya dari indeks, kemudian melakukan perubahan.

thSoft
sumber
7
Jika Anda perlu menghapusnya dari direktori kerja, maka jalankan saja git ls-files --ignored --exclude-standard | xargs git rm . Saya percaya jawaban ini adalah yang terbaik! Karena sangat jelas, Unix-way, dan melakukan hal yang diinginkan secara langsung, tanpa membuat efek samping dari perintah lain yang lebih kompleks.
imz - Ivan Zakharyaschev
6
Jawaban bagus; Namun, perintah akan gagal jika Anda memiliki jalur dengan spasi di tengah, misalnya: "Dir saya / my_ignored_file.txt"
David Hernandez
8
git ls-files --ignored --exclude-standard | sed 's /.*/"&"/' | xargs git rm --cached
David Hernandez
3
git rmakan mengeluh jika ls-filestidak cocok dengan apa pun. Gunakan xargs -r git rm ...untuk memberi tahu agar xargstidak berjalan git rmjika tidak ada file yang cocok.
Wolfgang
10
Akan lebih baik menggunakan \ 0 sebagai pemisah:git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
Nils-o-mat
83

Saya selalu menggunakan perintah ini untuk menghapus file-file yang tidak terlacak. Output satu baris, gaya Unix, bersih:

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

Ini mencantumkan semua file yang Anda abaikan, ganti setiap baris keluaran dengan garis yang dikutip sebagai ganti untuk menangani jalur dengan spasi di dalamnya, dan meneruskan segalanya git rm -r --cacheduntuk menghapus jalur / file / direktori dari indeks.

David Hernandez
sumber
3
Solusi hebat! Bekerja dengan sempurna dan terasa lebih benar bahwa menghapus semua file kemudian menambahkannya kembali.
Jon Catmull
5
Saya juga menemukan ini "terbersih". Mungkin sudah jelas, tetapi hanya menjalankan bagian pertama, git ls-files --ignored --exclude-standarddengan sendirinya memungkinkan Anda memahami / memverifikasi file apa .gitignoreyang akan dikecualikan / dihapus file baru Anda , sebelum Anda melanjutkan dan menjalankan final git rm.
JonBrave
Waspada, gagal pada nama file dengan karakter "jahat" di dalamnya, mis \n. Saya telah memposting solusi saya untuk memenuhi ini.
JonBrave
3
Peringatan lain: saat ditarik, ini akan menyebabkan file dihapus di direktori kerja orang lain, bukan?
LarsH
mencoba, tetapi tidak berhasil untuk saya: sed: 1: "s/.*/": unterminated substitute in regular expressiondalam perintah cabang-filter pada repo dengan spasi. (Tampaknya bekerja di luar cabang-filter). Saya menggunakan jawabangit ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached dari @ JonBrave sebagai gantinya.
goofology
71

pindahkan, komit, lalu pindahkan kembali. Ini telah bekerja untuk saya di masa lalu. Mungkin ada cara 'gittier' untuk mencapai ini.

Joel Hooks
sumber
2
Ini berfungsi dengan baik jika Anda ingin mengabaikan banyak file yang sebelumnya tidak diabaikan. Meskipun seperti yang Anda katakan, mungkin ada cara yang lebih baik untuk ini.
Oskar Persson
Inilah yang saya lakukan. Cukup pindahkan file ke folder di luar git, lalu lakukan "git add.", "Git commit". (Ini menghapus file) kemudian menambahkan gitignore, mereferensikan file / folder, komit lagi untuk menambahkan file gitignore ke git, kemudian salin / kembali ke folder, dan mereka harus diabaikan. NB: akan muncul bahwa file-file itu dihapus dari GIT, jadi mungkin akan menghapusnya dari checkout / tarikan lainnya, seperti yang disebutkan dalam solusi di atas, tetapi karena Anda membuat salinannya pada awalnya, ini bukan masalah IMHO. biarkan seluruh anggota tim tahu ...
Del
Ini adalah cara termudah untuk menyingkirkan folder yang salah komitmen.
Martlark
2
Sepertinya satu-satunya cara, yang bisa saya lihat. Ini adalah bug besar (bukan 'fitur') di git yang segera setelah Anda menambahkan file / folder ke .gitignore, itu tidak hanya mengabaikan file itu sejak saat itu - selamanya - di mana-mana.
JosephK
Ini berhasil setelah saya menambahkannya, dan kemudian setelah fakta menambahkannya ke .gitignore
hanzolo
66

Jika Anda tidak dapat git rmmelacak file karena orang lain mungkin membutuhkannya (peringatan, bahkan jika Anda git rm --cached , ketika orang lain mendapatkan perubahan ini, file mereka akan dihapus dalam sistem file mereka). Ini sering dilakukan karena menimpa file konfigurasi, kredensial otentikasi, dll. Silakan lihat https://gist.github.com/1423106 untuk mengetahui cara orang mengatasi masalah tersebut.

Untuk meringkas:

  • Mintalah aplikasi Anda mencari file config-overide.ini yang diabaikan dan menggunakannya di file config.ini yang sudah ditentukan (atau secara bergantian, cari ~ / .config / myapp.ini, atau $ MYCONFIGFILE)
  • Komit file config-sample.ini dan abaikan file config.ini, buat skrip atau salin file yang serupa jika perlu.
  • Cobalah menggunakan gitattributes clean / smudge magic untuk menerapkan dan menghapus perubahan untuk Anda, misalnya mencoreng file konfigurasi sebagai checkout dari cabang alternatif dan membersihkan file konfigurasi sebagai checkout dari HEAD. Ini adalah hal yang rumit, saya tidak merekomendasikannya untuk pengguna pemula.
  • Simpan file konfigurasi pada cabang deploy yang didedikasikan untuk itu yang tidak pernah digabungkan untuk dikuasai. Saat Anda ingin menggunakan / mengkompilasi / menguji Anda bergabung ke cabang itu dan mendapatkan file itu. Ini pada dasarnya adalah pendekatan noda / bersih kecuali menggunakan kebijakan penggabungan manusia dan modul ekstra-git.
  • Anti-recommentation: Jangan menggunakan asumsi-tidak berubah, itu hanya akan berakhir dengan air mata (karena berbohong pada dirinya sendiri akan menyebabkan hal-hal buruk terjadi, seperti perubahan Anda hilang selamanya).
Seth Robertson
sumber
7
git tidak akan menghapus file, jika itu kotor pada saat penghapusan. Dan jika tidak kotor, mengambil file akan semudah git checkout <oldref> -- <filename>- tetapi kemudian akan diperiksa dan diabaikan.
amenthes
Mengenai catatan terakhir Anda (tentang --assume-unchanged): apakah ini kultus kargo dan harus diberhentikan, atau Anda dapat menjelaskan mengapa (yang saya yakinkan) dan itu menjadi berguna.
RomainValeri
57

Gunakan ini saat:

1. Anda ingin membuka banyak file, atau

2. Anda memperbarui file gitignore Anda

Tautan sumber: http://www.codeblocq.com/2016/01/Untrack-files-already-added-to-git-repository-based-on-gitignore/

Katakanlah Anda telah menambahkan / mengkomit beberapa file ke repositori git Anda dan kemudian menambahkannya ke .gitignore Anda; file-file ini akan tetap ada di indeks repositori Anda. Artikel ini akan kita lihat bagaimana cara menghilangkannya.

Langkah 1: Komit semua perubahan Anda

Sebelum melanjutkan, pastikan semua perubahan Anda dilakukan, termasuk file .gitignore Anda.

Langkah 2: Hapus semuanya dari repositori

Untuk menghapus repo Anda, gunakan:

git rm -r --cached .
  • rm adalah perintah hapus
  • -r akan memungkinkan penghapusan rekursif
  • –Cached hanya akan menghapus file dari indeks. File Anda akan tetap ada di sana.

The rmperintah bisa tak kenal ampun. Jika Anda ingin mencoba apa yang dilakukan sebelumnya, tambahkan -natau--dry-run tandai untuk menguji hal-hal.

Langkah 3: Tambahkan kembali semuanya

git add .

Langkah 4: Berkomitmen

git commit -m ".gitignore fix"

Repositori Anda bersih :)

Dorong perubahan ke kendali jarak jauh Anda untuk melihat perubahannya juga efektif di sana.

Dheeraj Bhaskar
sumber
1
Itu tidak akan menghapus file dari repositori jarak jauh? Bagaimana jika saya ingin menyimpan file dalam repo lokal dan repo jarak jauh tetapi membuat git "lupa" tentang mereka?
Avishay28
AFAIK ini tidak akan menghapus file dari riwayat karena kita tidak menggunakan perintah pengubahan riwayat apa pun (koreksi saya jika saya salah). Ini hanya menambah komit baru dengan menghapus file yang diabaikan di gitignore dari git. File-file itu akan ada di sana di komitmen historis
Dheeraj Bhaskar
49

Saya menyelesaikan ini dengan menggunakan git filter-branch . Perintah persis yang saya gunakan diambil dari halaman manual:

PERINGATAN : ini akan menghapus file dari seluruh riwayat Anda

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

Perintah ini akan membuat ulang seluruh riwayat komit, mengeksekusi git rmsebelum komit masing-masing sehingga akan menyingkirkan file yang ditentukan. Jangan lupa untuk mencadangkannya sebelum menjalankan perintah karena akan hilang.

drrlvn
sumber
9
Ini akan mengubah semua ID komit, sehingga memecah gabungan dari cabang di luar salinan repositori Anda.
bdonlan
19
PERINGATAN: ini akan menghapus file dari seluruh riwayat Anda. Ini adalah apa yang saya cari, untuk menghapus file yang sama sekali tidak perlu dan besar (output yang seharusnya tidak pernah dilakukan) yang sudah lama dilakukan dalam sejarah versi.
zebediah49
48

Apa yang tidak berhasil untuk saya

(Di Linux), saya ingin menggunakan posting di sini yang menyarankan ls-files --ignored --exclude-standard | xargs git rm -r --cachedpendekatan. Namun, (beberapa) file yang akan dihapus memiliki baris baru / LF / \ndalam nama mereka. Tak satu pun dari solusi:

git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

mengatasi situasi ini (dapatkan kesalahan tentang file tidak ditemukan).

Jadi saya menawarkan

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"

Ini menggunakan -zargumen untuk ls-file , dan -0argumen untuk xargs untuk melayani dengan aman / benar untuk karakter "jahat" dalam nama file.

Di halaman manual git-ls-files (1) , ia menyatakan:

Ketika opsi -z tidak digunakan, TAB, LF, dan karakter backslash di pathnames masing-masing direpresentasikan sebagai \ t, \ n, dan \\.

jadi saya pikir solusi saya diperlukan jika nama file memiliki karakter ini di dalamnya.

JonBrave
sumber
1
Bagi saya ini adalah solusi terbaik. Ini memiliki kinerja yang jauh lebih baik daripada a git add .. Ini juga berisi perbaikan terbaik dari beberapa komentar di atas.
Nils-o-mat
Bisakah Anda menambahkan ini git commit -am "Remove ignored files"setelah jawaban Anda? Gabungan jawaban Anda membuat saya melalui beberapa hal: j
kando
Saya tidak mengerti tujuannya git commit -a. Bagi saya git rm --cachedmempengaruhi persis indeks sehingga tidak perlu melakukan stage file setelah ...
Jean Paul
23
  1. Perbarui .gitignorefile Anda - misalnya, tambahkan folder yang tidak ingin Anda lacak .gitignore.

  2. git rm -r --cached .- Hapus semua file yang dilacak, termasuk yang diinginkan dan yang tidak diinginkan. Kode Anda akan aman selama Anda telah menyimpan secara lokal.

  3. git add .- Semua file akan ditambahkan kembali, kecuali yang ada di .gitignore.


Kiat ujung ke @AkiraYamamoto karena mengarahkan kami ke arah yang benar.

Chen_Wayne
sumber
1
Bagaimana kalau diturunkan karena fakta bahwa itu tidak akan benar-benar berfungsi karena Anda memerlukan -r untuk menjalankan rm secara rekursif :) (Seseorang tidak menyalin dengan benar)
Aran Mulholland
1
Peringatan: Teknik ini sebenarnya tidak menyebabkan git mengabaikan file, tetapi justru menyebabkan git menghapus file. Itu berarti jika Anda menggunakan solusi ini, kapan saja orang lain melakukan git pull, file tersebut akan terhapus. Jadi itu sebenarnya tidak diabaikan. Lihat solusi yang menyarankan git update-index --assume-tidak berubah sebagai solusi untuk pertanyaan awal.
orrd
16

Saya pikir, mungkin git tidak dapat sepenuhnya melupakan file karena konsepsinya ( bagian "Snapshots, Not Differences" ).

Masalah ini tidak ada, misalnya, saat menggunakan CVS. CVS menyimpan informasi sebagai daftar perubahan berbasis file. Informasi untuk CVS adalah seperangkat file dan perubahan yang dibuat untuk setiap file dari waktu ke waktu.

Tetapi di Git setiap kali Anda berkomitmen, atau menyimpan keadaan proyek Anda, pada dasarnya mengambil gambar apa semua file Anda pada saat itu dan menyimpan referensi ke snapshot itu. Jadi, jika Anda menambahkan file sekali, itu akan selalu ada di snapshot itu.

2 artikel ini sangat membantu saya:

git menganggap-tidak berubah vs melewatkan-worktree dan Cara mengabaikan perubahan dalam file yang dilacak dengan Git

Mendasarkan pada itu saya melakukan hal berikut, jika file sudah dilacak:

git update-index --skip-worktree <file>

Mulai saat ini semua perubahan lokal dalam file ini akan diabaikan dan tidak akan pergi ke remote. Jika file diubah di remote, konflik akan muncul, kapan git pull. Stash tidak akan berfungsi. Untuk mengatasinya, salin konten file ke tempat yang aman dan ikuti langkah-langkah ini:

git update-index --no-skip-worktree <file>
git stash
git pull 

Konten file akan diganti oleh konten jarak jauh. Rekatkan perubahan Anda dari tempat yang aman ke file dan lakukan lagi:

git update-index --skip-worktree <file>

Jika semua orang, yang bekerja dengan proyek, akan melakukan git update-index --skip-worktree <file>, masalah denganpull harus tidak ada. Solusi ini OK untuk file konfigurasi, ketika setiap pengembang memiliki konfigurasi proyek sendiri.

Sangat tidak nyaman untuk melakukan ini setiap kali, ketika file telah diubah pada remote, tetapi dapat melindunginya dari menimpa dengan konten jarak jauh.

Boolean_Type
sumber
16

Lakukan langkah-langkah berikut secara seri, Anda akan baik-baik saja.

1. menghapus file yang salah ditambahkan dari direktori / penyimpanan . Anda dapat menggunakan perintah "rm -r" (untuk linux) atau menghapusnya dengan menjelajahi direktori. Atau pindahkan ke lokasi lain di PC Anda. [Anda mungkin harus menutup IDE jika dijalankan untuk memindahkan / menghapus ]

2. Tambahkan file / direktori ke gitignorefile sekarang dan simpan.

3.Sekarang menghapusnya dari cache git dengan menggunakan perintah ini (jika ada lebih dari satu direktori, hapus satu per satu dengan berulang kali mengeluarkan perintah ini)

git rm -r --cached path-to-those-files

4.Now melakukan suatu komit dan dorongan , menggunakan perintah ini. Ini akan menghapus file-file itu dari git remote dan membuat git berhenti melacak file-file itu.

git add .
git commit -m "removed unnecessary files from git"
git push origin
Shamsul Arefin Sajib
sumber
13

Jawaban salin / tempel adalah git rm --cached -r .; git add .; git status

Perintah ini akan mengabaikan file yang telah dikomit ke repositori Git tetapi sekarang kami telah menambahkannya ke .gitignore.

youhans
sumber
9

Jawaban dari Matt Fear adalah IMHO paling efektif. Berikut ini hanyalah skrip PowerShell bagi mereka yang berada di windows untuk hanya menghapus file dari repo git mereka yang cocok dengan daftar pengecualian mereka.

# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles =  gc .gitignore | ?{$_ -notmatch  "#"} |  ?{$_ -match  "\S"} | % {
                    $ignore = "*" + $_ + "*"
                    (gci -r -i $ignore).FullName
                }
$ignoreFiles = $ignoreFiles| ?{$_ -match  "\S"}

# Remove each of these file from Git 
$ignoreFiles | % { git rm $_}

git add .
Ameer Deen
sumber
Dalam situasi apa daftar file ini tidak akan sama dengan --cached rekursif?
John Zabroski
8

Pindahkan atau salin file ke lokasi yang aman, sehingga Anda tidak kehilangannya. Kemudian git file dan komit. File masih akan muncul jika Anda kembali ke salah satu dari komit sebelumnya, atau cabang lain di mana itu belum dihapus. Namun, di semua komitmen di masa mendatang, Anda tidak akan melihat file lagi. Jika file di git diabaikan, maka Anda dapat memindahkannya kembali ke folder, dan git tidak akan melihatnya.

Apreche
sumber
34
git rm --cachedakan menghapus file dari indeks tanpa menghapusnya dari disk, jadi tidak perlu memindahkan / menyalinnya
bdonlan
7

Menggunakan git rm --cachedperintah tidak menjawab pertanyaan awal:

Bagaimana Anda memaksa gituntuk sepenuhnya melupakan [file]?

Bahkan, solusi ini akan menyebabkan file dihapus di setiap instance repositori lainnya ketika menjalankan git pull!

Cara yang benar untuk memaksa git melupakan file didokumentasikan oleh GitHub di sini .

Saya merekomendasikan membaca dokumentasi, tetapi pada dasarnya:

git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
git push origin --force --all
git push origin --force --tags
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

ganti saja full/path/to/filedengan path lengkap file. Pastikan Anda telah menambahkan file ke file Anda .gitignore.

Anda juga perlu (sementara) mengizinkan push-push tidak-maju ke repositori Anda , karena Anda mengubah riwayat git Anda.

Skeets
sumber
5

The BFG dirancang khusus untuk menghapus data yang tidak diinginkan seperti file besar atau password dari repo Git, sehingga memiliki bendera sederhana yang akan menghapus setiap sejarah besar (tidak-di-saat-komit) file: '--strip-blobs- lebih besar dari'

$ java -jar bfg.jar --strip-blobs-bigger-than 100M

Jika Anda ingin menentukan file dengan nama, Anda dapat melakukannya juga:

$ java -jar bfg.jar --delete-files *.mp4

BFG 10-1000x lebih cepat dari git-cabang filter, dan umumnya lebih mudah digunakan - lihat petunjuk penggunaan lengkap dan contoh untuk detail lebih lanjut.

Sumber: https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html

Meir Gerenstadt
sumber
5

Jika Anda tidak ingin menggunakan CLI dan bekerja di Windows, solusi yang sangat sederhana adalah dengan menggunakan TortoiseGit , ia memiliki Tindakan "Hapus (tetap lokal)" di menu yang berfungsi dengan baik.

Peter T.
sumber
5

Saya menyukai jawaban JonBrave tetapi saya memiliki cukup banyak direktori kerja yang komit yang membuat saya sedikit takut, jadi inilah yang saya lakukan:

git config --global alias.exclude-ignored '! git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls-files -z --ignored --exclude-standard | xargs -0 git stage && git stage .gitignore && git commit -m "gitignore baru dan hapus file yang diabaikan dari indeks" '

memecahnya:

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached 
git ls-files -z --ignored --exclude-standard | xargs -0 git stage 
git stage .gitignore 
git commit -m "new gitignore and remove ignored files from index"
  • hapus file yang diabaikan dari indeks
  • tahap .gitignore dan file yang baru saja Anda hapus
  • melakukan
Jay Irvine
sumber
4

Ini bukan lagi masalah di git terbaru (v2.17.1 pada saat penulisan).

Yang .gitignoreterakhir mengabaikan file yang dilacak tetapi dihapus. Anda dapat menguji ini sendiri dengan menjalankan skrip berikut. git statusPernyataan akhir harus melaporkan "tidak ada komitmen".

# Create empty repo
mkdir gitignore-test
cd gitignore-test
git init

# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial

# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore

# Remove the file and commit
git rm file
git commit -m "removed file"

# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status
Lloyd
sumber
Aku senang git sekarang melakukan ini. Namun, OP bertanya tentang tidak melacak modifikasi pada file yang ada di .gitignore, bukan file yang dihapus masih menunjukkan status.
mrturtle
2

Dalam hal sudah berkomitmen DS_Store:

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch

Abaikan mereka dengan:

echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

Akhirnya, buatlah komitmen!


sumber
2

Khusus untuk file berbasis IDE, saya menggunakan ini:

Misalnya slnx.sqlite, saya baru saja menghapusnya sepenuhnya seperti berikut:

git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"

Perlu diingat bahwa beberapa file tersebut menyimpan beberapa pengaturan pengguna lokal dan preferensi untuk proyek (seperti file apa yang Anda buka). Jadi setiap kali Anda menavigasi atau melakukan beberapa perubahan pada IDE Anda, file itu diubah dan karenanya memeriksa dan ditampilkan karena ada perubahan yang tidak dikomit.

curiousBoy
sumber
2

Jawaban yang diterima tidak "membuat Git " lupa " tentang file ..." (secara historis). Itu hanya membuat git diabaikan file di masa sekarang / masa depan.

Metode ini membuat git benar-benar lupa file yang diabaikan ( dulu / sekarang / masa depan), tetapi tidak menghapus apa pun dari direktori kerja (bahkan ketika ditarik kembali dari jarak jauh).

Metode ini membutuhkan penggunaan /.git/info/exclude(lebih disukai) ATAU yang sudah ada .gitignore di semua komit yang memiliki file untuk diabaikan / dilupakan. 1

Semua metode penegakan git mengabaikan perilaku setelah-fakta-secara efektif menulis ulang sejarah dan dengan demikian memiliki konsekuensi yang signifikan untuk setiap repositori publik / bersama / kolaboratif yang mungkin ditarik setelah proses ini. 2

Saran umum: mulai dengan repo bersih - semua yang dilakukan, tidak ada yang tertunda di direktori atau indeks kerja, dan buat cadangan !

Juga, komentar / riwayat revisi dari jawaban ini ( dan riwayat revisi dari pertanyaan ini ) mungkin berguna / mencerahkan.

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch

git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch

git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#Commit to prevent working directory data loss!
#this commit will be automatically deleted by the --prune-empty flag in the following command
#this command must be run on each branch

git commit -m "ignored index"

#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits.  If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command

git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all

#List all still-existing files that are now ignored properly
#if this command returns nothing, it's time to restore from backup and start over
#this command must be run on each branch

git ls-files --other --ignored --exclude-standard

Terakhir, ikuti panduan GitHub lainnya ini (mulai dari langkah 6) yang mencakup peringatan / informasi penting tentang perintah di bawah ini .

git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

Pengembang lain yang menarik dari repo jarak jauh yang dimodifikasi sekarang harus membuat cadangan lalu:

#fetch modified remote

git fetch --all

#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed

git reset FETCH_HEAD

Catatan kaki

1 Karena /.git/info/excludedapat diterapkan pada semua commit historis menggunakan instruksi di atas, mungkin detail tentang memasukkan .gitignorefile ke dalam commit historis yang memerlukannya berada di luar cakupan jawaban ini. Saya ingin yang tepat .gitignoreberada di root commit, seolah-olah itu adalah hal pertama yang saya lakukan. Orang lain mungkin tidak peduli karena /.git/info/excludedapat mencapai hal yang sama di mana pun .gitignoreada dalam sejarah commit, dan jelas menulis ulang sejarah adalah subjek yang sangat sensitif, bahkan ketika menyadari konsekuensi .

FWIW, metode potensial dapat mencakup git rebaseatau git filter-branchyang menyalin eksternal .gitignore ke setiap komit, seperti jawaban untuk pertanyaan ini

2 Menegakkan perilaku git abaikan setelah fakta dengan melakukan hasil dari git rm --cachedperintah mandiri dapat mengakibatkan penghapusan file yang baru-baru ini diabaikan di tarikan di masa depan dari remote yang didorong paksa. The --prune-emptybendera di berikut git filter-branchperintah menghindari masalah ini dengan secara otomatis menghapus sebelumnya "menghapus semua file diabaikan" Indeks hanya komit. Menulis ulang sejarah git juga mengubah hash, yang akan mendatangkan malapetaka di masa depan dari repositori publik / bersama / kolaboratif. Harap pahami konsekuensi sepenuhnya sebelum melakukan ini pada repo tersebut. Panduan GitHub ini menetapkan yang berikut:

Beri tahu kolaborator Anda untuk rebase , bukan menggabungkan, cabang apa pun yang mereka buat dari riwayat repositori Anda yang lama (ternoda). Satu komit gabungan dapat memperkenalkan kembali sebagian atau seluruh sejarah yang tercemar yang baru saja Anda susahkan untuk dibersihkan.

Solusi alternatif yang tidak memengaruhi repo jarak jauh adalah git update-index --assume-unchanged </path/file>atau git update-index --skip-worktree <file>, contohnya dapat ditemukan di sini .

goofologi
sumber
0

Jika ada yang mengalami kesulitan di Windows dan Anda ingin mengabaikan seluruh folder, 'cd' untuk yang diinginkan 'folder' dan lakukan 'Git Bash Here'.

git ls-files -z | xargs -0 git update-index --assume-unchanged
RajVimalC
sumber
0

Dalam kasus saya di sini, saya memiliki beberapa file .lock di beberapa direktori yang perlu saya hapus. Saya menjalankan yang berikut ini dan berhasil tanpa harus masuk ke setiap direktori untuk menghapusnya:

git rm -r --cached **/*.lock

Melakukan ini masuk ke setiap folder di bawah 'root' di mana saya berada dan mengecualikan semua file yang cocok dengan pola.

Semoga ini bisa membantu orang lain!

DC. Katakanlah
sumber