Почему есть два способа удалить файл из 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