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


3049

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

git rm mylogfile.log

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

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



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

Ответы:


4357

Из файла man :

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

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

git rm --cached mylogfile.log

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

git rm --cached -r mydirectory

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)

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

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


@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"


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 )

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

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


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