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

Когда вы используете

git rm --cached myfile

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

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

Изменить: Уточненный, надеюсь.

Ответ 1

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

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


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

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

Восстановить файл как не обработанный после вытягивания фиксации, удаляющей его

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

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

Или с git checkout (за комментарий William Pursell, но не забудьте удалить его из индекса!):

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

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


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

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

Если не полностью неприемлемо продолжать поддерживать содержимое конфигурационного файла в репозитории, вы можете переименовать отслеживаемый файл из (например) foo.conf в foo.conf.default, а затем проинструктировать своих пользователей cp foo.conf.default foo.conf после применения переименования. Или, если пользователи уже используют некоторую существующую часть репозитория (например, script или какая-либо другая программа, сконфигурированная контентом в репозитории (например, 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 справочная страница переустановки). Специальная обработка, необходимая для вашего файла конфигурации, будет всего лишь еще одним шагом, который необходимо выполнить при восстановлении после перезаписи:

  • Сохраните копию конфигурационного файла.
  • Восстановить из перезаписи.
  • Восстановить файл конфигурации.

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

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

Ответ 2

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

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

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

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

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

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

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

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

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

Ответ 3

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

git reset myfile

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

Ответ 4

После выполнения команды git rm --cached попробуйте добавить myfile в файл .gitignore (создайте его, если он не существует). Это должно означать git игнорировать myfile.

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

Ответ 5

  • git rm --cached remove_file
  • добавить файл в gitignore
  • git add .gitignore
  • git commit -m "Excluding"
  • Удачи;)

Ответ 6

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

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

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

Ответ 7

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

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

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

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

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

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