Git
Chapters ▾ 2nd Edition

2.4 Fundamentos de Git - Desfazendo coisas

Desfazendo coisas

Em qualquer estágio, você talvez queira desfazer algo. Aqui, vamos rever algumas ferramentas básicas para desfazer modificações que porventura tenha feito. Seja cuidadoso, porque nem sempre você pode voltar uma alteração desfeita. Essa é uma das poucas áreas do Git onde pode perder algum trabalho feito se você cometer algum engano.

Um dos motivos mais comuns para desfazer um comando, aparece quando você executa um commit muito cedo e possivelmente esquecendo de adicionar alguns arquivos ou você escreveu a mensagem do commit de forma equivocada. Se você quiser refazer este commit, execute o commit novamente usando a opção --amend:

$ git commit --amend

Esse comando pega a área stage e a usa para realizar o commit. Se você não fez nenhuma alteração desde o último commit (por exemplo, se você executar o comando imediatamente depois do commit anterior), então sua imagem dos arquivos irá ser exatamente a mesma, e tudo o que você alterará será a mensagem do commit.

O mesmo editor de mensagens de commit é acionado, porém o commit anterior já possui uma mensagem. Você pode editar a mensagem como sempre, porém esta sobrescreve a mensagem do commit anterior.

Por exemplo, se você fizer um commit e então lembrar que esqueceu de colocar no stage as modificações de um arquivo que você quer adicionar no commit, você pode fazer algo semelhante a isto:

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

No final das contas você termina com um único commit – O segundo commit substitui o resultante do primeiro.

Retirando um arquivo do Stage

A próxima sessão demonstra como trabalhar com modificações na área stage e work directory. A boa notícia é que o comando que você usa para verificar o estado dessas duas áreas, também te relembra como desfazer as modificações aplicadas. Por exemplo, vamos supor que você alterou dois arquivos, e deseja realizar o commit deles separadamente, porém você acidentalmente digitou git add * adicionando ambos ao stage. Como você pode retirar um deles do stage? O comando git status lhe lembrará de como fazer isso:

$ 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”, diz git reset HEAD <file>... para retirar o arquivo do stage. Então, vamos usar esta sugestão para retirar o arquivo CONTRIBUTING.md do stage:

$ 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 tanto quanto estranho, mas funciona. O arquivo CONTRIBUTING.md volta ao estado modificado porem está novamente fora do stage.

Note

É verdade que o comando git reset pode ser perigoso, especialmente se você usar a opção --hard. Entretanto, no cenário descrito acima, o arquivo no working directory está inalterado, então é relativamente seguro utilizar o comando.

Essa mágica usando o git reset é tudo que você precisa saber por enquanto sobre este comando. Nós vamos entra mais no detalhe sobre o que o comando reset faz e como usá-lo de forma a fazer coisas realmente interessantes em Reset Demystified.

Desfazendo as Modificações de um Arquivo

E se você se der conta de que na verdade não quer manter as modificações do arquivo CONTRIBUTING.md? Como você pode reverter as modificações, voltando a ser como era quando foi realizado o último commit (ou clone inicial, ou seja como for que você chegou ao seu working directory)? Felizmente, git status diz a você como fazer isso também. Neste último exemplo, a área fora do stage parece com isso:

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

Isso lhe diz de forma explicita como descartar as modificações que você fez. Vamos fazer o que o comando nos sugeriu:

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

    renamed:    README.md -> README

Você pode notar que as modificações foram revertidas.

Important

É importante entender que o git checkout -- <file> é um a comando perigoso. Qualquer modificação que você fez no arquivo se foi — O Git apenas substitui o arquivo pela última versão (mais recente) que sofreu commit. Nunca use este comando a não ser que você saiba com certeza que não quer salvar as modificações do arquivo.

Se você gostaria de manter as modificações que fez no arquivo, porem precisa tirá-lo do caminho por enquanto, sugerimos que pule para a documentação sobre Branches[ch03-git-branching]; esta geralmente é a melhor forma de fazer isso.

Lembre-se, qualquer coisa que sobre commit com Git pode quase sempre ser recuperada. Até mesmo commits que estava em algum branches que foram deletados ou commits que forma sobre escritos através de um --amend podem ser recuperados (vejaData Recovery para recuperação de dados). Contudo, qualquer coisa que você perder que nunca sofreu commit pode ser considerada praticamente perdida.