Удалить файл из репозитория Git, не удаляя его из локальной файловой системы

Моя первоначальная фиксация содержала несколько файлов журналов. Я добавил *log в свой .gitignore, и теперь я хочу удалить файлы журнала из своего репозитория.

git rm mylogfile.log

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

Как я могу удалить этот файл из репозитория без удаления моей локальной копии файла?


person mveerman    schedule 17.07.2009    source источник
comment
Стоит отметить, что ответ, получивший наибольшее количество голосов, опасен для некоторых. Если вы используете удаленное репо, чем когда вы нажимаете свой локальный, вытащите в другое место те файлы, которые вы удалили из git, только БУДУТ УДАЛЕНЫ. Об этом упоминается в одном из ответов, но не комментируется.   -  person RichieHH    schedule 24.08.2018
comment
чтобы сделать это правильно: stackoverflow.com/questions/57418769/   -  person goofology    schedule 11.08.2020


Ответы (11)


Из man-файла:

Когда задано --cached, поэтапное содержимое должно соответствовать либо кончику ветви, либо файлу на диске, что позволяет удалить файл только из индекса.

Итак, для одного файла:

git rm --cached mylogfile.log

и для одного каталога:

git rm --cached -r mydirectory
person bdonlan    schedule 17.07.2009
comment
Его легко упустить, потому что он не так понятен, как svn rm --keep-local. - person Martin; 24.06.2011
comment
Но как мне сохранить файлы на удаленных серверах? Это сохраняет мой локальный, но если я нажимаю и извлекаю с другого сервера, файл удаляется. Я также добавил .gitignore для файла, но он все равно удаляется - person spankmaster79; 22.02.2013
comment
Это по-прежнему удаляет файлы на git pull, если вы отстали от фиксации после git rm - person Petr Peller; 22.05.2014
comment
Может быть, вместо git rm --cached mylogfile.log это должно быть git rm --unstage mylogfile.log для большего зазора. - person sobi3ch; 21.02.2015
comment
При переходе в другую ветку файл удаляется. - person Vladimir Vukanac; 07.07.2016
comment
Стоит отметить, что после выполнения команды в ответе нужно использовать git commit -m "Commit message" и git push. Если у вас есть какие-либо другие поэтапные изменения (проверьте с помощью git status), они также будут зафиксированы в это время. - person Sinjai; 11.09.2017
comment
Поскольку это наиболее распространенный ответ, и он не работает, то, о чем просят, я расскажу, что я делаю. Использую команду git rm --cached mylogfile.log и удаляю файл из репозитория. Чтобы избежать потери файла в производительной системе, я делаю резервную копию файла и после этого вытаскиваю. Файл будет удален, как упоминалось ранее, и его необходимо скопировать обратно из резервной копии. Это довольно неприятно, но я не нашел лучшего решения этой проблемы. - person Marcel Grolms; 14.12.2017
comment
Для тех, кто пропустил вопрос о том, что OP уже добавил в .gitignore, обратите внимание, что это необходимый шаг, чтобы убедиться, что локальный файл не удален во время более позднего слияния или извлечения. Вы также можете найти этот ответ полезным: stackoverflow.com/a/32182114/1024735 - person kevinmicke; 14.08.2019
comment
Вау, язык этой записи на странице руководства очень запутанный. - Я мог прочитать его трижды и не сообразить, что это связано с этой темой. - person BrainSlugs83; 24.08.2020
comment
@ BrainSlugs83 Это тебе мерзость! - person Kerry Johnson; 22.09.2020
comment
Предупреждение: если вы воспользуетесь этим методом, файлы БУДУТ удалены из любых других клонов того же репо. Они будут сохранены ТОЛЬКО в вашей локальной установке. Например, если у вас есть действующий производственный сервер и локальный сервер разработки, удаление из кеша повлияет на ваш производственный сервер. - person MrMoxy; 19.07.2021

Чтобы удалить всю папку из репозитория (например, файлы Resharper), сделайте следующее:

git rm -r --cached folderName

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

person Sam Tyson    schedule 04.04.2012
comment
Просто добавленное примечание для будущих посетителей: не используйте графический интерфейс для синхронизации фиксации с репозиторием. Это вернет файлы обратно в ваше локальное репо. Вы должны сделать Git Push repo branch, чтобы удалить файлы с пульта. - person RubberDuck; 04.12.2014

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

git rm --cached `git ls-files -i -X .gitignore`

Или, в качестве альтернативы, в Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)
person null    schedule 31.01.2014
comment
Не работает в Windows. git ls-files -i -X ​​.gitignore работает, но я не знаю, как отправить файлы в 'git rm'. Вы знаете, как это сделать? - person Erik Z; 09.05.2014
comment
Работает в Windows, если вы используете Git Bash вместо cmd-console - person Andreas Zita; 16.12.2014
comment
Люблю это. Сработало, за исключением того, что у меня были некоторые файлы, в которых в имени файла были пробелы. Я изменил решение на это: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Пожалуйста, подумайте об изменении или добавлении этого решения в ответ здесь, потому что это отличный инструмент, чтобы ... - person mpettis; 12.03.2016
comment
Я не пробовал, но нужно проверить, удалит ли он также файлы типа .gitkeep, который сохраняет пустую папку в репозитории. Например. .gitignore содержит папку uploads, а репо вынуждено отслеживать .gitkeep. Удалив все из репо под uploads, он также удалит .gitkeep. - person Vladimir Vukanac; 07.07.2016
comment
Это предложение отлично сработало в PowerShell: git rm --cached $ (git ls-files -i -X ​​.gitignore) - person geekandglitter; 21.04.2019
comment
Если .gitignore в подкаталогах также должен быть оценен, используйте --exclude-per-directory вместо -X. - person Samufi; 23.04.2020
comment
В CMD используйте для: for /f %x in ('git ls-files -i -X .gitignore') do git rm --cached %x - person B.McKee; 02.05.2020

Согласно моему ответу здесь: https://stackoverflow.com/a/27271913/3540289

Чтобы удалить папку / каталог или файл только из репозитория git, а не из локального, попробуйте 3 простых шага.


Действия по удалению каталога

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Действия по игнорированию этой папки при следующих фиксациях

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

Файл .gitignore будет выглядеть так

/FolderName

удалить каталог

person Suresh Karia    schedule 24.08.2015

Более общее решение:

  1. Отредактируйте .gitignore файл.

    echo mylogfile.log >> .gitignore

  2. Удалить все элементы из индекса.

    git rm -r -f --cached .

  3. Восстановить index.

    git add .

  4. Сделать новую фиксацию

    git commit -m "Removed mylogfile.log"

person mAsT3RpEE    schedule 13.12.2013
comment
Это действительно удалит файл? - person Mr_and_Mrs_D; 13.12.2013
comment
Из GitHub? НЕТ. Если вы уже перешли на github, он не удалит его с сайта. Но он обновит ваш локальный репозиторий git. - person mAsT3RpEE; 14.12.2013
comment
Комментарий, который вы удалили, на самом деле был более удален :) Проблема с решением rm --cashed в том, что оно в конечном итоге удалит файл, когда вы его потянете - верно? И это не то, чего хотят люди, когда они говорят: «Удалить файл из репозитория , не удаляя его из локальной файловой системы». Теперь, почему было принято вышеупомянутое решение, я не понимаю - возможно, OP работал один и никогда не тянул? Не знаю. Я так понимаю, что когда-то github всегда нажимал на проблему с - person Mr_and_Mrs_D; 14.12.2013
comment
Я не думаю, что есть 100% решение, если вы не спросите сам github. А пока придерживайтесь этого. Скопируйте файл, добавьте в gitignore, выполните фактический git rm -r, зафиксируйте, нажмите, восстановите файл. Удалось найти другое решение? - person mAsT3RpEE; 14.12.2013
comment
Моя проблема не в github, а в том, что файл будет фактически удален у коллег, когда они извлекут. Я не хочу, чтобы файл был удален. В прошлом это вызывало у меня огромные проблемы. Поэтому мне было интересно, действительно ли существует решение, которое действительно не удаляет файл. См. Также комментарий к принятому ответу: stackoverflow.com/questions/1143796/ - person Mr_and_Mrs_D; 14.12.2013
comment
Извини чувак. Я в тупике. Вариант 1. Включите скрипт загрузки, который добавляет файлы после извлечения. Вариант 2. Настроить git update-index --assume-unchanged вместо git rm. - person mAsT3RpEE; 14.12.2013
comment
Поскольку я боюсь уничтожить данные, этот ответ был бы лучше, если бы он явно указывал, будет ли mylogfile.log удаляться локально на любом из этих шагов. - person Wyck; 10.03.2021

Кроме того, если вы передали конфиденциальные данные (например, файл, содержащий пароли), вы должны полностью удалить их из истории репозитория. Вот руководство, объясняющее, как это сделать: http://help.github.com/remove-sensitive-data/

person BoD    schedule 21.08.2011
comment
Этот ответ должен включать в себя необходимые команды для выполнения этой задачи вместо ссылки на другой веб-сайт. - person Florian Lemaitre; 02.02.2018
comment
Я также хотел бы отметить, что с помощью инструмента очистки репозитория git bfg стало проще и быстрее . - person Lubed Up Slug; 15.02.2019

Git позволяет игнорировать эти файлы, предполагая, что они не изменились. Это делается с помощью команды git update-index --assume-unchanged path/to/file.txt. Отметив файл как таковой, git полностью проигнорирует любые изменения в этом файле; они не будут отображаться при запуске git status или git diff и никогда не будут зафиксированы.

(Из https://help.github.com/articles/ignoring-files)

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

Примечание: это не ответ на вопрос напрямую, а основан на последующих вопросах в комментариях к другим ответам.

person Rystraum    schedule 28.01.2014
comment
Хм, я делаю это, но вижу, что файл может быть перезаписан, если кто-то другой внесет в него изменения в репо. - person AlxVallejo; 15.09.2014

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

git update-index --assume-unchanged  file_name_with_path
person Afraz Ahmad    schedule 15.08.2018
comment
Хотя это хороший ответ, важно отметить, что он не отменяет отслеживание файла в том смысле, что люди обычно используют это слово в Git, где неотслеживаемый файл - это файл, которого нет в истории репозитория и никогда не было. Этот ответ сохраняет файл в репозитории, но не позволяет Git заметить, что в него были внесены изменения. В этом есть некоторые существенные различия - самое главное, файл все еще присутствует для других, и если кто-то другой внесет в него изменения, а вы потянете, ваша локальная копия может быть перезаписана без подтверждения. - person Soren Bjornstad; 22.10.2019

Вышеуказанные ответы не сработали для меня. Я использовал filter-branch для удаления всех зафиксированных файлов.

Удалите файл из репозитория git с помощью:

git filter-branch --tree-filter 'rm  file'

Удалите папку из репозитория git с помощью:

git filter-branch --tree-filter 'rm -rf directory'

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

Вы можете указать фиксацию, используя:

git filter-branch --tree-filter 'rm -rf directory' HEAD

Или диапазон:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

Чтобы отправить все на удаленный компьютер, вы можете:

git push origin master --force
person Martijn Mellens    schedule 12.01.2016
comment
Это в сочетании с git rm -r --cached NAME является уловкой, позволяющей удалить его из локального репозитория git и предотвратить его влияние на всех, кто извлечет его позже (путем удаления истории файла или каталога из git). - person notbad.jpeg; 17.03.2016
comment
Это переписывает историю git, и вам нужно будет нажать --force после, это немного выходит за рамки вопроса, я думаю. В публично известном репо вы не можете просто так изменить строку истории, так как у всех, кто уже клонировал репо, возникнут проблемы при извлечении. - person Guillaume Perrot; 01.04.2017
comment
На странице руководства git filter-branch содержит множество подводных камней .... Используйте альтернативный инструмент фильтрации истории, такой как git filter-repo. Кроме того, если вы собираетесь переписать историю, я думаю, вы могли бы изменить файл игнорирования в раннем возрасте, чтобы удаленные элементы игнорировались на протяжении всей новой истории? - person Rodney; 25.02.2021

Это зависит от того, что вы подразумеваете под словом «удалить» из git. :)

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

Если вы хотите сделать больше, чем деактивировать файл, например удалить конфиденциальные данные из всех предыдущих коммитов, вам нужно будет изучить фильтрацию ветки с помощью таких инструментов, как BFG Repo-Cleaner.

person Zach    schedule 15.11.2020

Игнорируйте файлы, удалите файлы из git, обновите git (для удаления).

Примечание. Это не касается истории конфиденциальной информации.

Этот процесс определенно требует понимания того, что происходит с git. Со временем, получив это, я научился выполнять такие процессы, как:

1) Игнорируйте файлы

  • Добавьте или обновите проект .gitignore, чтобы игнорировать их - во многих случаях, таких как ваш, родительский каталог, например log/ будет используемым регулярным выражением.
  • зафиксировать и нажать это .gitignore изменение файла (не уверен, нужен ли push, помните, ничего страшного, если это будет сделано).

2) Удалите файлы из git (только).

  • Теперь удалите файлы из git (только) с помощью git remove --cached some_dir/
  • Убедитесь, что они по-прежнему остаются локально (должны!).

3) Добавьте и зафиксируйте это изменение (по сути, это изменение для добавления удаляющего материала, несмотря на запутанную команду добавления!)

  • git add .
  • git commit -m"removal"
person Michael Durrant    schedule 14.04.2020
comment
см. эти вопросы, чтобы узнать, почему это плохой ответ: stackoverflow.com/questions/57418769/ - person Ilya Kolesnikov; 12.03.2021