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

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

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

20 ответов


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

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

git rm --cached <file>

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


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

первый:

git rm -r --cached . 
git add .

затем:

git commit -am "Remove ignored files"

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

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

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

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


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

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


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

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

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


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

подведем итоги:

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

уходим, предаем, затем переместить его обратно. В прошлом это срабатывало. Вероятно, есть более "хитрый" способ добиться этого.


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

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

использует до ls-files и


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

предупреждение: это удалит файл из всей вашей истории

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

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


использовать это, когда:

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 позволит рекурсивный удаление
  • –сохраненная удаляет только файлы из индекса. Ваши файлы все еще будут там.

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

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

git add .

Шаг 4: Commit

git commit -m ".gitignore fix"

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

нажимаем изменения к удаленному увидеть изменения эффективны и там.


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

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

  3. git add . – все файлы будут добавлены обратно, за исключением .gitignore.


наконечник шляпы @AkiraYamamoto для указания нам в правильном направлении.


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

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


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


ответ от Мэтта страха был самым эффективным ИМХО. Ниже приведен только сценарий 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 .

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

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

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

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

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

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


Если вы не хотите использовать CLI и работаете в Windows, очень простое решение-использовать TortoiseGit, Он имеет действие "удалить (сохранить локальный)" в меню, которое отлично работает.


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

git config --глобальный псевдоним.исключить-проигнорировать!ГИТ ЛС-файлы -з --игнорировать --исключить-стандарт | команды xargs -0 ГИТ РМ -Р --кэшированные && Git в ЛС-файлы -з --игнорировать --исключить-стандарт | команды xargs -0 ГИТ этап && Git на сцене .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"
  • удалить игнорируемые файлы из index
  • этап .gitignore и файлы просто удалены
  • commit

Это больше не проблема в последнем 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

В случае уже совершенного 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

наконец, сделайте фиксацию!


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

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

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

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

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

4.теперь do a commit и push используйте эти команды. Это будет удалите эти файлы из git remote и сделать git остановить отслеживание эти файлы.

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