Как заставить Git «забыть» о файле, который отслеживался, но теперь находится в .gitignore?


5407

Существует файл, который отслеживался git, но теперь этот файл находится в .gitignoreсписке.

Однако этот файл продолжает появляться git statusпосле того, как он отредактирован. Как вы заставляете gitполностью забыть об этом?


16
git clean -Xзвучит похоже, но это не относится к этой ситуации (когда файлы все еще отслеживаются Git). Я пишу это для тех, кто ищет решение не следовать по неверному маршруту.
imz - Иван Захарящев

35
Единственный реальный ответ на это внизу, понимаете git update-index --assume-unchanged. Это решение 1) хранит файл на сервере (индекс), 2) позволяет свободно изменять его локально.
Qwerty

8
Вы должны использовать --skip-worktree, см .: stackoverflow.com/questions/13630849/…
Doppelganger

77
Важный вопрос: файл должен оставаться в хранилище или нет? Например, если кто-то новый клонирует репо, он должен получить файл или нет? Если ДА, значит, git update-index --assume-unchanged <file>файл правильный и файл останется в хранилище, а изменения не будут добавлены git add. Если НЕТ (например, это был какой-то кеш-файл, сгенерированный файл и т. Д.), Он git rm --cached <file>будет удален из хранилища.
Мартин

9
@Martin @Qwerty Каждый должен остановиться, чтобы посоветовать, из-за --assume-unchangedчего производительность не позволяет git проверять состояние больших отслеживаемых файлов, но предпочитает --skip-worktreeдля измененных отслеживаемых файлов, которые пользователь больше не хочет фиксировать. См. Stackoverflow.com/questions/13630849/…
Филипп

Ответы:


5710

.gitignoreпредотвратит добавление неотслеживаемых файлов (без add -f) в набор файлов, отслеживаемых git, однако git продолжит отслеживать любые файлы, которые уже отслеживаются.

Чтобы остановить отслеживание файла, вам нужно удалить его из индекса. Это может быть достигнуто с помощью этой команды.

git rm --cached <file>

Если вы хотите удалить всю папку, вам нужно рекурсивно удалить все файлы в ней.

git rm -r --cached <folder>

Удаление файла из заголовка ревизии произойдет при следующем коммите.

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


55
Процесс, который работал для меня: 1. сначала зафиксировать ожидающие изменения 2. git rm --cached <file> и зафиксировать снова 3. добавить файл в .gitignore, проверить состояние git и повторить снова
mataal

117
Очень важное добавление. Если игнорируемый файл будет изменен (но, несмотря на это, его не следует фиксировать), после изменения и выполнения git add .он будет добавлен в индекс. И следующий коммит передаст его в хранилище. Чтобы избежать этого, сразу после того, как этот матал произнес еще одну команду:git update-index --assume-unchanged <path&filename>
Дао

32
Метод @AkiraYamamoto хорошо работал и для меня. В моем случае я подавил вывод, так как в моем хранилище были тысячи файлов:git rm -r -q --cached .
Аарон Бленкуш,

85
Это удалит файл, git pullхотя.
Петр Пеллер

22
git rm --cached <file> просто удаляет файл из репозитория, git update-index --assume-unchanged <file> не показывает файл в неустановленных изменениях и не выполняет извлечение новых изменений. Но я хочу, чтобы GIT ПРОСТО ИГНОРИРОВАЛ СОДЕРЖАНИЕ ФАЙЛА
Игорь Семин

2613

Приведенная ниже серия команд удалит все элементы из индекса Git (не из рабочего каталога или локального репо), а затем обновит индекс Git, соблюдая при этом git игнорирует. PS. Индекс = Кэш

Первый:

git rm -r --cached . 
git add .

Затем:

git commit -am "Remove ignored files"

Или однострочник:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"

197
Чтобы подчеркнуть разницу между этим ответом и принятым: используя эти команды, вам не нужно знать, какие файлы затронуты. (Представьте себе временный каталог с большим количеством случайных файлов, которые должны быть удалены из индекса).
Людвиг

53
То же, что принятый ответ. Файлы будут удалены на git pull.
Петр Пеллер

73
Было бы неплохо иметь это как стандартную команду git. Нечто подобное git rmignored.
Берик

12
@gudthing -r означает "рекурсивный"
Марк

14
При этом вы можете добавить другие бесполезные файлы, которых в данный момент нет .gitignore. Что может быть трудно выяснить, если это зависит от того, какой у вас шум git statusпосле этой команды. Команда, которая удаляет только недавно проигнорированные файлы, была бы лучше. Вот почему я предпочитаю ответ
thSoft

1123

git update-index делает всю работу за меня:

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

Примечание. Это решение фактически не зависит от .gitignoregitignore только для неотслеживаемых файлов.

редактировать: так как этот ответ был опубликован, новая опция была создана, и это должно быть предпочтительным. Вы должны использовать --skip-worktreeэто для модифицированных отслеживаемых файлов, которые пользователь больше не хочет фиксировать, и сохранять --assume-unchangedпроизводительность, чтобы git не проверял состояние больших отслеживаемых файлов. См. Https://stackoverflow.com/a/13631525/717372 для получения более подробной информации ...

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

173
Это IS реальный ответ. Удивительно на самом деле, очень просто, не загрязняет окружающую среду git statusи на самом деле очень интуитивно. Спасибо.
Пабло Олмос де Агилера К.

4
Я выбрал достаточно хорошее rm [...] .решение, так как, по крайней мере, смогу понять, как оно работает. Я не нашел отличной документации о том, что update-indexи как --assume-unchangedделать. Может кто-нибудь добавить, как это сравнивается с другим, в котором я хотел бы удалить все файлы, которые были бы проигнорированы? (Или ссылка на четкое объяснение?)
Брейди Трейнор

25
git update-index --assume-unchanged <path> …заставит git игнорировать изменения в указанных путях, независимо от .gitignore. Если вы извлекаете данные с удаленного компьютера, и этот пульт имеет изменения в этом пути, git не сможет выполнить слияние с конфликтом, и вам потребуется выполнить слияние вручную. git rm --cached <path> …заставит git перестать отслеживать этот путь. Если вы не добавите путь к .gitignoreвам, вы увидите путь в будущем git status. Первый вариант имеет меньше шума в истории коммитов git и позволяет распространять изменения в «игнорируемом» файле в будущем.
ManicDee

26
Я совершенно сбит с толку относительно того, как это не принятый ответ. Принятый ответ здесь явно не отвечает на фактически задаваемый вопрос. Этот ответ игнорирует изменения в файле, находящемся в хранилище, но не удаляет его из хранилища.
Дейв Купер

11
Этот ответ был бы намного полезнее, если бы он точно объяснил, что делает данная команда, например, чем она отличается от других предлагаемых решений.
LarsH

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

Это берет список игнорируемых файлов и удаляет их из индекса, а затем фиксирует изменения.


7
Если вам тоже нужно удалить их из рабочего каталога, просто запустите git ls-files --ignored --exclude-standard | xargs git rm . Я считаю этот ответ лучшим! Потому что это очень понятно, Unix-способ, и делает желаемую вещь прямым способом, без компоновки побочных эффектов других, более сложных команд.
imz - Иван Захарящев

6
Отличный ответ; однако команда не выполнится, если у вас есть пути с пробелами посередине, например: «My dir / my_ignored_file.txt»
Дэвид Эрнандес,

8
git ls-files --ignored --exclude-standard | sed 's /.*/"&"/' | xargs git rm --cached
Дэвид Эрнандес

3
git rmбудет жаловаться, если ls-filesне соответствует ничего. Используйте, xargs -r git rm ...чтобы запретить xargsзапуск, git rmесли не найдено ни одного файла.
Вольфганг

10
Было бы лучше использовать \ 0 в качестве разделителя:git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
Nils-o-mat

83

Я всегда использую эту команду, чтобы удалить эти неотслеживаемые файлы. Однострочный, Unix-стиль, чистый вывод:

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

Он перечисляет все ваши игнорируемые файлы, заменяет каждую строку вывода строкой в ​​кавычках вместо этого, чтобы обрабатывать пути с пробелами внутри, и передает все, git rm -r --cachedчтобы удалить пути / файлы / каталоги из индекса.


3
Отличное решение! Работал отлично и чувствует себя более правильным, чем удаление всех файлов, а затем добавление их обратно.
Джон Кэтмалл

5
Я тоже нашел этот "самый чистый". Это может быть очевидно, но только выполнение первой части само git ls-files --ignored --exclude-standardпо себе позволяет сначала понять / проверить, какие файлы .gitignoreбудут исключены / удалены вашими новыми , прежде чем вы приступите к выполнению финальной части git rm.
JonBrave

Имейте в виду, происходит сбой в именах файлов с определенными «неприятными» символами в них, например \n. Я отправил свое решение, чтобы обслужить это.
JonBrave

3
Еще одна оговорка: при извлечении это приведет к удалению файла в других рабочих каталогах, верно?
LarsH

пытался, но у меня не получилось: sed: 1: "s/.*/": unterminated substitute in regular expressionв команде filter-branch на репо с пробелами. (Казалось бы, работать за пределами ответвления фильтра, хотя). Я использовал git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cachedот @ JonBrave в ответ вместо этого.
Гофология

71

уберите это, передайте, затем верните это обратно. Это работало для меня в прошлом. Вероятно, есть «более мерзкий» способ сделать это.


2
Это отлично работает, если вы хотите игнорировать кучу файлов, которые ранее не игнорировались. Хотя, как вы сказали, возможно, есть лучший способ для этого.
Оскар Перссон

Это именно то, что я сделал. Просто переместите файлы в папку за пределами git, затем выполните «git add.», «Git commit». (Это удалило файлы), затем добавьте gitignore, ссылаясь на файлы / папки, подтвердите снова, чтобы добавить файл gitignore в git, затем скопируйте / переместите обратно в папки, и их следует игнорировать. NB. Похоже, что файлы были удалены из GIT, поэтому, вероятно, удалят их из других проверок / извлечений, как упоминалось в вышеупомянутых решениях, но, поскольку вы изначально делаете их копии, это не является большой проблемой IMHO. просто сообщите остальной команде ...
Del

Это самый простой способ избавиться от неверно зафиксированных папок.
Martlark

2
Кажется, это единственный путь, который я вижу. Это серьезная ошибка (не «функция») в git, что, как только вы добавляете файл / папку в .gitignore, он не просто игнорирует этот файл с этого момента - навсегда - везде.
JosephK

Это сработало после того, как я добавил их, а затем по факту добавил их в .gitignore
hanzolo

66

Если вы не можете git rmотследить файл, потому что это может понадобиться другим людям (предупреждение, даже если вы git rm --cached , когда кто-то другой получит это изменение, его файлы будут удалены в их файловой системе). Это часто делается из-за переопределения файла конфигурации, учетных данных аутентификации и т. Д. Пожалуйста, посмотрите на https://gist.github.com/1423106 способы, которыми люди обошли проблему.

Обобщить:

  • Попросите ваше приложение найти пропущенный файл config-overide.ini и использовать его поверх зафиксированного файла config.ini (или, альтернативно, найдите ~ / .config / myapp.ini или $ MYCONFIGFILE)
  • Зафиксируйте файл config-sample.ini и проигнорируйте файл config.ini, при необходимости создайте скрипт или аналогичный файл для копирования.
  • Попробуйте применить магию gitattributes clean / smudge для применения и удаления изменений, например, размазать файл конфигурации как извлечение из альтернативной ветви и очистить файл конфигурации как извлечение из HEAD. Это сложная штука, я не рекомендую ее для начинающего пользователя.
  • Сохраните файл конфигурации в выделенной для него ветке развертывания, которая никогда не объединяется с master. Когда вы хотите развернуть / скомпилировать / протестировать, вы сливаетесь с этой веткой и получаете этот файл. По сути, это подход smudge / clean, за исключением использования политик слияния людей и дополнительных git-модулей.
  • Антирекомендация: не используйте предположения без изменений, это закончится только слезами (потому что ложная ложь сама по себе приведет к плохим вещам, таким как ваши изменения будут потеряны навсегда).

7
git не удалил бы файл, если бы он был грязным во время удаления. И если он не грязный, поиск файла будет таким же простым, как и git checkout <oldref> -- <filename>- но тогда он будет проверен и проигнорирован.
amenthes

Относительно вашей последней заметки (о --assume-unchanged): либо это культ груза и его следует отклонить, либо вы можете объяснить, почему (в чем я убежден), и это становится полезным.
RomainValeri

58

Используйте это когда:

1. Вы хотите распаковать много файлов, или

2. Вы обновили свой файл gitignore

Ссылка на источник: http://www.codeblocq.com/2016/01/Untrack-files-already-added-to-git-repository-based-on-gitignore/

Допустим, вы уже добавили / передали некоторые файлы в свой репозиторий git, а затем добавили их в свой .gitignore; эти файлы все еще будут присутствовать в вашем индексе репозитория. В этой статье мы увидим, как от них избавиться.

Шаг 1: внесите все ваши изменения

Прежде чем продолжить, убедитесь, что все ваши изменения зафиксированы, включая ваш файл .gitignore.

Шаг 2: Удалить все из хранилища

Чтобы очистить репо, используйте:

git rm -r --cached .
  • rm это команда удаления
  • -r позволит рекурсивное удаление
  • –Cached удалит только файлы из индекса. Ваши файлы все еще будут там.

Команда rmможет быть неумолимой. Если вы хотите попробовать то, что он делает заранее, добавьте флаг -nили, --dry-runчтобы проверить это.

Шаг 3: заново добавить все

git add .

Шаг 4: совершить

git commit -m ".gitignore fix"

Ваш репозиторий чистый :)

Нажмите изменения на вашем пульте, чтобы увидеть изменения, действующие и там.


1
Это не удалит файлы из удаленного хранилища? Что если я захочу сохранить файлы как в локальном, так и в удаленном репозиториях, но заставить git «забыть» о них?
Avishay28

AFAIK, это не удалит файлы из истории, потому что мы не используем никаких команд изменения истории (исправьте меня, если я ошибаюсь). Это только добавляет новый коммит, удаляя файлы, игнорируемые в gitignore из git. Эти файлы будут в исторические
Дирадж Бхаскар

49

Я сделал это с помощью git filter-branch . Точная команда, которую я использовал, была взята со страницы руководства:

ВНИМАНИЕ : это удалит файл из всей вашей истории

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

Эта команда воссоздает всю историю коммитов, выполняющуюся git rmперед каждым коммитом, и, таким образом, избавляется от указанного файла. Не забудьте сделать резервную копию перед выполнением команды, так как она будет потеряна.


9
Это изменит все идентификаторы коммитов, тем самым нарушая слияния из веток за пределами вашей копии репозитория.
bdonlan

19
ВНИМАНИЕ: это удалит файл из всей вашей истории. Это было то, что я искал, хотя, чтобы удалить совершенно ненужный и слишком большой файл (вывод, который никогда не должен был быть зафиксирован), который был зафиксирован давным-давно в истории версий.
zebediah49

48

Что не сработало для меня

(Под Linux) я хотел использовать посты, предлагающие ls-files --ignored --exclude-standard | xargs git rm -r --cachedподход. Тем не менее, (некоторые из) файлов, которые должны быть удалены, имеют встроенную новую строку / LF / \nв своих именах. Ни одно из решений:

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

справиться с этой ситуацией (получить ошибки о не найденных файлах).

Так что я предлагаю

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

При этом используется -zаргумент для ls-файлов и -0аргумент для xargs для безопасного / правильного обслуживания «неприятных» символов в именах файлов.

На странице руководства git-ls-files (1) говорится:

Когда опция -z не используется, символы TAB, LF и обратная косая черта в путевых именах представляются как \ t, \ n и \\ соответственно.

поэтому я думаю, что мое решение необходимо, если в именах файлов есть какие-либо из этих символов.


1
Для меня это лучшее решение. Он имеет гораздо лучшую производительность, чем git add .. Он также содержит лучшие улучшения из некоторых комментариев выше.
Nils-o-mat

Можете ли вы добавить thSoft's git commit -am "Remove ignored files"позже к своему ответу? Ваши ответы в сочетании получили меня через вещи: J
Kando

Я не понимаю цель git commit -a. Для меня git rm --cachedвлияет именно индекс, поэтому нет необходимости ставить файлы после ...
Жан-Пол

23
  1. Обновите свой .gitignoreфайл - например, добавьте папку, которую вы не хотите отслеживать .gitignore.

  2. git rm -r --cached .- Удалите все отслеживаемые файлы, включая нужные и нежелательные. Ваш код будет в безопасности, если вы сохранили локально.

  3. git add .- Все файлы будут добавлены обратно, кроме тех, что в .gitignore.


Шляпа на @AkiraYamamoto, чтобы указать нам правильное направление.


1
Как насчет понижения голосов из-за того, что он на самом деле не будет работать, так как вам все равно нужен ключ -r для рекурсивного запуска rm :) (Кто-то не правильно копировал)
Аран Малхолланд,

1
Предупреждение: этот метод на самом деле не заставляет git игнорировать файл, а фактически заставляет git удалить файл. Это означает, что если вы используете это решение, то всякий раз, когда кто-либо другой делает git pull, файл будет удален. Так что это на самом деле не игнорируется. Посмотрите решение, предлагающее вместо этого git update-index --assume-неизмененный для решения исходного вопроса.
orrd

16

Я думаю, что git не может полностью забыть о файле из-за его концепции ( раздел «Снимки, а не различия» ).

Эта проблема отсутствует, например, при использовании CVS. CVS хранит информацию в виде списка изменений на основе файлов. Информация для CVS представляет собой набор файлов и изменений, внесенных в каждый файл с течением времени.

Но в Git каждый раз, когда вы фиксируете или сохраняете состояние вашего проекта, он в основном делает снимок того, как все ваши файлы выглядят в данный момент, и сохраняет ссылку на этот снимок. Таким образом, если вы добавили файл один раз, он всегда будет присутствовать в этом снимке.

Эти 2 статьи были полезны для меня:

git предположить, что без изменений vs skip-worktree и как игнорировать изменения в отслеживаемых файлах с помощью Git

На основании этого я делаю следующее, если файл уже отслежен:

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

С этого момента все локальные изменения в этом файле будут игнорироваться и не будут передаваться удаленно. Если файл изменяется на удаленном компьютере, конфликт может произойти, когда git pull. Тайник не сработает. Чтобы решить эту проблему, скопируйте содержимое файла в безопасное место и выполните следующие действия:

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

Содержимое файла будет заменено удаленным содержимым. Вставьте ваши изменения из безопасного места в файл и выполните снова:

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

Если все, кто работает с проектом, будут выступать git update-index --skip-worktree <file>, проблемы с ним pullдолжны отсутствовать. Это решение подходит для файлов конфигурации, когда каждый разработчик имеет свою собственную конфигурацию проекта.

Это не очень удобно делать каждый раз, когда файл был изменен на удаленном компьютере, но может защитить его от перезаписи удаленным контентом.


16

Делайте следующие шаги поочередно, у вас все будет хорошо.

1. удалите ошибочно добавленные файлы из каталога / хранилища . Вы можете использовать команду «rm -r» (для linux) или удалить их, просматривая каталоги. Или переместите их в другое место на вашем ПК. [Возможно, вам придется закрыть IDE, если вы хотите переместить / удалить ]

2. добавьте файлы / каталоги в gitignoreфайл и сохраните их.

3. удалите их из кэша git с помощью этих команд (если существует несколько каталогов, удалите их одну за другой, повторно выполнив эту команду)

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

4.Now сделать фиксации и нажим , использовать эти команды. Это удалит эти файлы из git remote и заставит git перестать отслеживать эти файлы.

git add .
git commit -m "removed unnecessary files from git"
git push origin

13

Копировать / вставить ответ git rm --cached -r .; git add .; git status

Эта команда будет игнорировать файлы, которые уже были переданы в Git-репозиторий, но теперь мы добавили их в .gitignore.


9

Ответ от Мэтта Фира был самым эффективным ИМХО. Ниже приведен сценарий PowerShell для тех, кто в Windows удаляет только файлы из своего репозитория git, которые соответствуют их списку исключений.

# 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 .

В какой ситуации этот список файлов не будет равен рекурсивному --cached?
Джон Заброски

8

Переместите или скопируйте файл в безопасное место, чтобы не потерять его. Затем откройте файл и выполните коммит. Файл все равно будет отображаться, если вы вернетесь к одному из этих предыдущих коммитов или к другой ветке, где он не был удален. Тем не менее, во всех будущих коммитах вы больше не увидите файл. Если файл находится в git ignore, вы можете переместить его обратно в папку, и git его не увидит.


34
git rm --cachedудалит файл из индекса, не удаляя его с диска, поэтому нет необходимости перемещать / копировать его
bdonlan

7

Использование git rm --cachedкоманды не отвечает на исходный вопрос:

Как вы заставляете gitполностью забыть о [файле]?

Фактически, это решение приведет к удалению файла во всех остальных экземплярах репозитория при выполнении git pull!

Правильный способ заставить git забыть о файле задокументирован GitHub здесь .

Я рекомендую прочитать документацию, но в основном:

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

просто замените full/path/to/fileна полный путь к файлу. Убедитесь, что вы добавили файл в свой .gitignore.

Вам также нужно (временно) разрешить не-ускоренные пересылки в ваш репозиторий , так как вы изменяете свою историю git.


5

BFG специально разработана для удаления нежелательных данных , таких как большие файлы или пароли из Git РЕПО, так что имеет простой флаг , который будет удалять любой большой исторический (не-в-ваш-ток фиксации) файлов: «--strip-blobs- больше чем'

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

Если вы хотите указать файлы по имени, вы можете сделать это тоже:

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

BFG в 10-1000 раз быстрее, чем git filter-branch, и, как правило, намного проще в использовании - для получения более подробной информации ознакомьтесь с полными инструкциями и примерами использования.

Источник: https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html


5

Если вы не хотите использовать интерфейс командной строки и работаете в Windows, очень простое решение - использовать TortoiseGit , в меню есть действие «Удалить (сохранить локальное)», которое работает нормально.


5

Мне понравился ответ JonBrave, но у меня есть достаточно грязные рабочие каталоги, которые фиксируют -a меня немного пугает, так что вот что я сделал:

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 и удаление игнорируемых файлов из индекса" '

ломая это:

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"
  • удалить игнорируемые файлы из индекса
  • этап .gitignore и файлы, которые вы только что удалили
  • совершить

4

Это больше не проблема в последнем git (v2.17.1 на момент написания).

.gitignoreНаконец игнорирует отслеживаются, но удаленные файлы. Вы можете проверить это сами, запустив следующий скрипт. В заключительном git statusутверждении должно быть указано «нечего совершать».

# 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

Я рад, что Git сейчас делает это. Однако ОП спрашивал о том, чтобы не отслеживать изменения в файлах, присутствующих в .gitignore, а не в удаленных файлах, по-прежнему отображающих состояние.
mrturtle

2

В случае уже совершенного DS_Store:

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

Проигнорируйте их:

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

Наконец, сделайте коммит!


2

Специально для файлов на основе IDE, я использую это:

Например, slnx.sqlite, я просто полностью избавился от него следующим образом:

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

Просто имейте в виду, что некоторые из этих файлов хранят некоторые локальные пользовательские настройки и предпочтения для проектов (например, какие файлы у вас были открыты). Таким образом, каждый раз, когда вы перемещаетесь или делаете какие-либо изменения в вашей IDE, этот файл изменяется, и поэтому он проверяет его и показывает, что есть незафиксированные изменения.


2

Принятый ответ не «заставляет Git » забывать « о файле ...» (исторически). Это только заставляет git игнорировать файл в настоящем / будущем.

Этот метод позволяет мерзавец полностью забыть игнорируемые файлы ( прошлое / настоящее / будущее), но не удаляет ничего из рабочего каталога (даже при повторном извлечении из удаленного).

Этот метод требует использования /.git/info/exclude(предпочтительнее) или уже существующий .gitignore в всех коммитах , которые имеют файлы , которые будут игнорироваться / забыто. 1

Все методы принудительного применения git игнорируют поведение за фактом, фактически переписывают историю и, следовательно, имеют значительные последствия для любых публичных / общих / совместных репозиториев, которые могут быть получены после этого процесса. 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>, примеры которых можно найти здесь .


0

Если кто-то испытывает трудности с Windows, и вы хотите игнорировать всю папку, «cd», чтобы выбрать «папку» и выполните «Git Bash Here».

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

0

В моем случае у меня было несколько файлов .lock в нескольких каталогах, которые мне нужно было удалить. Я запустил следующее, и это работало без необходимости заходить в каждый каталог, чтобы удалить их:

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

Это делало все папки, находящиеся под «корнем» того места, где я находился, и исключал все файлы, соответствующие шаблону.

Надеюсь, что это помогает другим!

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