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

3049

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

git rm mylogfile.log

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

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

mveerman
источник
14
Стоит отметить, что ответ с наибольшим количеством голосов опасен для некоторых. Если вы используете удаленный репозиторий , чем когда вы нажимаете вашему локальному затем вытащить эти файлы в другом месте, удаленных от мерзавца только будет удалено . Это упоминается в одном из ответов, но не комментируется.
RichieHH

Ответы:

4357

Из файла man :

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

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

git rm --cached mylogfile.log

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

git rm --cached -r mydirectory
bdonlan
источник
151
Легко пропустить, потому что это не так само за себя, как svn rm --keep-local.
Мартин
114
Но как мне сохранить файлы на удаленных серверах? Это сохраняет мой локальный, но если я нажму и потяну с другого сервера, файл будет удален. Я также добавил .gitignore для файла, но он все еще удален
spankmaster79
6
Это все равно удаляет файлы, git pullесли вы находитесь за коммитом послеgit rm
Петр Пеллер
9
Стоит отметить, что после запуска команды в ответе необходимо использовать git commit -m "Commit message"и git push. Если у вас есть какие-либо другие поэтапные изменения (проверьте с помощью git status), они также будут зафиксированы в это время.
Синджай
9
Так как это самый приемлемый ответ и он не делает то, о чем просят, я расскажу, что я делаю. Я использую команду git rm --cached mylogfile.logи удаляю файл из репозитория. Чтобы не потерять файл в продуктивной системе, я делаю резервную копию файла и вытащу после этого. Файл будет удален, как упоминалось ранее, и его необходимо скопировать обратно из резервной копии. Это довольно больно, но я не нашел лучшего решения этой проблемы.
Марсель Гролмс
275

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

git rm -r --cached folderName

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

Сэм Тайсон
источник
13
Просто добавленная заметка для будущих посетителей: не используйте графический интерфейс для «синхронизации» фиксации обратно в репо. Это вернет файлы обратно в ваш локальный репозиторий. Вы должны сделать, Git Push repo branchчтобы фактически удалить файлы с пульта.
RubberDuck
211

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

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

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

git rm --cached $(git ls-files -i -X .gitignore)
значение NULL
источник
7
Не работает на Windows. git ls-files -i -X ​​.gitignore работает, но я не знаю, как отправить файлы в 'git rm'. Ты знаешь как это сделать?
Эрик З
17
Работает на Windows, если вы используете Git Bash вместо cmd-консоли
Andreas Zita
17
Люблю это. Работал за исключением того, что у меня были некоторые файлы, которые заканчивались тем, что имели пробелы в имени файла. Я изменил решение здесь это: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Пожалуйста, подумайте об изменении или добавлении этого решения к ответу здесь, потому что это отличный инструмент для ...
mpettis
Я не пробовал, но это должно быть проверено, удалит ли он также такие файлы, .gitkeepкоторые сохраняют пустую папку в хранилище. Например. .gitignoreсодержать папку uploadsи репо вынужден отслеживать .gitkeep. Удалив все из репо под uploadsнего, удалят также .gitkeep.
Владимир Вуканац
Это предложение отлично работает в powershell: git rm --cached $ (git ls-files -i -X ​​.gitignore)
geekandglitter
89

Согласно моему ответу здесь: /programming/6313126/how-to-remove-a-directory-in-my-github-repository

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


Шаги по удалению каталога

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

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

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

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

/FolderName

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

eirenaios
источник
@gaurav рад, что это помогло!
Eirenaios
69

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

Совет директоров
источник
13
Этот ответ должен включать необходимые команды для выполнения этой задачи вместо ссылки на другой веб-сайт.
Флориан Леметр
1
Я также хотел бы отметить, что я нашел, что использовать инструмент git bfg repo cleaner проще и быстрее.
Lubed Up Slug
64

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

  1. Редактировать .gitignoreфайл

    ECHO mylogfile.log >> .gitignore

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

    git rm -r -f --cached .

  3. Перестрой индекс.

    git add .

  4. Сделать новый коммит

    git commit -m "Removed mylogfile.log"

mAsT3RpEE
источник
2
Будет ли это на самом деле удалить файл?
Mr_and_Mrs_D
6
Из GitHub? NO. Если вы уже нажали на github, он не удалит его с сайта. Но это обновит ваш локальный репозиторий git.
mAsT3RpEE
5
Комментарий, который вы удалили, был на самом деле более удален :) Проблема с решением rm --cashedсостоит в том, что он в конечном итоге удалит файл, когда вы нажмете - правильно? И это не то, что люди хотят, когда говорят «Удалить файл из хранилища, не удаляя его из локальной файловой системы ». Теперь, почему принятое выше решение мне не подходит - возможно, ОП работал один и никогда не работал? Не знаю. Я понимаю, что GitHub "когда-то толкнул всегда" проблема ofc
Mr_and_Mrs_D
Я не думаю, что есть 100% решение, если вы не спросите сам Github. А пока придерживайтесь этого. Скопируйте файл, добавьте в gitignore, выполните git rm -r, зафиксируйте, нажмите, восстановите файл. Вам удалось найти другое решение?
mAsT3RpEE
9
Моя проблема не в github, а в том, что файл действительно будет удален из коллег, когда они будут тянуть . Я не хочу, чтобы файл был удален. Это вызвало у меня огромные проблемы в прошлом. Поэтому мне было интересно, есть ли действительно решение, которое действительно не удаляет файл. См. Также комментарий в принятом ответе: stackoverflow.com/questions/1143796/…
Mr_and_Mrs_D
24

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

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

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

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

Rystraum
источник
2
Хм, я делаю это, но вижу, что файл может быть перезаписан, если кто-то еще внесет изменения в репо.
AlxVallejo
17

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

git update-index --assume-unchanged  file_name_with_path
Афраз Ахмад
источник
2
Хотя это хороший ответ, важно отметить, что он не «отслеживает» файл в том смысле, что люди обычно используют это слово в Git, где неотслеживаемый файл - это файл, которого нет в истории хранилища и никогда не было , Этот ответ сохраняет файл в хранилище, но не позволяет Git замечать, что в него были внесены изменения. Это имеет некоторые существенные отличия - самое главное, что файл все еще присутствует для других, и если кто-то внесет в него изменения и вы извлечете его, ваша локальная копия может быть перезаписана без подтверждения.
Сорен Бьорнстад
8

Приведенные выше ответы не сработали для меня. Я использовал, 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
Мартейн Мелленс
источник
2
В сочетании с git rm -r --cached NAMEэтим уловка заключается в том, чтобы удалить его из локального репозитория git и предотвратить его влияние на всех, кто извлекает позже (удаляя историю файла или каталога из git.)
notbad.jpeg
1
Это переписывает историю git, и вам нужно будет нажать --force после этого, это немного выходит за рамки вопроса, который я думаю. В общедоступном репо вы не можете просто изменить линию истории, так как у всех, кто уже клонировал репо, возникнут проблемы при извлечении.
Гийом Перро
0

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

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

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

1) Игнорировать файлы

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

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

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

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

  • git add .
  • git commit -m"removal"
Майкл Даррант
источник