Есть ли разница между" git reset --hard hash "и"git checkout hash"?
пока reset
и checkout
имеют разные обычаи большую часть времени, я не вижу, какая разница между этими двумя.
вероятно, есть один или никто не потрудился бы добавить --hard
возможность сделать что-то основное checkout
можно сделать.
может быть, есть разница в том, как вы будете видеть историю?
3 ответов
этот ответ в основном цитируется из моего ответа на предыдущий вопрос:git reset на простом английском языке.
эти два очень разные. Они приводят к одинаковому состоянию для вашего индекса и дерева работы, но результирующая история и текущая ветвь не совпадают.
предположим, что ваша история выглядит так, с главной веткой в настоящее время проверено:
- A - B - C (HEAD, master)
а ты беги git reset --hard B
. Вы получите это:
- A - B (HEAD, master) # - C is still here, but there's no
# branch pointing to it anymore
вы действительно получите этот эффект, если используете --mixed
или --soft
too-единственная разница заключается в том, что происходит с вашим деревом работы и индексом. В --hard
case, дерево работы и индекс совпадают B
.
теперь, предположим, вы побежите . Вы получите это:
- A - B (HEAD) - C (master)
вы оказались в отдельной главе государства. HEAD
, дерево работы, индекс все Матч B
, то же, что и с жестким сбросом, но главная ветвь осталась позади на C
. Если вы сделаете новый commit D
в этот момент Вы получите это, что, вероятно, не то, что вы хотите:
- A - B - C (master)
\
D (HEAD)
Итак, вы используете checkout, чтобы, ну, проверить эту фиксацию. Вы можете играть с ним, делать что хотите, но вы оставили свою ветку позади. Если вы тоже хотите переместить ветку, используйте reset.
Если документация, предоставленная с Git, не поможет вам, взгляните на Визуальная Ссылка Git Марк Lodato.
в частности, если вы сравниваете git checkout <non-branch>
с git reset --hard <non-branch>
(hotlinked):
мастер проверки git~3 http://marklodato.github.com/visual-git-guide/checkout-detached.svg.png
сброс git --жесткий мастер~3 http://marklodato.github.com/visual-git-guide/reset-commit.svg.png
Примечание. что в случае git reset --hard master~3
вы оставляете часть DAG ревизий - на некоторые из коммитов не ссылается ни одна ветвь. Они защищены в течение (по умолчанию) 30 дней reflog; они в конечном счете будут обрезаны (удалены).
git-reset hash
устанавливает ссылку на ветку для данного хэша и дополнительно проверяет ее с помощью--hard
.
git-checkout hash
устанавливает рабочее дерево в заданный хэш; и если хэш не является именем ветви, вы получите отделенную голову.
в конечном счете, git имеет дело с 3 вещами:
working tree (your code)
-------------------------------------------------------------------------
index/staging-area
-------------------------------------------------------------------------
repository (bunch of commits, trees, branch names, etc)
git-checkout
по умолчанию просто обновляет индекс и рабочее дерево, и при необходимости можно обновить что-то в репозитории (с -b
вариант)
git-reset
по умолчанию просто обновляет репозиторий и индекс, а также, возможно, рабочее дерево (с помощью )
вы можете думать о репозитории так:
HEAD -> master
refs:
master -> sha_of_commit_X
dev -> sha_of_commit_Y
objects: (addressed by sha1)
sha_of_commit_X, sha_of_commit_Y, sha_of_commit_Z, sha_of_commit_A ....
git-reset
манипулирует тем, на что указывают ссылки ветви.
предположим, что ваша история выглядит так:
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic2][topic3]
имейте в виду, что ветви-это просто имена, которые автоматически продвигаются при фиксации.
Так вы имеют следующие ветви:
master -> Q
dev -> Q
topic1 -> G
topic2 -> W
topic3 -> W
и ваша текущая ветвь -topic2
, то есть голова указывает на topic2.
HEAD -> topic2
затем, git reset X
сброс именем topic2
чтобы указать на X; то есть, если вы сделаете фиксацию P на ветке topic2, все будет выглядеть так:
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic3]
\
P [topic2]