Przyjęta odpowiedź nie powoduje, że Git „zapomina” o pliku ... ”(historycznie). Powoduje to, że git ignoruje plik w teraźniejszości / przyszłości.
Ta metoda powoduje, że git całkowicie zapomina zignorowane pliki ( przeszłość / teraźniejszość / przyszłość), ale nie robi tego usuwa niczego z katalogu roboczego (nawet po ponownym pobraniu ze zdalnego).
Metoda ta wymaga wykorzystania /.git/info/exclude
(preferowane) lub wcześniej istniejących .gitignore
w każdym z zatwierdzeń, które pliki mają być ignorowane / zapomniane. 1
Wszystkie metody wymuszania git ignorują zachowanie po fakcie skutecznie ponownie zapisują historię, a zatem mają znaczące konsekwencje dla publicznych / wspólnych / wspólnych repozytoriów, które mogą zostać wyciągnięte po tym procesie. 2)
Porady ogólne: zacznij od czystego repozytorium - wszystko zostało popełnione, nic nie czeka w katalogu roboczym lub indeksie i wykonaj kopię zapasową !
Również komentarze / historię zmian od tej odpowiedzi ( oraz historii zmian w tej kwestii ) może być przydatna / oświecenie.
#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
Na koniec postępuj zgodnie z resztą tego przewodnika GitHub (zaczynając od kroku 6), który zawiera ważne ostrzeżenia / informacje o poniższych poleceniach .
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
Inni deweloperzy, którzy pobierają teraz zmodyfikowane zdalne repozytorium, powinni wykonać kopię zapasową, a następnie:
#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
Przypisy
1 Ponieważ /.git/info/exclude
można zastosować do wszystkich historycznych zatwierdzeń przy użyciu powyższych instrukcji, być może szczegóły dotyczące umieszczania .gitignore
pliku w historycznych zatwierdzeniach, które go potrzebują, wykraczają poza zakres tej odpowiedzi. Chciałem, żeby właściwość .gitignore
znajdowała się w głównym zatwierdzeniu, jakby to była pierwsza rzecz, którą zrobiłem. Inni mogą się tym nie przejmować, ponieważ /.git/info/exclude
mogą osiągnąć to samo, bez względu na to, gdzie .gitignore
istnieje w historii zatwierdzeń, a wyraźne ponowne zapisanie historii jest bardzo drażliwym tematem, nawet jeśli zdaje sobie sprawę z konsekwencji .
FWIW, potencjalne metody mogą obejmować git rebase
lub git filter-branch
kopiowanie zewnętrznego .gitignore
do każdego zatwierdzenia, podobnie jak odpowiedzi na to pytanie
2 Wymuszanie zachowania git ignore po fakcie przez zatwierdzenie wyników działania samodzielnego git rm --cached
polecenia może spowodować usunięcie nowo zignorowanego pliku w przyszłych ściągnięciach ze zdalnego sterowania wymuszonego. --prune-empty
Flag w następującej git filter-branch
komendy pozwala uniknąć tego problemu poprzez automatyczne usunięcie poprzedniego „usunąć wszystkie pliki ignorowane” indeksu tylko popełnić. Ponowne pisanie historii gitów zmienia także skróty zatwierdzania, które sieją spustoszenie w przyszłych ściągnięciach z repozytoriów publicznych / wspólnych / współpracujących. Proszę zrozumieć konsekwencje w pełni przed zrobieniem tego do takiego repozytorium. W tym przewodniku GitHub określono:
Powiedz swoim współpracownikom, aby utworzyli bazy , a nie scalali, wszelkie gałęzie, które utworzyli ze starej (skażonej) historii repozytorium. Jedno zatwierdzenie scalania może przywrócić część lub całą skażoną historię, którą właśnie zadałeś sobie trud oczyszczenia.
Alternatywnymi rozwiązaniami, które nie wpływają na zdalne repo, są git update-index --assume-unchanged </path/file>
lub git update-index --skip-worktree <file>
, których przykłady można znaleźć tutaj .
git clean -X
brzmi podobnie, ale nie ma zastosowania w tej sytuacji (gdy pliki są nadal śledzone przez Git). Piszę to dla każdego, kto szuka rozwiązania, które nie podąży niewłaściwą drogą.