Почему есть 2 способа удалить файл из git?
Иногда мерзавец предлагает git rm --cached
иногда удалять файл git reset HEAD file
, Когда я должен использовать что?
РЕДАКТИРОВАТЬ:
D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
D:\code\gt2>touch b
D:\code\gt2>git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# b
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add b
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
16 ответов
git rm --cached <filePath>
не удаляет файл, он фактически удаляет файл (ы) из репозитория (при условии, что он уже был зафиксирован ранее), но оставляет файл в рабочем дереве (оставляя файл без отслеживания).
git reset -- <filePath>
будет отменять любые поэтапные изменения для данного файла (ов).
Тем не менее, если вы использовали git rm --cached
для нового файла, который находится в стадии подготовки, он будет выглядеть так, как будто вы только что установили его, поскольку он никогда не был зафиксирован ранее.
git rm --cached
используется для удаления файла из индекса. В случае, если файл уже находится в репо, git rm --cached
удалит файл из индекса, оставив его в рабочем каталоге, а коммит теперь также удалит его из репозитория. По сути, после коммита вы бы развернули файл и сохранили локальную копию.
git reset HEAD file
(который по умолчанию использует --mixed
Параметр flag) отличается тем, что в случае, когда файл уже находится в репо, он заменяет индексную версию файла версией из репо (HEAD), фактически не внося изменений в него.
В случае неверсионного файла он собирается удалить весь файл, так как его не было в HEAD. В этом аспекте git reset HEAD file
а также git rm --cached
одинаковы, но не совпадают (как описано в случае файлов, уже находящихся в репо)
К вопросу о Why are there 2 ways to unstage a file in git?
- в git никогда не бывает только одного способа что-либо сделать. в этом вся прелесть:)
Довольно просто:
git rm --cached <file>
заставляет git полностью прекратить отслеживание файла (оставляя его в файловой системе, в отличие от простогоgit rm
*)git reset HEAD <file>
unstages любые изменения, сделанные в файле с момента последнего коммита (но не возвращает их в файловой системе, в отличие от того, что может указывать имя команды **). Файл остается под контролем ревизии.
Если файл ранее не контролировался ревизиями (т. Е. Вы удаляете файл, который у вас был git add
в первый раз), затем эти две команды имеют одинаковый эффект, следовательно, они выглядят как "два способа сделать что-то".
* Имейте в виду, предостережение, которое @DrewT упоминает в своем ответе относительно git rm --cached
файла, который был ранее зафиксирован в хранилище. В контексте этого вопроса о файле, который был только что добавлен и еще не зафиксирован, не о чем беспокоиться.
** Мне было страшно долгое время использовать команду git reset из-за ее названия - и до сих пор я часто просматриваю синтаксис, чтобы убедиться, что я не облажался. (обновление: я наконец нашел время, чтобы подвести итоги использования git reset
на странице tldr, так что теперь у меня есть лучшая ментальная модель того, как это работает, и краткий справочник, когда я забываю некоторые детали.)
Этот поток немного староват, но я все же хочу добавить небольшую демонстрацию, так как это все еще не интуитивная проблема:
me$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: to-be-added
# modified: to-be-modified
# deleted: to-be-removed
#
me$ git reset -q HEAD to-be-added
# ok
me$ git reset -q HEAD to-be-modified
# ok
me$ git reset -q HEAD to-be-removed
# ok
# or alternatively:
me$ git reset -q HEAD to-be-added to-be-removed to-be-modified
# ok
me$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: to-be-modified
# deleted: to-be-removed
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# to-be-added
no changes added to commit (use "git add" and/or "git commit -a")
git reset HEAD
(без -q
) выдает предупреждение об измененном файле и его код выхода равен 1, что будет считаться ошибкой в скрипте.
Редактировать: git checkout HEAD to-be-modified to-be-removed
также работает для unstaging, но полностью удаляет изменения из рабочей области
Если вы случайно создали файлы, которые не хотели бы фиксировать, и хотите быть уверены, что сохраните изменения, вы также можете использовать:
git stash
git stash pop
это выполнит сброс в HEAD и повторно применяет ваши изменения, позволяя вам повторно подготовить отдельные файлы для фиксации. это также полезно, если вы забыли создать функциональную ветвь для запросов извлечения (git stash ; git checkout -b <feature> ; git stash pop
).
В более новой версии > 2.2 вы можете использовать
git restore --staged <file_name>
. Примечание. Если вы хотите отменить (перейти к изменениям) ваши файлы по одному, вы используете приведенную выше команду с именем вашего файла. например
git restore --staged abc.html
Теперь, если вы хотите отключить весь файл сразу, вы можете сделать что-то вроде этого
git restore --staged .
Обратите внимание на пробел и точку (.), что означает считать все файлы подготовленными.
Эти 2 команды имеют несколько тонких отличий, если рассматриваемый файл уже находится в репозитории и находится под контролем версий (ранее зафиксирован и т. Д.):
git reset HEAD <file>
unstages файл в текущем коммите.git rm --cached <file>
также разархивирует файл для будущих коммитов. Это unstaged, пока это не будет добавлено снова сgit add <file>
,
И есть еще одно важное отличие:
- После запуска
git rm --cached <file>
и перенесите вашу ветку на удаленный, любой, кто вытаскивает вашу ветку с удаленного, получит файл, фактически удаленный из их папки, даже если в вашем локальном рабочем наборе файл просто не будет отслежен (то есть физически не удален из папки).
Это последнее различие важно для проектов, которые включают в себя конфигурационный файл, в котором каждый разработчик в команде имеет разный конфиг (т. Е. Разные базовые url, ip или настройки порта), поэтому, если вы используете git rm --cached <file>
любой, кто тянет вашу ветку, должен будет заново создать конфигурацию вручную, или вы можете отправить им свою собственную, и они могут повторно отредактировать ее обратно в свои настройки ip (и т. д.), потому что удаление только влияет на людей, тянущих вашу ветку с удаленного,
Скажем вам stage
весь каталог через git add <folder>
, но вы хотите исключить файл из поэтапного списка (то есть списка, который генерируется при запуске git status
) и сохраните изменения в исключенном файле (вы работали над чем-то, и он не готов к коммиту, но вы не хотите терять свою работу...). Вы можете просто использовать:
git reset <file>
Когда ты бежишь git status
, вы увидите, что любой файл (ы) вы reset
являются unstaged
а остальные файлы вы added
все еще в staged
список.
1.
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
(используйте "git rm --cached ..." для удаления)
Git это система указателей
у вас еще нет коммита, чтобы изменить указатель на
Единственный способ "извлечь файлы из корзины, на которую указывают", - это удалить файлы, которые вы сказали git, чтобы следить за изменениями.
2.
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a
git commit -ma
- вы совершили "спас"
3.
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
(используйте "git reset HEAD ..." для удаления)
- вы сделали коммит в своем коде в это время
- Теперь вы можете сбросить указатель на ваш коммит "вернуться к последнему сохранению"
Просто используйте:
git reset HEAD <filename>
Это деактивирует файл и сохраняет внесенные в него изменения, поэтому вы можете, в свою очередь, изменить ветки, если хотите, и git add
эти файлы вместо этого в другую ветку. Все изменения сохранены.
Только для версий 2.23 и выше,
Вместо этих предложений вы можете использоватьgit restore --staged <file>
чтобы unstage
файлы).
Unstaging файлы (отмена git add)
git restore --staged file.js # Копирует последнюю версию file.js из репозитория в индекс
отбрасывание локальных изменений
git restore file.js # Копирует file.js из индекса в рабочий каталог
git restore file1.js file2.js # Восстанавливает несколько файлов в рабочем каталоге
гит восстановить. # Отбрасывает все локальные изменения (кроме неотслеживаемых файлов)
git clean -fd # Удаляет все неотслеживаемые файлы
Я удивлен, что никто не упомянул git reflog ( http://git-scm.com/docs/git-reflog):
# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}
Reflog - это история git, которая не только отслеживает изменения в репозитории, но также отслеживает действия пользователя (например, извлечение, возврат в другую ветку и т. Д.) И позволяет отменить эти действия. Таким образом, вместо удаления файла, который был ошибочно подготовлен, вы можете вернуться к точке, в которой вы не ставили файлы.
Это похоже на git reset HEAD <file>
но в некоторых случаях может быть более гранулированным.
Извините - на самом деле не отвечаю на ваш вопрос, а просто указываю еще один способ нестандартных файлов, которые я использую довольно часто (например, мне очень нравятся ответы Райана Стюарта и Вальдириуса.);) Надеюсь, это поможет.
Мне кажется, что git rm --cached <file>
удаляет файл из индекса, не удаляя его из каталога, в котором находится простой git rm <file>
будет делать как, так и ОС rm <file>
удалит файл из каталога, не удаляя его версии.
Это было очень полезно. Я хотел сбросить файл, который я изменил. Это потребовало дополнительного шага git checkout . Я знаю, что это не замечает, но...
Я выполнил приведенные выше команды, но команда, которая сработала, похожа на то, когда вы находитесь в корне проекта, просто добавляя снимок экрана для большей ясности.
git rm --cached 'ios/AppName/Info.plist'
ИЛИ
git reset HEAD 'ios/AppName/Info.plist'