В то время как reset
и checkout
имейте различные использования большую часть времени, я не вижу то, что различие там между этими двумя.
Вероятно, существует один, или никто не потрудился бы добавлять a --hard
опция сделать что-то основное checkout
может сделать.
Возможно, существует различие, способ, которым Вы будете видеть историю?
Этот ответ в основном цитируется из моего ответа на предыдущий вопрос: 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
Вы действительно получите этот эффект, если используете - смешанный
или - мягкий
тоже - единственная разница в том, что происходит с вашим деревом работы и index. В - сложном
случае дерево работы и индекс соответствуют B
.
Теперь предположим, что вместо этого вы запустите git checkout B
. Вы получите следующее:
- A - B (HEAD) - C (master)
Вы оказались в состоянии отсоединенной HEAD. HEAD
, дерево работ, индекс все соответствует B
, то же самое, что и при аппаратном сбросе, но главная ветвь осталась позади на C
. Если вы сделаете новую фиксацию D
на этом этапе, вы получите это, что, вероятно, не то, что вам нужно:
- A - B - C (master)
\
D (HEAD)
Итак, вы используете checkout, чтобы проверить эту фиксацию. Вы можете возиться с этим, делать что хотите, но вы оставили свою ветку позади.Если вы хотите, чтобы ветка тоже переместилась, используйте сброс.
git-reset hash
устанавливает ссылку ветки на заданный хэш и, при необходимости, проверяет его с помощью - hard
.
git-checkout hash
устанавливает для рабочего дерева заданный хэш; и если hash не является именем ветки, у вас будет отдельная голова.
в конечном счете, git имеет дело с тремя вещами:
working tree (your code)
-------------------------------------------------------------------------
index/staging-area
-------------------------------------------------------------------------
repository (bunch of commits, trees, branch names, etc)
git-checkout
по умолчанию просто обновляет индекс и рабочее дерево, а также может при желании обновлять что-то в репозитории (с помощью -b
option)
git-reset
по умолчанию просто обновляет репозиторий и индекс, а также, необязательно, рабочее дерево (с опцией - hard
)
Репозиторий можно рассматривать как это:
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]
Если документация, поставляемая с Git'ом, вам не поможет, взгляните на A Visual Git Reference Марка Лодато.
В частности, если вы сравниваете git checkout
с git reset --hard
(горячая ссылка):
(source: github. com)
Обратите внимание, что в случае git reset --hard master~3
вы оставляете часть DAG ревизий - на некоторые коммиты не ссылается ни одна ветвь. Они защищены (по умолчанию) на 30 дней с помощью reflog; в конечном итоге они будут обрезаны (удалены).