Есть ли разница между «git reset --hard hash» и «git checkout hash»?

StackOverflow https://stackoverflow.com/questions/2541545

  •  23-09-2019
  •  | 
  •  

Вопрос

Пока reset и checkout большую часть времени используются по-разному, я не вижу, какая разница между этими двумя.

Вероятно, есть один, иначе никто бы не удосужился добавить --hard возможность сделать что-то основное checkout сможет сделать.

Может быть, есть разница в том, как вы смотрите на историю?

Это было полезно?

Решение

Этот ответ в основном цитируется из моего ответа на предыдущий вопрос: git сброс на простом английском языке.

Эти двое очень разные.Они приводят к одному и тому же состоянию вашего индекса и рабочего дерева, но результирующая история и текущая ветвь не совпадают.

Предположим, ваша история выглядит так: в данный момент извлечена основная ветка:

- 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 тоже - единственная разница в том, что происходит с вашим рабочим деревом и индексом.в --hard случае рабочее дерево и индекс совпадают B.

Теперь предположим, что вы побежите git checkout B вместо.Вы получите это:

- A - B (HEAD) - C (master)

Вы оказались в состоянии отсоединенного HEAD. HEAD, рабочее дерево, индекс все совпадают B, то же самое, что и при аппаратном сбросе, но главная ветка осталась C.Если вы сделаете новый коммит D на этом этапе вы получите это, что, вероятно, не то, что вы хотите:

- A - B - C (master)
       \
        D (HEAD)

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

Другие советы

Если документация, поставляемая с Git, вам не помогает, взгляните на Визуальный справочник по Git Марк Лодато.

В частности, если вы сравниваете git checkout <non-branch> с git reset --hard <non-branch> (ссылка):

git checkout master~3
(источник: github.com)

git reset --hard master~3

Обратите внимание, что в случае git reset --hard master~3 вы оставляете часть ревизий DAG — на некоторые коммиты не ссылается ни одна ветка.Они защищены (по умолчанию) 30 дней перезаписать;в конечном итоге они будут обрезаны (удалены).

git-reset hash устанавливает ссылку на ветку для данного хеша и, при необходимости, проверяет ее с помощью--hard.

git-checkout hash устанавливает рабочее дерево по заданному хэшу;и если хеш не является именем ветки, вы получите оторванную голову.

в конечном счете, git имеет дело с тремя вещами:

                   working tree (your code)
-------------------------------------------------------------------------
                     index/staging-area
-------------------------------------------------------------------------
      repository (bunch of commits, trees, branch names, etc)

git-checkout по умолчанию просто обновляет индекс и рабочее дерево и при желании может обновить что-то в репозитории (с помощью -b вариант)

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, то есть HEAD указывает на theme2.

HEAD -> topic2

Затем, git reset X сбросит имя topic2 указать на Х;то есть, если вы сделаете коммит P в ветке theme2, все будет выглядеть так:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic3]
                           \
                            P [topic2]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top