Почему есть два способа удалить файл из Git?
Иногда git предлагает git rm --cached
отключить файл, иногда git reset HEAD file
. Когда следует использовать какой?
EDIT:
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
#
Ответы
Ответ 1
git rm --cached <filePath>
не удаляет файл, а фактически удаляет файл (ы) из репозитория (если он уже был зафиксирован ранее), но оставляет файл в рабочем дереве (оставляя вас без отслеживания). файл).
git reset -- <filePath>
отменяет любые поэтапные изменения для данного файла (файлов).
Тем не менее, если бы вы использовали git rm --cached
для нового файла, который находится в git rm --cached
подготовки, это выглядело бы так, как будто вы только что установили его, поскольку он никогда не был зафиксирован ранее.
Ответ 2
git rm --cached
используется для удаления файла из индекса. В случае, когда файл уже находится в репо, git rm --cached
удалит файл из индекса, оставив его в рабочем каталоге, и фиксация также удалит его из репо. В принципе, после фиксации вы бы не перенесли файл и сохранили локальную копию.
git reset HEAD file
(который по умолчанию использует флаг --mixed
) отличается тем, что в случае, когда файл уже находится в репо, он заменяет индексную версию файла ссылкой на репо (HEAD), эффективно не используя модификации.
В случае неверсированного файла он будет отключать весь файл, поскольку файл не был в HEAD. В этом аспекте git reset HEAD file
и git rm --cached
одинаковы, но они не одинаковы (как описано в случае файлов, уже находящихся в репо)
К вопросу о Why are there 2 ways to unstage a file in git?
- никогда не существует только одного способа сделать что-либо в git. это его красота:)
Ответ 3
Довольно просто:
-
git rm --cached <file>
заставляет git полностью останавливать файл полностью (оставляя его в файловой системе, в отличие от простой git rm
*)
-
git reset HEAD <file>
отменяет любые изменения, внесенные в файл с момента последнего фиксации (но не возвращает их в файловой системе, в отличие от того, что может предложить название команды **). Файл остается под контролем версии.
Если раньше файл не находился в контроле версий (т.е. вы не выполняете форматирование файла, который у вас был только git add
ed в первый раз), тогда две команды имеют одинаковый эффект, следовательно, появление этих "два способа сделать что-то".
* Имейте в виду, что в его ответе упоминается оговорка @DrewT, касающаяся git rm --cached
файла, который ранее был привязан к репозиторию. В контексте этого вопроса, файл только что добавлен и еще не зафиксирован, не о чем беспокоиться.
** Я боялся смущающе долгое время использовать команду git reset из-за ее имени - и сегодня я часто просматриваю синтаксис, чтобы убедиться, что я не испортил, (update): я наконец-то нашел время обобщил использование git reset
на странице TL;DR, так что теперь я имеют лучшую ментальную модель того, как она работает, и краткое описание, когда я забываю некоторые детали.)
Ответ 4
Этот поток немного староват, но я все же хочу добавить небольшую демонстрацию, так как это все еще не интуитивная проблема:
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 2.23.0: Время от времени команды меняются. Теперь git status
говорит:
(use "git restore --staged <file>..." to unstage)
... который работает для всех трех типов изменений
Ответ 5
если вы случайно поставили файлы, которые не хотели бы совершать, и хотите быть уверенными, что сохраните изменения, вы также можете использовать:
git stash
git stash pop
это выполняет reset в HEAD и повторно применяет ваши изменения, позволяя вам перегруппировать отдельные файлы для фиксации. это также полезно, если вы забыли создать ветвь функции для запросов на pull (git stash ; git checkout -b <feature> ; git stash pop
).
Ответ 6
Эти две команды имеют несколько тонких отличий, если этот файл уже находится в репо и под управлением версии (ранее были зафиксированы и т.д.):
-
git reset HEAD <file>
отключает файл в текущей фиксации.
-
git rm --cached <file>
также отключит файл для будущих коммитов. Он не установлен, пока он не будет добавлен снова с помощью git add <file>
.
И еще одно важное различие:
- После запуска
git rm --cached <file>
и нажмите на свою ветку на удаленный компьютер, любой, кто потянет вашу ветку с удаленного, получит файл, ФАКТИЧЕСКИ удаленный из своей папки, хотя в вашем локальном рабочем наборе файл просто перестает быть просмотренным (то есть физически не удаляется из папки).
Это последнее отличие важно для проектов, которые включают конфигурационный файл, в котором каждый разработчик в команде имеет другую конфигурацию (то есть другой базовый url, ip или порт), поэтому, если вы используете git rm --cached <file>
, тот, кто тянет вашу ветку вам придется вручную заново создать конфигурацию, или вы можете отправить их вам, и они могут повторно отредактировать ее обратно в свои настройки ip (и т.д.), потому что удаление только влияет на то, что люди вытаскивают вашу ветку с удаленного.
Ответ 7
Скажем, вы stage
весь каталог через git add <folder>
, но вы хотите исключить файл из поэтапного списка (т.е. список, который генерируется при запуске git status
) и сохранить изменения в исключенном файле (вы что-то работали и не готовы к фиксации, но вы не хотите потерять свою работу...). Вы можете просто использовать:
git reset <file>
Когда вы запустите git status
, вы увидите, что любой файл вы reset
равны unstaged
, а остальные файлы, которые вы added
, все еще находятся в списке staged
.
Ответ 8
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 -m a
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...", чтобы отключиться)
- вы сделали фиксацию в своем коде в настоящее время
- теперь вы можете reset указатель на вашу фиксацию вернуться к последнему сохранению
Ответ 9
Я удивлен, что никто не упомянул git reflog (http://git-scm.com/docs/git-reflog):
# git reflog
<find the place before your staged anything>
# git reset [email protected]{1}
reflog - это git история, которая не только отслеживает изменения в репо, но также отслеживает действия пользователя (например, pull, checkout to different branch и т.д.) и позволяет отменить эти действия. Поэтому вместо отказа от файла, который был ошибочно поставлен, где вы можете вернуться к точке, где вы не создавали файлы.
Это похоже на git reset HEAD <file>
, но в некоторых случаях может быть более зернистым.
Извините - не отвечая на ваш вопрос, а просто указывая еще один способ нестационарных файлов, которые я использую довольно часто (я, например, как и ответы Райана Стюарта и очень валидный).) Надеюсь, это поможет.
Ответ 10
Мне кажется, что git rm --cached <file>
удаляет файл из индекса, не удаляя его из каталога, где будет выполняться простой git rm <file>
, так же как OS rm <file>
удалит файл из каталога без удаления его версии.
Ответ 11
Просто используйте:
git reset HEAD <filename>
Это освобождает файл от файла и сохраняет изменения, которые вы внесли в него, так что вы, в свою очередь, можете изменить ветки, если хотите, и вместо этого git add
перевести эти файлы в другую ветку. Все изменения сохранены.
Ответ 12
Чтобы не обращать внимание на весь каталог, используйте rm рекурсивно (-r)
git rm -r --cached folderpath