Как удалить файлы, которые перечислены в .gitignore, но все еще находятся в хранилище?


327

У меня есть несколько файлов в моем хранилище, которые следует игнорировать, я добавил их в .gitignore, но, конечно, они не удалены из моего хранилища.

Итак, мой вопрос: есть ли волшебная команда или скрипт, использующий фильтр-ветку, который может переписать мою историю и легко удалить все эти файлы? Или просто команда, которая создаст коммит, который удалит их?





ВНИМАНИЕ: Хотя это не удалит физический файл из вашего локального, он будет удалять файлы с машин других разработчиков при следующем git pull. Как заставить Git «забыть» о файле, который отслеживался, но теперь находится в .gitignore?
Крис Руф

@Stevoisiak, это не дубликат этого вопроса, потому что он спрашивает обо ВСЕХ проигнорированных файлах, и у него также есть лучший ответ, чем любой из подобных вопросов.
Omn

Ответы:


438

Вы можете удалить их из хранилища вручную:

git rm --cached file1 file2 dir/file3

Или, если у вас много файлов:

git rm --cached `git ls-files -i --exclude-from=.gitignore`

Но это не работает в Git Bash на Windows. Выдает сообщение об ошибке. Следующее работает лучше:

git ls-files -i --exclude-from=.gitignore | xargs git rm --cached  

Что касается переписывания всей истории без этих файлов, я очень сомневаюсь, что есть автоматический способ сделать это.
И мы все знаем, что переписывать историю плохо, не так ли? :)


2
К сожалению, команда Git Bash на Windows не работает с путями, которые содержат пробелы
Нейт Банди

19
@ Кекс спасибо. git ls-files -i -z --exclude-from=.gitignore | xargs -0 git rm --cachedкажется,
Нейт Банди

3
Я застрял с той же проблемой на окнах. Я использую PowerShell, и в моем случае я получил третью команду с подсказкой @ samy-dindane и превратил ее в foreach. Так и сталоgit ls-files -i --exclude-from=.gitignore | %{git rm --cached $_}
дигаоматиас

1
"git ls-files -i --exclude-from = .gitignore" очень полезна, она говорит мне, какие файлы исключены .ignore.
Оуэн Цао

1
Я был счастлив найти эти команды, НО это действительно не удаляет файлы из хранилища. Когда я удалил 2300 кБ изображений, размер хранилища упал только на 10 кБ. Так что его нельзя использовать, например, чтобы сделать хранилище меньше и быстрее переносить.
Ян Потужник

343

Самый простой способ, который работает на любой ОС, это сделать

git rm -r --cached .
git add .
git commit -m "Removing all files in .gitignore"

Вы в основном читали все файлы, кроме тех, что в .gitignore


1
Как это влияет на других пользователей в репо, выполняющих извлечение - когда я читаю его, папка, которую мы больше не хотим отслеживать, удаляется ??? Как мы можем предотвратить это - мы просто хотим отследить
snh_nl

Это пометит все файлы как измененные с ложным сообщением фиксации!
Хайдар Зейнеддин

3
что вы подразумеваете под фальшивым коммитом? Это реальное сообщение коммита: P Конечно, вы можете изменить сообщение, в зависимости от ваших потребностей ...
gtatr

1
Для полноты картины вам нужна команда git push в конце.
Мариуш Бялобжески

1
Не делайте этого, он удалит историю из всех файлов
agrath

145

Поскольку файлы в .gitignore не отслеживаются, вы можете использовать команду git clean для рекурсивного удаления файлов, которые не находятся под контролем версий.

Используйте git clean -xdnдля выполнения пробного запуска и посмотрите, что будет удалено.
Затем используйте git clean -xdfдля его выполнения.

В основном, git clean -hили man git-clean(в Unix) окажет вам помощь.

Помните, что эта команда также удалит новые файлы , которые не находятся в промежуточной области.

Надеюсь, поможет.


6
Это должен быть принятый ответ. Это на самом деле работает (у меня принятый ответ не работает, на macOS), и это намного чище.
Роджер Оба

25
Этот ответ не относится - ОП говорит файлы в .gitignore которые отслеживаются.
Кен Уильямс

20
BEWARE! Это навсегда удаляет все неотслеживаемые файлы, а не просто удаляет из ветки
Эммануэль

1
git clean -xdnсухой прогон , который не будет удалять. следующий будет.
JohnZaj

17
-1: Это очень вводящий в заблуждение ответ - оригинальный постер хотел удалить из репозитория, а не удалять файлы полностью. Я был близок к удалению загрузки динамических файлов, необходимых для моей IDE, но не для того, чтобы находиться в репозитории.
Прошение

4

Я сделал очень простое решение, управляя выводом оператора .gitignore с помощью sed:

cat .gitignore | sed '/^#.*/ d' | sed '/^\s*$/ d' | sed 's/^/git rm -r /' | bash

Объяснение:

  1. распечатать файл .gitignore
  2. удалить все комментарии из печати
  3. удалить все пустые строки
  4. добавить 'git rm -r' в начало строки
  5. выполнить каждую строку.

10
sedэто просто?
Игорь Ганапольский

0

В Linux вы можете использовать этот комманд:

Например, я хочу удалить "* .py ~", поэтому моя команда должна быть ==>

find . -name "*.py~" -exec rm -f {} \;


-3

Git будет игнорировать файлы, соответствующие шаблону .gitignore, после добавления его в .gitignore.

Но файлы, которые уже существовали в хранилище, будут все еще в.

используйте git rm files_ignored; git commit -m 'rm no use files'для удаления игнорируемых файлов.


4
Их много, есть ли способ удалить их без указания их имен?
Intrepidd
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.