ti-enxame.com

Qual é a diferença entre "git reset" e "git checkout"?

Eu sempre pensei em git reset e git checkout como o mesmo, no sentido de que ambos trazem o projeto de volta para um commit específico. No entanto, sinto que não podem ser exatamente iguais, pois isso seria redundante. Qual é a diferença real entre os dois? Estou um pouco confuso, pois o svn só tem svn co para reverter o commit.

ADICIONADO

VonC e Charles explicaram as diferenças entre git reset e git checkout muito bem. Meu entendimento atual é que git reset reverte todas as alterações de volta para um commit específico, enquanto git checkout é mais ou menos preparado para um branch. Eu achei os dois diagramas a seguir bastante úteis para chegar a esse entendimento:

http://a.imageshack.us/img651/1559/86421927.pnghttp://a.imageshack.us/img801/1986/resetr.png

ADICIONADO 3

De http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html =, checkout e reset podem emular o rebase.

enter image description here

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

enter image description here

393
prosseek
  • git reset é especificamente sobre atualizar o índice , movendo o HEAD.
  • git checkout é sobre atualizar a árvore de trabalho (para o índice ou a árvore especificada). Ele atualizará o HEAD somente se você fizer o checkout de um branch (se não, você acabará com um HEAD desanexado ).

Em comparação, como o svn não possui um índice, somente uma árvore de trabalho svn checkout copiará uma determinada revisão em um diretório separado.
O equivalente mais próximo para git checkout seria:

  • svn update (se você estiver no mesmo ramo, significando o mesmo URL do SVN)
  • svn switch (se você verificar, por exemplo, o mesmo ramo, mas de outro URL de reporte do SVN)

Todas essas três modificações da árvore de trabalho (svn checkout, update, switch) possuem apenas um comando no git: git checkout.
Mas como o git também tem a noção de índice (aquela "área de teste" entre o repositório e a árvore de trabalho), você também possui git reset.


Thinkeye menciona nos comentários o artigo " Redefinir Desmistificado ".

Por exemplo, se temos duas ramificações, 'master' e 'develop' apontando para diferentes commits, e estamos atualmente em 'develop' (então HEAD aponta para ele) e nós rodamos git reset master, 'develop 'agora apontará para o mesmo commit que' master 'faz.

Por outro lado, se, em vez disso, executarmos git checkout master, 'develop' não será movido, HEAD será o próprio. HEAD agora apontará para 'master'.

Então, em ambos os casos, estamos movendo HEAD para apontar para commitar A, mas como fazemos isso é muito diferente. reset irá mover a ramificação HEAD pontos para checkout move a própria HEAD para apontar para outra ramificação.

http://git-scm.com/images/reset/reset-checkout.png

Nesses pontos, porém:

LarsH adiciona nos comentários :

O primeiro parágrafo desta resposta, porém, é enganoso: "git checkout ... atualizará o HEAD somente se você fizer o checkout de um branch (se não, você terminará com um HEAD separado)".
Não é verdade: git checkout atualizará o HEAD mesmo se você fizer o checkout de um commit que não é um branch (e sim, você acaba com um HEAD separado, mas ele ainda é atualizado).

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novo concurs nos comentários :

@LarsH está correto.
A segunda bala tem um equívoco sobre o que HEAD está em atualizará o HEAD somente se você fizer o checkout de uma ramificação.
. CABEÇA vai onde quer que você esteja, como uma sombra.
Fazer check-out de algum ref não-filial (por exemplo, um tag) ou um commit diretamente, moverá o HEAD. Cabeçalho desanexado não significa que você se desvinculou da CABEÇA, significa que a cabeça é separada de uma ref de ramificação, da qual você pode ver, por exemplo, git log --pretty=format:"%d" -1.

  • Cabeçalhos anexados começarão com (HEAD ->,
  • desanexado ainda mostrará (HEAD, mas não terá uma seta para um ramo ref.
171
VonC

Em sua forma mais simples, reset redefine o índice sem tocar na árvore de trabalho, enquanto checkout altera a árvore de trabalho sem tocar no índice.

Redefine o índice para corresponder a HEAD, árvore de trabalho deixada sozinha:

git reset

Conceitualmente, isso verifica o índice na árvore de trabalho. Para fazê-lo realmente fazer qualquer coisa, você teria que usar -f para forçá-lo a sobrescrever quaisquer alterações locais. Esse é um recurso de segurança para garantir que o formulário "sem argumento" não seja destrutivo:

git checkout

Depois de começar a adicionar parâmetros, é verdade que existe alguma sobreposição.

checkout é geralmente usado com um branch, tag ou commit. Nesse caso, ele reconfigurará HEAD e o índice para o commit fornecido, além de executar a verificação do índice na árvore de trabalho.

Além disso, se você fornecer --hard para reset, poderá solicitar reset para sobrescrever a árvore de trabalho e também para redefinir o índice.

Se você tem um branch verificado atualmente, existe uma diferença crucial entre reset e checkout quando você fornece um branch ou commit alternativo. reset mudará a ramificação atual para apontar para a confirmação selecionada, enquanto que checkout deixará a ramificação atual sozinha, mas fará checkout da ramificação ou confirmação fornecida.

Outras formas de reset e commit envolvem o fornecimento de caminhos.

Se você fornecer caminhos para reset, você não poderá fornecer --hard e reset somente alterará a versão do índice dos caminhos fornecidos para a versão na confirmação fornecida (ou HEAD, se você não especificar uma confirmação).

Se você fornecer caminhos para checkout, como reset, ele atualizará a versão de índice dos caminhos fornecidos para corresponder à confirmação fornecida (ou HEAD), mas sempre fará o checkout da versão de índice dos caminhos fornecidos na árvore de trabalho.

61
CB Bailey

Um caso de uso simples ao reverter a alteração:
1. Use reset se você quiser desfazer o teste de um arquivo modificado.
2. Use o checkout se você quiser descartar as alterações no arquivo/s não processado.

28
John Doe

Atlassian nos dê uma excelente explicação sobre git reset , git checkout e assim, git revert . Neste artigo, são explicados os diferentes usos desses comandos em diferentes níveis - arquivo, instantâneo e confirmação.

https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

9
Rochadsouza

A principal diferença em poucas palavras é que reset move a referência de ramificação atual , enquanto checkout não (move HEAD).

Como o livro Pro Git explica em Redefinir Desmistificado ,

A primeira coisa que reset fará é mover o que HEAD aponta para . Isso não é o mesmo que mudar HEAD propriamente dito (que é o que checkout faz); reset move a ramificação que HEAD está apontando para. Isso significa que se HEAD for definido como a ramificação master (ou seja, você está atualmente na ramificação master), a execução de git reset 9e5e6a4 começará fazendo com que master aponte para 9e5e6a4. [enfase adicionada]

Veja também a resposta de VonC para a texto muito útil e trecho do diagrama do mesmo artigo, que não vou duplicar aqui.

É claro que há muito mais detalhes sobre quais efeitos checkout e reset podem ter no índice e na árvore de trabalho, dependendo de quais parâmetros são usados. Pode haver muitas semelhanças e diferenças entre os dois comandos. Mas, do meu ponto de vista, a diferença mais crucial é se eles movem a ponta do ramo atual.

8
LarsH

Os dois comandos (reset e checkout) são completamente diferentes.

checkout X IS NÃO reset --hard X

Se X for um nome de ramificação, checkout X alterará o ramo atual enquanto reset --hard X não.

1
wiki1000