Existem muitos recursos online sobre git
, e alguns deles (como este) realmente se concentram no que acontece nesses cenários indesejados.
Mas sempre achei que faltavam esses recursos “porque” . Quando fornecido com um conjunto de comandos, o que cada comando faz? E como você chegou a esses comandos em primeiro lugar? 🤔
Dentro em um post anterior, forneci uma introdução visual aos componentes internos do Git. Apesar de compreender os aspectos internos de git
é útil, obter a teoria quase nunca é suficiente. Como aplicamos nosso conhecimento de git
internos e usá-lo para corrigir problemas em que nos metemos?
Neste post, gostaria de preencher essa lacuna e elaborar sobre o git reset
comando. Vamos entender o que git reset
faz nos bastidores e, em seguida, aplica esse conhecimento para resolver vários cenários. 😎
Fundamentos comuns – diretório de trabalho, índice e repositório
A fim de compreender os mecanismos internos de git reset
, é importante entender o processo de registro de mudanças dentro git
. Especificamente, quero dizer o diretor de trabalho, a índice, e a repositório.
Se você tiver certeza sobre esses termos, sinta-se à vontade para pular para a próxima seção. Se você quiser uma explicação ainda mais profunda, veja isto postagem anterior.
Quando trabalhamos em nosso código-fonte, trabalhamos a partir de um trabalho dir – qualquer diretório em nosso sistema de arquivos que tenha um repositórioassociado a isso. Ele contém as pastas e arquivos do nosso projeto, e também um diretório chamado .git
.
Depois de fazer algumas alterações, queremos gravá-las em nosso repositório . UMA repositório (repopara encurtar) é uma coleção de compromete , cada um dos quais é um arquivo do que o projeto árvore de trabalho parecia em uma data passada, seja em nossa máquina ou de outra pessoa.
Vamos criar um arquivo no diretório de trabalho e executar git status
:
Ainda, git
não confirma as alterações do árvore de trabalhodiretamente no repositório.
Em vez disso, as alterações são registradas primeiro em algo chamado de índice, ou o área de preparação. Ambos os termos se referem à mesma coisa e são usados com frequência em git
documentação de. Usaremos esses termos de forma intercambiável ao longo deste post.
Quando usamos git add
, adicionamos arquivos (ou alterações dentro de arquivos) ao área de preparação . Vamos usar este comando no arquivo que criamos anteriormente:
Como git status
revela, nosso arquivo é encenado(e pronto “para ser comprometido”). No entanto, não faz parte de nenhum comprometer. Em outras palavras, agora está no diretor de trabalho, assim como o índice, mas não no repositório .
Em seguida, quando usamos git commit
, nós criamos um comprometercom base no estado do índice . Então o novo comprometer (commit 3 no exemplo abaixo) incluirá o arquivo adicionado ao índice de antemão.
Em outras palavras, o diretor de trabalho tem exatamente o mesmo estado que o índicee a repositório .
O comando git commit
também faz o ramo atual master
aponte para o recém-criado comprometerobjeto.
O funcionamento interno do git reset
Eu gosto de pensar em git reset
como um comando que inverte o processo descrito acima (introduzindo uma mudança no diretor de trabalho, adicionando-o ao índice, e depois comprometerpara o repositório )
O reset do Git tem três modos de operação –--soft
, --mixed
, ou --hard
. Eu os vejo como três estágios:
- Etapa 1 – atualização
HEAD
–git reset --soft
- Estágio 2 – atualização índice–
git reset --mixed
- Estágio 3 – atualização diretor de trabalho –
git reset --hard
Etapa 1 – atualização HEAD
(git reset --soft
)
Primeiro, git reset
atualiza tudo HEAD
aponta para. Para git reset --hard HEAD~1
vai mover o que HEAD
aponta para (no exemplo acima, master
) para HEAD~1
. Se o— -soft
bandeira é usada, git reset
pára aí.
Continuando com nosso exemplo acima, HEAD
vai apontar para commit 2
, e assim new_file.txt
não fará parte da árvore do commit atual. Será, no entanto, parte do índice e a diretor de trabalho.
Olhando para git status
, podemos ver que o arquivo é realmente testado, mas não confirmado:
Em outras palavras, revertemos o processo para o estágio em que usamos git add
, mas ainda não usei git commit
.
Estágio 2 – atualizar índice para HEAD (git reset --mixed
)
Se usarmos git reset --mixed HEAD~1
, então git
não vai parar depois de atualizar o que quer que seja HEAD
aponta para ( master
)para HEAD~1
. Ele também atualizará o índice para (o já atualizado) HEAD
.
Em nosso exemplo, isso significa que o índice terá o mesmo estado que comprometer 2 :
Então, revertemos o processo para o estágio antes de usargit add
– o arquivo recém-criado agora faz parte do diretório de trabalho, mas o índice e a repositórionão são.
Estágio 3 – atualizar o diretório de trabalho para indexar (git reset --hard
)
Usando git reset — hard HEAD~1
, depois de atualizar tudo HEAD
aponta para (master
)para HEAD~1
, bem como atualizar o índice para (o já atualizado) HEAD
, git
seguirá em frente e atualizará o diretor de trabalho para se parecer com o índice.
Em nosso exemplo, isso significa que o diretor de trabalho terá o mesmo estado que o índice,que já tem o mesmo estado que comprometer 2:
Na verdade, revertemos todo o processo para antes mesmo de criar my_file.txt
.
Aplicando nosso conhecimento a cenários do mundo real
Agora que entendemos como git reset
funciona, vamos aplicar esse conhecimento para salvar o nosso dia! 💪
1. OOPS! Eu cometi algo por engano.
Vamos considerar o seguinte cenário. Criamos um arquivo com a string This is very importnt
, encenou e cometeu.
E então … Ops! Percebemos que ocorreu um erro de digitação. 🙈
Bem, agora sabemos que podemos resolver isso facilmente. Podemos reverter nosso último commit e obter o arquivo de volta para o diretório de trabalho usando git reset --mixed HEAD~1
. Agora, podemos editar o conteúdo do nosso arquivo, prepará-lo e confirmá-lo novamente.
Dica:neste caso específico, também podemos usar git commit --amend
, conforme descrito aqui.
2. OOPS! Eu comprometi algo no branch errado – e preciso disso em um novo branch
Todos nós já passamos por isso. Fizemos um pouco de trabalho e depois o comprometemos …
Oh não, nós nos comprometemos com master
branch, embora devêssemos ter criado um novo branch e emitido uma solicitação pull. 🙈
Neste estágio, acho útil visualizar o estado em que estamos e para onde gostaríamos de chegar:
Na verdade, existem três mudanças entre o estado atual e o desejado.
Primeiro, new
pontos de ramificação para nosso commit adicionado recentemente. Segundo, master
aponta para o commit anterior. Terceiro, HEAD
aponta para new
.
Podemos chegar ao estado desejado por meio de três etapas simples:
Primeiro, faça new
ponto de ramificação para o commit adicionado recentemente – isso pode ser feito simplesmente usando git branch new
. Portanto, alcançamos o seguinte estado:
Em segundo lugar, faça master
apontar para o commit anterior (em outras palavras, para HEAD~1
) Podemos fazer isso usando git reset --hard HEAD~1
. Portanto, alcançamos o seguinte estado:
Por último, gostaríamos de estar no ramo new
, isto é, façaHEAD
aponta para new
. Isso é facilmente alcançado executando git checkout new
.
Contudo:
git branch new
git reset --hard HEAD~1
git checkout new
3. OOPS! Eu comprometi algo no branch errado – e eu preciso disso em outro branch já existente
Nesse caso, seguimos as mesmas etapas do cenário anterior – fizemos algum trabalho e depois o comprometemos …
Oh não, nós nos comprometemos com master
branch, embora devêssemos ter nos comprometido com outro branch que já existe. 🙈
Vamos voltar à nossa prancheta:
Novamente, podemos ver que existem algumas diferenças aqui.
Primeiro, precisamos que o commit mais recente esteja em existing
ramo. Desde a master
atualmente aponta para ele, podemos simplesmente perguntar git
para pegar o commit recente de master
ramificar e aplicá-lo a existing
ramo assim:
git checkout existing
– Mudando paraexisting
ramogit cherry-pick master
– aplicando o último commit emmaster
ramificar para o atual (existing
) ramo
Agora, chegamos ao seguinte estado:
Agora só precisamos fazer master
aponte para o commit anterior, ao invés do último. Para isso podemos:
git checkout master
– mude a ramificação ativa paramaster
novamente.git reset --hard HEAD~1
– agora estamos de volta ao ramo original.
E alcançamos nosso estado desejado:
Resumo
Nesta postagem, aprendemos como git reset
opera, e esclareceu seus três modos de operação –--soft
, --mixed
, e --hard
.
Em seguida, aplicamos nosso conhecimento sobre git reset
para resolver alguns problemas da vida real com git
.
Compreendendo o caminho git
opera, podemos enfrentar com segurança todos os tipos de cenários e também apreciar a beleza desta ferramenta 😎
Em postagens futuras, abordaremosgit
comandos e como eles podem nos ajudar a resolver todos os tipos de situações indesejadas.
Omer Rosenbaum, NadarDiretor de Tecnologia da. Especialista em treinamento cibernético e fundador da Checkpoint Security Academy. Autor de Redes de Computadores (em hebraico). Me visite Canal do Youtube.
Recursos adicionais