Git
Chapters ▾ 2nd Edition

2.4 Noções Básicas do Git - Desfazer Coisas

Desfazer Coisas

A qualquer momento tu podes querer desfazer algo. Aqui vamos analisar algumas ferramentas básicas usadas para desfazer as alterações que tu fizeste. Te, cuidado, às vezes não é possível recuperar algo depois de o ter desfeito. Esta é uma das poucas áreas em que a Git pode perder parte do seu trabalho se cometer um erro.

Um dos itens comuns ocorre quando cometes muito cedo e, possivelmente esqueçes de adicionar alguns arquivos ou confundes a tua mensagem de confirmação. Se quiseres refazer esta confirmação, faz as alterações adicionais que te esqueceste, coloca-as e confirma novamente usando a opção --amend:

$ git commit --amend

Este comando usa a tua área de preparação para confirmação. Se não fizeste alterações desde a tua última confirmação (por exemplo, executas este comando logo após a confirmação anterior), o instantâneo ficará exatamente o mesmo, e a única coisa que tu mudarás é a mensagem de confirmação.

O mesmo editor de confirmação será iniciado, mas tu verás que já inclui a mensagem da tua confirmação anterior. Podes editar a mensagem como de costume e a tua confirmação anterior será substituída.

Por exemplo, se confirmares e depois perceberes que te esqueceste de preparar as alterações num arquivo que tu querias incluir nesta confirmação, tu podes fazer o seguinte:

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

No final, acabarás com apenas uma confirmação — a segunda confirmação substitui o resultado da primeira.

É importante entender que, quando estás a modificar a tua última confirmação, não estás tanto a arranjar-la como a substituir inteiramente com uma nova confirmação melhorada que empurra a antiga confirmação fora do caminho e coloca a nova confirmação no seu lugar. Efectivamente, é como se a confirmação anterior nunca acontecesse, e não aparecerá no teu histórico do repositório.

O valor óbvio para comprometer confirmações é fazer melhorias menores para a tua última confirmação, sem aglomerar o histórico do repositório com as mensagens de confirmação do formulário, “Oops, esqueci de adicionar um arquivo” ou “Darn, a corrigir um erro de digitação na última confirmação”.

Desfazer um Arquivo Preparado

As próximas duas seções demonstram como lidar com as mudanças na tua área de preparação e seu diretório de trabalho. Felizmente, o comando que tu usas para determinar o estado destas duas áreas também lembra como desfazer as mudanças neles. Por exemplo, supõe que tenhas mudado dois arquivos e que as confirmações como duas mudanças separadas, mas acidentalmente digitaste git add * e preparaste os dois. Como podes obter um deles fora da área de preparação? O comando git status lembra-te como:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

Logo abaixo do texto “Changes to be committed”, podes ver que diz que usas git reset HEAD <file>... para desfazer a preparação. Portanto, vamos usar os conselhos para desfazer a preparação do arquivo CONTRIBUTING.md:

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M	CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

O comando é um pouco estranho, mas funciona. O arquivo CONTRIBUTING.md é modificado e, novamente, não está pronto.

Embora o git reset seja um comando perigoso se tu o chamares com --hard. No entanto, no cenário descrito acima, o arquivo no teu diretório de trabalho não é tocado, por isso é relativamente seguro.

Por enquanto, a única coisa que precisas de saber sobre o comando git reset é esta invocação mágica. Entraremos em mais detalhes sobre o que é reiniciar e como dominá-lo para que ele faça coisas realmente interessantes em <ch07-git-tools#_git_reset>>..

Desfazer um arquivo modificado

E se tu perceberes que não desejas manter as tuas alterações no arquivo CONTRIBUTING.md? Como podes facilmente restaura-lo — reverte-o de volta ao que ele parecia quando quando o tu o confirmaste pela última vez (ou inicialmente clonado, ou no entanto entraste no teu diretório de trabalho)? Por sorte, git status diz-te como fazer isto também. No último exemplo de saída, a área não identificada parece com isto:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Ele diz muito explicitamente como descartar as mudanças que tu fizeste. Vamos fazer o que ele diz:

$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Agora podes verificar que as mudanças foram revertidas.

É importante entender que git checkout -- <file> é um comando perigoso. Todas as mudanças que izeste neste arquivo desapareceram — o Git apenas copiou outro arquivo sobre ele. Nunca uses este comando a menos que saibas absolutamente que não desejas o arquivo.

Se tu quiseres manter as mudanças que fizeste neste arquivo, mas ainda precisas sair do caminho por agora, iremos falar de como ocultar e ramificar em Ramificação do Git; estas são, geralmente as melhores maneiras de ir.

Lembra-te, qualquer coisa que seja committed no Git quase sempre pode ser recuperada. Mesmo os compromissos que estavam em ramos que foram excluídos ou os compromissos que foram substituídos por um compromisso --amend podem ser recuperados (consulta Data Recovery para recuperação de dados). No entanto, qualquer coisa que tu perderes que nunca foi cometido provavelmente nunca mais será vista novamente.