Existe uma diferença entre "Hash -hard hash de" Git Reset -e "Hash de checkout do git"?
-
23-09-2019 - |
Pergunta
Enquanto reset
e checkout
Tenha usos diferentes na maioria das vezes, não consigo ver que diferença existe entre esses dois.
Provavelmente existe um ou ninguém teria se incomodado em adicionar um --hard
opção para fazer algo o básico checkout
pode fazer.
Talvez haja uma diferença é a maneira como você verá a história?
Solução
Esta resposta é citada principalmente da minha resposta para uma pergunta anterior: Reset Git em inglês simples.
Os dois são muito diferentes. Eles resultam no mesmo estado para o seu índice e árvore de trabalho, mas o histórico e o ramo atual resultantes não são os mesmos.
Suponha que sua história se pareça com isso, com a filial mestre atualmente check -out:
- A - B - C (HEAD, master)
E você corre git reset --hard B
. Você vai conseguir isso:
- A - B (HEAD, master) # - C is still here, but there's no
# branch pointing to it anymore
Você realmente obteria esse efeito se usar --mixed
ou --soft
Também - a única diferença é o que acontece com sua árvore de trabalho e índice. No --hard
caso, a árvore de trabalho e correspondência de índice B
.
Agora, suponha que você corra git checkout B
em vez de. Você entenderia isso:
- A - B (HEAD) - C (master)
Você acabou em um estado de cabeça isolada. HEAD
, árvore de trabalho, índice todos correspondem B
, o mesmo que com a redefinição dura, mas o ramo mestre foi deixado para trás em C
. Se você fizer um novo compromisso D
Neste ponto, você conseguirá isso, o que provavelmente não é o que você deseja:
- A - B - C (master)
\
D (HEAD)
Então, você usa a compra para, bem, confira esse compromisso. Você pode mexer com isso, fazer o que quiser, mas deixou seu galho para trás. Se você deseja que o ramo também seja movido, você usa a redefinição.
Outras dicas
Se a documentação fornecida com o Git não o ajudar, dê uma olhada em Uma referência visual git por Mark Lodato.
Em particular se você estiver comparando git checkout <non-branch>
com git reset --hard <non-branch>
(HotLinked):
(fonte: github.com)
Observe que no caso de git reset --hard master~3
Você deixa para trás uma parte do DAG de revisões - algumas das confirmações não são referenciadas por nenhuma filial. Esses são protegidos por (por padrão) 30 dias por Reflogue; Eles acabariam sendo podados (removidos).
git-reset hash
define a referência da filial ao hash dado e opcionalmente verifica, com--hard
.
git-checkout hash
define a árvore de trabalho para o hash dado; E, a menos que o hash seja um nome de filial, você acabará com uma cabeça destacada.
Por fim, o GIT lida com 3 coisas:
working tree (your code)
-------------------------------------------------------------------------
index/staging-area
-------------------------------------------------------------------------
repository (bunch of commits, trees, branch names, etc)
git-checkout
Por padrão, apenas atualiza o índice e a árvore de trabalho e pode opcionalmente atualizar algo no repositório (com o -b
opção)
git-reset
Por padrão, apenas atualiza o repositório e o índice e, opcionalmente, a árvore de trabalho (com o --hard
opção)
Você pode pensar no repositório como este:
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
manipula o que as referências do ramo apontam.
Suponha que sua história se pareça com a seguinte:
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic2][topic3]
Lembre -se de que os ramos são apenas nomes que avançam automaticamente quando você se compromete.
Então você tem os seguintes ramos:
master -> Q
dev -> Q
topic1 -> G
topic2 -> W
topic3 -> W
E sua filial atual é topic2
, isto é, a cabeça aponta para o tópico2.
HEAD -> topic2
Então, git reset X
redefinirá o nome topic2
apontar para x; Ou seja, se você formar um comprometimento no tópico do ramo 2, as coisas ficarão assim:
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic3]
\
P [topic2]