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

вопрос создан в Wed, Dec 20, 2017 12:00 AM

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

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

    
4477
  1. git clean -X звучит похоже, но в этой ситуации это неприменимо (когда Git по-прежнему отслеживает файлы). Я пишу это для тех, кто ищет решение не следовать по неверному маршруту.
    2015-02-27 12: 14: 42Z
  2. Единственный реальный ответ на этот вопрос приведен ниже, см. git update-index --assume-unchanged . Это решение 1) хранит файл на сервере (индекс), 2) позволяет свободно изменять его локально.
    2016-01-04 14: 15: 28Z
  3. Вам необходимо использовать --skip-worktree, см .: stackoverflow.com/questions/13630849/…
    2016-08-05 20: 33: 17Z
  4. Важный вопрос: должен ли файл оставаться в хранилище или нет? Например, если кто-то новый клонирует репо, он должен получить файл или нет? Если YES , то значение git update-index --assume-unchanged <file> является правильным, и файл останется в хранилище, а изменения не будут добавлены с git add. Если NO (например, это был какой-то файл кэша, сгенерированный файл и т. д.), то git rm --cached <file> удалит его из хранилища.
    2016-11-22 10: 45: 06Z
  5. @ Martin @Qwerty Каждый должен прекратить давать советы для --assume-unchanged, который предназначен для того, чтобы производительность не позволяла git проверять состояние больших отслеживаемых файлов, но предпочитает --skip-worktree, который предназначен для измененных отслеживаемых файлов, которые пользователь не хочет больше фиксировать. См. stackoverflow.com/questions/13630849/...
    2018-02-15 11: 16: 15Z
23 ответа                              23                         

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

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

git rm --cached <file>

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

git rm -r --cached <folder>

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

ПРЕДУПРЕЖДЕНИЕ. Хотя это не приведет к удалению физического файла из вашего локального файла, он будет удалять файлы с компьютеров других разработчиков на следующем git pull.

    
4712
2019-06-16 16: 24: 13Z
  1. процесс, который работал для меня: 1. сначала зафиксировать ожидающие изменения 2. git rm --cached < file > и выполните коммит 3. добавьте файл в .gitignore, проверьте состояние git и снова подтвердите
    2009-08-13 21: 07: 29Z
  2. Очень важное добавление. Если игнорируемый файл будет изменен (но, несмотря на это, он не должен быть зафиксирован), после изменения и выполнения git add . он будет добавлен в индекс. И следующий коммит передаст его в хранилище. Чтобы избежать этого, выполните сразу же после того, как этот матал сказал еще одну команду: git update-index --assume-unchanged <path&filename>
    2011-08-24 16: 39: 33Z
  3. @ Метод AkiraYamamoto также хорошо работал для меня. В моем случае я подавил вывод, так как в моем хранилище были тысячи файлов: git rm -r -q --cached .
    2013-10-11 15: 21: 13Z
  4. Тем не менее, этот файл будет удален в git pull.
    2014-05-22 16: 04: 32Z
  5. git rm --cached < file > просто удалите файл из репозитория, git update-index --assume-unchanged < file > не показывается файл в неустановленных изменениях и не вызывает новых изменений. Но я хочу, чтобы GIT просто игнорировал содержимое файла PLEEEEEASE
    2015-04-07 09: 03: 18Z

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

Во-первых:

git rm -r --cached . 
git add .

Тогда:

git commit -am "Remove ignored files"
    
2361
2017-10-10 20: 57: 10Z
  1. Чтобы подчеркнуть разницу между этим ответом и принятым: при использовании этих команд вам не нужно фактически знать затронутые файлы. (Представьте себе временный каталог со множеством случайных файлов, которые должны быть удалены из индекса).
    2014-03-27 10: 17: 37Z
  2. То же, что и принятый ответ. Файлы будут удалены git pull.
    2014-05-22 16: 07: 17Z
  3. Было бы неплохо иметь это как стандартную команду git. Что-то вроде git rmignored.
    2014-12-20 11: 59: 05Z
  4. @ gudthing -r означает "рекурсивный"
    2015-07-15 11: 24: 12Z
  5. Таким образом, вы можете в конечном итоге добавить другие бесполезные файлы, которые в данный момент не находятся в .gitignore. Что может быть трудно выяснить, если это зависит от того, как шум ваш git status после этой команды. Команда, которая удаляет только недавно проигнорированные файлы, была бы лучше. Вот почему я предпочитаю ответ thSoft
    2015-09-22 14: 27: 06Z

git update-index выполняет эту работу за меня:

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

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

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

git update-index --skip-worktree <file>
    
929
2018-11-13 08: 24: 39Z
  1. Это IS реальный ответ. Удивительно на самом деле, очень просто, не загрязняет git status и на самом деле очень интуитивно понятно. Спасибо.
    2014-01-12 23: 57: 18Z
  2. git update-index --assume-unchanged <path> … приведет к тому, что git будет игнорировать изменения в указанных путях, независимо от .gitignore. Если вы извлекаете данные с удаленного устройства и этот удаленный имеет изменения в этом пути, git произойдет сбой слияния с конфликтом, и вам нужно слить вручную. git rm --cached <path> … заставит git перестать отслеживать этот путь. Если вы не добавите путь к .gitignore, вы увидите путь в будущем git status. Первый параметр имеет меньший шум в истории изменений git и позволяет распространять изменения в "игнорируемом" файле в будущем.
    2014-06-25 02: 02: 40Z
  3. Отмените, используя: git update-index --no-предположить-неизменный < file >
    2014-08-07 19: 20: 42Z
  4. Я не совсем понимаю, почему это не принятый ответ. Принятый ответ здесь явно не отвечает на фактически задаваемый вопрос. Этот ответ игнорирует изменения в файле, который находится в хранилище, но не удаляет его из хранилища.
    2015-12-02 22: 46: 16Z
  5. Этот ответ был бы намного более полезным, если бы он точно объяснил, что делает данная команда, например, чем он отличается от других предлагаемых решений.
    2016-08-19 15: 39: 50Z
git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

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

    
254
2018-01-23 15: 26: 59Z
  1. Если вам тоже нужно удалить их из рабочего каталога, просто запустите git ls-files --ignored --exclude-standard | xargs git rm . Я считаю, что этот ответ лучший! Потому что это очень понятно, Unix-способ, и делает желаемую вещь прямым способом, без создания побочных эффектов других, более сложных команд.
    2015-02-27 12: 23: 34Z
  2. Отличный ответ; однако команда не будет выполнена, если у вас есть пути с пробелами в середине, например: "My dir /my_ignored_file.txt"
    2015-06-19 15: 29: 27Z
  3. git ls-files --ignored --exclude-standard | sed 's /.*/"& "/' | xargs git rm --cached
    2015-06-19 15: 36: 02Z
  4. git rm будет жаловаться, если ls-files ничего не соответствует. Используйте xargs -r git rm ..., чтобы указать xargs не запускать git rm, если не найдено ни одного файла.
    2016-01-06 19: 15: 35Z
  5. Было бы лучше использовать \0 в качестве разделителя: git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
    2016-02-02 10: 05: 42Z

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

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

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

    
70
2015-06-19 15: 42: 11Z
  1. Отличное решение! Работает отлично и чувствует себя более корректно, чем удаление всех файлов, а затем добавление их обратно.
    2015-09-09 08: 59: 38Z
  2. Я тоже нашел этот "самый чистый". Это может быть очевидно, но только выполнение первой части, git ls-files --ignored --exclude-standard, само по себе позволяет вам сначала понять /проверить, какие файлы ваш новый .gitignore собирается исключить /удалить, прежде чем идти вперед и выполнить окончательный вариант git rm.
    2015-12-29 11: 56: 02Z
  3. Помните, что произойдет сбой в именах файлов с определенными "неприятными" символами в них, например, \n. Я опубликовал свое решение для этого.
    2015-12-29 13: 01: 42Z
  4. Еще одна оговорка: при извлечении это приведет к удалению файла в других рабочих каталогах, верно?
    2016-08-19 15: 46: 04Z

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

Подводя итог:

  • Попросите ваше приложение найти пропущенный файл config-overide.ini и использовать его поверх зафиксированного файла config.ini (или, альтернативно, найдите ~ /.config /myapp.ini или $MYCONFIGFILE)
  • Зафиксируйте файл config-sample.ini и проигнорируйте файл config.ini, при необходимости создайте скрипт или аналогичный файл для копирования.
  • Попробуйте применить магию gitattributes clean /smudge для применения и удаления изменений, например, размазать файл конфигурации как извлечение из альтернативной ветви и очистить файл конфигурации как извлечение из HEAD. Это сложная штука, я не рекомендую ее для начинающего пользователя.
  • Сохраните файл конфигурации в выделенной для него ветке развертывания, которая никогда не объединяется с master. Когда вы хотите развернуть /скомпилировать /протестировать, вы сливаетесь с этой веткой и получаете этот файл. По сути, это подход smudge /clean, за исключением использования политик слияния людей и дополнительных git-модулей.
  • Антирекомендация: не используйте предположения-без изменений, это только приведет к слезам (потому что, если вы будете мерзко обманывать себя, это может привести к плохим вещам, таким как ваши изменения будут потеряны навсегда).
59
2018-11-24 04: 17: 54Z
  1. git не удалит файл, если он был грязным во время удаления. И если он не грязный, поиск файла будет таким же простым, как git checkout <oldref> -- <filename> - но тогда он будет извлечен и проигнорирован.
    2014-07-24 14: 05: 41Z
  2. Относительно вашей последней заметки (около --assume-unchanged): либо это культ груза и его следует отклонить, либо вы можете объяснить, почему (в чем я убежден), и оно становится полезно.
    2018-11-22 09: 17: 53Z

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

    
54
2009-08-13 19: 27: 31Z
  1. Это прекрасно работает, если вы хотите игнорировать группу файлов, которые ранее не игнорировались. Хотя, как вы сказали, возможно, есть лучший способ для этого.
2013-05-28 16: 19: 12Z
  • Это именно то, что я и сделал. Просто переместите файлы в папку за пределами git, затем выполните «git add.», «Git commit». (Это удалило файлы), затем добавьте gitignore, ссылаясь на файлы /папки, подтвердите снова, чтобы добавить файл gitignore в git, затем скопируйте /переместите обратно в папки, и их следует игнорировать. NB. Похоже, что файлы были удалены из GIT, поэтому, вероятно, удалят их из других проверок /извлечений, как упоминалось в вышеупомянутых решениях, но, поскольку вы изначально делаете их копии, это не является большой проблемой IMHO. просто дайте знать остальной команде ...
    2016-09-23 12: 04: 27Z
  • Это самый простой способ избавиться от ошибочно зафиксированных папок.
    2017-01-14 08: 01: 29Z
  • Кажется, что это единственный способ, который я вижу. Это серьезная ошибка (не «функция») в git, которая, как только вы добавляете файл /папку в .gitignore, не просто игнорирует этот файл с этого момента - навсегда - везде.
    2017-09-24 09: 09: 17Z
  • Используйте это, когда:

    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"
    

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

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

        
    50
    2018-04-22 18: 11: 09Z
    1. Это не удалит файлы из удаленного хранилища? Что если я захочу сохранить файлы как в локальном, так и в удаленном репозиториях, но заставлю git «забыть» о них?
      2019-03-19 15: 35: 13Z
    2. AFAIK, это не удалит файлы из истории, потому что мы не используем никаких команд изменения истории (исправьте меня, если я ошибаюсь). Это только добавляет новый коммит удалив файлы, игнорируемые в gitignore, из git. Эти файлы будут там в исторических коммитах
      2019-03-19 20: 00: 57Z

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

    ПРЕДУПРЕЖДЕНИЕ : это приведет к удалению файлаиз всей вашей истории

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

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

        
    42
    2017-04-25 14: 50: 40Z
    1. Это изменит все идентификаторы коммитов, тем самым нарушая слияния ветвей за пределами вашей копии репозитория.
      2009-08-13 19: 56: 51Z
    2. ВНИМАНИЕ: это удалит файл из всей вашей истории. Однако это было то, что я искал, чтобы удалить совершенно ненужный и негабаритный файл (вывод, который никогда не должен был быть зафиксирован), который был зафиксирован давным-давно в истории версий.
      2013-03-13 05: 49: 10Z

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

    (Под 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
    

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

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

      

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

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

    РЕДАКТИРОВАТЬ: меня попросили добавить, что - как и любая команда git rm - за этим должна следовать фиксация , чтобы сделать удаления удаленными, например, git commit -am "Remove ignored files".

        
    40
    2017-10-06 13: 10: 03Z
    1. Для меня это лучшее решение. Он имеет гораздо лучшую производительность, чем git add .. Он также содержит лучшие улучшения из некоторых комментариев выше.
      2016-02-02 12: 08: 07Z
    2. Можете ли вы добавить thSoft's git commit -am "Remove ignored files" впоследствии к своему ответу? Ваши ответы в совокупности помогли мне разобраться: j
      2017-10-06 00: 07: 15Z
    3. Я не понимаю цели git commit -a. Для меня git rm --cached влияет именно на индекс, поэтому нет необходимости ставить файлы после ...
      2018-11-08 11: 32: 11Z
    1. Обновите файл .gitignore - например, добавьте папку, которую вы не хотите отслеживать, в .gitignore.

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

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

    Передайте @AkiraYamamoto подсказку, чтобы указать нам правильное направление.

        
    21
    2016-10-04 00: 58: 52Z
    1. Как насчет понижения рейтинга из-за того, что он на самом деле не будет работать, так как вам все равно нужен ключ -r для рекурсивного запуска rm :) (Кто-то неправильно копировал)
      2016-07-28 01: 55: 34Z
    2. Предупреждение: этот метод на самом деле не заставляет git игнорировать файл, а фактически заставляет git удалить файл. Это означает, что если вы используете это решение, то всякий раз, когда кто-либо другой делает git pull, файл будет удален. Так что это на самом деле не игнорируется. Посмотрите решение, предлагающее вместо этого git update-index --assume-неизмененный для решения исходного вопроса.
      2017-09-15 17: 33: 53Z

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

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

        
    15
    2017-05-21 15: 12: 39Z

    Выполните следующие шаги последовательно, все будет в порядке.

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

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

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

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

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

    git add .
    git commit -m "removed unnecessary files from git"
    git push origin
    
        
    12
    2019-02-20 05: 29: 49Z

    Ответ копирования /вставки: git rm --cached -r .; git add .; git status

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

        
    9
    2018-11-19 11: 36: 02Z

    Ответ от Мэтта Фира был самым эффективным ИМХО. Ниже приведен сценарий 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 .
    
        
    8
    2013-12-25 00: 51: 04Z
    1. В какой ситуации этот список файлов не будет равен рекурсивному --cached?
      2014-01-10 18: 47: 00Z
    источник размещен Вот