Прийнята відповідь не "змушує Git " забути " про файл ..." (історично). Це лише змушує git ігнорувати файл у теперішньому / майбутньому.
Цей метод змушує git повністю забути проігноровані файли ( минуле / теперішнє / майбутнє), але нічого не видаляє з робочого каталогу (навіть при повторному витягуванні з віддаленого).
Цей метод вимагає використання /.git/info/exclude
(переважно) або вже існуючий .gitignore
в усіх коммітов , які мають файли , які будуть ігноруватися / забуто. 1
Усі методи примусового ігнорування поведінки після фактично переписують історію і, таким чином, мають значні наслідки для будь-яких публічних / спільних / спільних / репортажів, які можуть бути витягнуті після цього процесу. 2
Загальна порада: почніть з чистого репо-репортажу - все, що зроблено, нічого не очікує на робочий каталог чи індекс, і зробіть резервну копію !
Крім того , коментарі / історія змін з цієї відповіді ( і історії змін по цьому питанню ) , може бути корисною / просвіщаючи.
#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
Нарешті, дотримуйтесь решти цього посібника GitHub (починаючи з кроку 6), який включає важливі попередження / інформацію про команди нижче .
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
Інші розробники, які витягуються з тепер модифікованого віддаленого репо, повинні зробити резервну копію, а потім:
#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
Виноски
1 Оскільки /.git/info/exclude
може застосовуватися до всіх історичних комісій за допомогою наведених вище вказівок, можливо, деталі щодо введення .gitignore
файлу в історичні комісії, які потребують цього, виходять за межі цієї відповіді. Я хотів, щоб це було належним .gitignore
чином у корені, так, ніби це було перше, що я зробив. Іншим може бути байдуже, оскільки вони /.git/info/exclude
можуть здійснити те саме, незалежно від того, де .gitignore
існує історія вчинення, і, очевидно, переписування історії є дуже чутливою темою, навіть коли знають про наслідки .
FWIW, потенційні методи можуть включати git rebase
або git filter-branch
копіювати зовнішнє .gitignore
у кожен комітет, як відповіді на це питання
2 Посилення поведінки ігнорування git після факту шляхом виконання результатів автономної git rm --cached
команди може призвести до видалення знову ігнорованого файлу у майбутніх витягах із пульта дистанційного керування. --prune-empty
Прапор в наступній git filter-branch
команді дозволяє уникнути цієї проблеми шляхом автоматичного видалення попереднього «видалити всі ігноровані файли» індекс тільки зробити. Перезапис історії git також змінює хеши, які спричинять шкоду на майбутніх репортажах з громадських / спільних / спільних / репортажів. Будь ласка, розумійте наслідки, перш ніж робити це до такого репо. Цей посібник GitHub визначає наступне:
Повідомте своїм співробітникам перезавантажувати , а не об’єднувати будь-які гілки, які вони створили з вашої старої (зіпсованої) історії сховища. Одне об'єднання злиття може знову ввести частину чи всю зіпсовану історію, яку ви просто вирішили очистити.
Альтернативні рішення, які не впливають на віддалений репо, є git update-index --assume-unchanged </path/file>
або git update-index --skip-worktree <file>
, приклади яких можна знайти тут .
git clean -X
звучить схоже, але це не застосовується в цій ситуації (коли файли все ще відслідковуються Git). Я пишу це для тих, хто шукає рішення не слідувати неправильному маршруту.