Подтвердить что ты не робот

Git reset vs git reset HEAD

Каждый раз, когда файл ставится в очередь, Git предлагает полезные инструкции в случае, если вам нужно было отключить файл:

(use "git reset HEAD <file>..." to unstage)

Однако порядочный Git учебник Atlassian просто скажет:

git reset <file>

Это кажется более простым, поэтому почему разница?

4b9b3361

Ответ 1

Нет разницы (от git reset справочной страницы) в отношении параметра по умолчанию:

<tree-ish>/<commit> по умолчанию HEAD во всех формах.

Изначально это сообщение не содержало HEAD: commit 3c1eb9c, январь 2007 г., git 1.5.0-rc1, но, поскольку значение по умолчанию не всегда известно, справочное сообщение проясняет, какой коммит вы должны делать сброса.

HEAD появляется в коммите 367c988, ноябрь 2007 г., Git 1.5.4:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)

Торек указывает на реальную разницу в комментариях:

Указав HEAD, вы гарантируете, что первое слово после HEAD будет использовано в качестве имени пути.
Например, предположим, что вы запускаете git reset zorg. Является ли zorg древовидной версией, такой как имя тега, или это путь, ./zorg?
Ответ Git: это древовидная структура, если git rev-parse может превратить его в идентификатор дерева, в противном случае это путь.
Вы можете написать git reset -- zorg или git reset HEAD zorg, чтобы убедиться, что git рассматривает его как путь.

Подробнее о синтаксисе двойных дефисов (--) см. в разделе "Удаление ветки git с плохим именем".




OP skube добавляет в комментарии:

Кроме того, они предлагают это для отмены изменений в рабочем каталоге
(т.е. git checkout -- <file>).
Это просто кажется несовместимым с git reset HEAD <file>.

Хотя git reset справочная страница четко указывает на отсутствие древовидной структуры в git reset <tree-ish> -- <paths>, означает HEAD, это не так для git checkout <tree-ish> -- <paths>.

git checkout <tree-ish> -- <pathspec>

Когда задано <paths>, git checkout не переключает ветки.
Он обновляет именованные пути в рабочем дереве из индексного файла или из именованного <tree-ish> (чаще всего коммит).

Это означает, что git checkout -- path переопределит рабочее дерево с тем, что уже было подготовлено (git add 'ed).
В то время как git reset -- PATH (будучи смешанной формой git reset) будет сбрасывать индекс с тем, что содержит HEAD (эффективно не ставя то, что было добавлено)

git reset и git checkout не используют одно и то же по умолчанию, и:

  • Вы можете представить дерево по умолчанию для git reset <tree-ish> <file>: HEAD.
    Следовательно git reset HEAD <file>;
  • но вы не можете представить параметр по умолчанию, если вы не предоставляете дерево для git checkout: это индекс.
    Отсюда git checkout -- file.

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

Обратите внимание, что git checkout HEAD files отличается: Торек упоминает в комментариях

. git checkout HEAD path копирует из коммита HEAD (tree-ish) в индекс, а затем в рабочий каталог.


Примечание. В Git 2. 23+, август 2019 г., вместо этого можно использовать git restore instead

.Смотрите примеры:

Чтобы восстановить файл в индексе, чтобы он соответствовал версии в HEAD (это аналогично использованию git-reset)

$ git restore --staged hello.c

Страница справочника:

git restore --staged hello.c не указывает источник и восстанавливает только индекс (--staged): он делает это (по умолчанию), используя HEAD в качестве источника.

По умолчанию источниками восстановления для рабочего дерева и индекса являются соответственно индекс и HEAD.
--source можно использовать для указания фиксации в качестве источника восстановления.

Другие примеры:

Вы можете восстановить как индекс, так и рабочее дерево (это так же, как при использовании git-checkout)

$ git restore --source=HEAD --staged --worktree hello.c

или краткая форма, которая более практична, но менее читабельна:

$ git restore [email protected] -SW hello.c

git restore является более естественным именем команды и не имеет двусмысленности.

Ответ 2

По умолчанию git reset эквивалентно git reset HEAD

Цитата man-страницы (мой акцент):

git - reset - Reset текущий HEAD в указанное состояние.

git reset [-q] [<tree-ish>] [--] <paths>…
git reset (--patch | -p) [<tree-ish>] [--] [<paths>…​]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

В первой и второй форме скопируйте записи из < tree-ish > в индекс. В третьей форме установите текущую ветвь ветки (HEAD) в <commit> , опционально изменяя индекс и рабочее дерево для соответствия. The < tree-ish > /<commit> по умолчанию используется HEAD во всех формах.

[...]

git reset [-q] [<tree-ish>] [--] <paths>…​

Эта форма сбрасывает записи индекса для всех <paths> в их состояние в < tree-ish > . (Это не влияет на рабочее дерево или текущий филиал.)

Это означает, что git reset <paths> является противоположностью git add <paths>.

Из этого вы видите, что нет реальной разницы в поведении.

Это кажется более простым, поэтому почему разница?

Поскольку они оба одинаковы, вы можете использовать кратчайшую версию этих двух.

Ответ 3

В первый раз, прежде чем какое-либо зафиксировать HEAD не существует, получим:

$git reset HEAD stagedFile
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree