ГИТ: Как удалить файл из индекса без удаления файлов из любого репозитория


при использовании

git rm --cached myfile

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

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

Edit: уточнил, Я надеюсь.

7 145

7 ответов:

я не думаю, что git commit может записать намерение типа "остановить отслеживание этого файла, но не удалять его".

принятие такого намерения потребует вмешательства за пределами Git в любых репозиториях, которые объединяют (или перебазируют) фиксацию, которая удаляет файл.


сохранить копию, применить удаление, восстановить

вероятно, проще всего сказать вашим нижестоящим пользователям сохранить копию файла, удалить его, а затем восстановить файл. Если они тянут через rebase и "переносят" изменения в файл, они получат конфликты. Для разрешения таких конфликтов используйте git rm foo.conf && git rebase --continue (Если конфликтующая фиксация имеет изменения, кроме тех, что в удаленном файле) или git rebase --skip (если конфликтующая фиксация изменилась только на удаленный файл).

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

если они уже вытащили вашу фиксацию удаления, они все еще могут восстановить предыдущую версию из файла с git show:

git show @{1}:foo.conf >foo.conf

или git checkout (за комментарий Уильяма Перселла; но не забудьте повторно удалить его из индекса!):

git checkout @{1} -- foo.conf && git rm --cached foo.conf

если они предприняли другие действия с момента удаления вашего удаления (или они тянут с rebase в отделенную голову), им может понадобиться что-то другое, чем @{1}. Они могли бы использовать git log -g чтобы найти фиксацию, прежде чем они вытащили ваш исключение.


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

сохранить файл в качестве "по умолчанию" и вручную/автоматически активировать его

если сохранение содержимого файла конфигурации в репозитории не является полностью неприемлемым, вы можете переименовать отслеживаемый файл из (например) foo.conf до foo.conf.default а затем дать пользователям возможность cp foo.conf.default foo.conf после применения фиксации переименования. Или, если пользователи уже используют некоторую существующую часть репозитория (например, скрипт или другую программу, настроенную по содержимому в репозитории (например,Makefile или аналогичный)) для запуска / развертывания вашего программного обеспечения вы можете включить механизм по умолчанию в процесс запуска / развертывания:

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf

С таким механизмом дефолта на месте, пользователи должны быть в состоянии вытащить фиксацию, что переименовывает foo.conf до foo.conf.default без необходимости делать любую дополнительную работу. Кроме того, вам не придется вручную копировать файл конфигурации, если вы сделаете дополнительные установки/репозитории в будущем.

Переписывание Истории Требует Ручного Вмешательства В Любом Случае...

если недопустимо поддерживать контент в репозитории, то вы, вероятно, захотите полностью искоренить его из истории с помощью чего-то вроде git filter-branch --index-filter …. Это равносильно переписыванию истории, что потребует ручного вмешательства для каждого филиала/хранилище (см. раздел "Восстановление из раздела" Перемещение "вверх" в git rebase manpage). Специальная обработка, необходимая для вашего файла конфигурации, будет всего лишь еще одним шагом, который необходимо выполнить при восстановлении после перезаписи:

  1. сохраните копию файла конфигурации.
  2. восстановление после перезаписи.
  3. восстановить конфигурацию файл.

игнорировать его, чтобы предотвратить рецидив

какой бы метод вы ни использовали, вы, вероятно, захотите включить имя файла конфигурации в .gitignore файл в репозитории, так что никто не может случайно git add foo.conf опять же (это возможно, но требует -f/--force). Если у вас есть более одного файла конфигурации, вы можете рассмотреть возможность "перемещения" их всех в один каталог и игнорировать все это (под "перемещением" я имею в виду изменение программа ожидает найти свои файлы конфигурации и заставить пользователей (или механизм запуска/развертывания) копировать / перемещать файлы в новое место; вы, очевидно, не захотите git mv файл в каталог, который вы будете игнорировать).

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

http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

работал нормально для меня и не упоминается до сих пор.

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

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

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

Если вы когда-либо хотели чтобы положить его обратно.

Edit: пожалуйста, смотрите комментарии от Chris Johnsen и KPM, это работает только локально, и файл остается под контролем версий для других пользователей, если они этого не делают. Принятый ответ дает более полные/правильные методы борьбы с этим. Также некоторые заметки из ссылки при использовании этого метода:

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

чтобы удалить файл из индекса, используйте:

git reset myfile

Это не должно повлиять на вашу локальную копию или чью-либо еще.

после , попробуйте добавить myfile до (создайте его, если он не существует). Это должно сказать git игнорировать myfile.

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

  1. git rm --cached remove_file
  2. добавить файл в gitignore
  3. git add .gitignore
  4. git commit -m "Excluding"
  5. удачи ;)

мое решение-вытащить другую рабочую копию, а затем сделать:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

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

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

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

https://help.github.com/articles/remove-sensitive-data/

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

чтобы увидеть изменения, вам может потребоваться перейти в корень GitHub вашего репозитория и обновить страницу. Затем перейдите по ссылке ссылки, чтобы добраться до старого коммита, который когда-то имел файл, чтобы увидеть, что он теперь удален. Для меня просто обновление старой страницы фиксации не показало изменения.

сначала это выглядело пугающе, но на самом деле было легко и работало как шарм ! : -)