Close

Saiba como desfazer alterações no Git usando o Bitbucket Cloud

Objetivo

Saiba como desfazer alterações na máquina local e em um repositório do Bitbucket Cloud enquanto colabora com outros.

Missão breve

Comandos abordados neste tutorial:

  • git revert, git reset, git log e git status

Tempo

40 minutos

Público-alvo:

Este tutorial pressupõe familiaridade com os comandos git:git clone, git commit, git pull e git push

Todos cometem erros. Nem todo push é perfeito, então este tutorial vai ajudar a usar as funções git mais comuns para desfazer uma alteração ou alterações com segurança.

Este tutorial requer conhecimento destes comandos git:

Se você não conhece esses comandos, conte com a gente para aprender o Git com o Bitbucket Cloud. Depois, volte aqui e saiba como desfazer as mudanças. Esses comandos git podem ser usados em ambientes Windows ou Unix. Este tutorial vai usar as utilidades da linha de comando do Unix ao explicar a navegação pelo sistema de arquivos.


Como desfazer mudanças na máquina local


Quando a alteração que você quer desfazer estiver no sistema local e não foi enviada por push a um repositório remoto, há duas formas básicas de desfazer a alteração:

Comando

Definição

git revert

Definição

Um comando "desfazer", embora não seja uma operação tradicional de desfazer. Em vez de remover o commit, ele descobre como desfazer as alterações no commit e acrescenta um novo commit com o conteúdo inverso. Isso evita que o Git perca o histórico, o que é importante para a integridade do histórico de revisão e para uma colaboração confiável.

git reset

Definição

Um comando git versátil para desfazer alterações. O comando git reset tem um conjunto poderoso de opções, mas vamos usar apenas os seguintes modos de redefinição para este tutorial:

  • --soft: redefine apenas o HEAD do commit que você selecionar. Funciona quase da mesma forma que o git checkout, mas não cria um estado de HEAD desvinculado.
  • --mixed: Redefine o HEAD do commit que você seleciona no histórico e desfaz as alterações no índice.
  • --hard: Redefine o HEAD do commit que você seleciona no histórico, desfaz as alterações no índice e desfaz as alterações em seu diretório de trabalho. Neste tutorial a gente não vai testar uma redefinição definitiva.

Para uma descrição completa de como o git reset funciona, consulte git-scm.com Ferramentas do Git - A redefinição desmistificada.

Logotipo do Bitbucket
VER SOLUÇÃO

Tutoriais avançados do Git

Logotipo do Git
Material relacionado

Comandos do Git

À medida que você avançar no tutorial, vai ver diversos outros comandos git como parte do aprendizado de como desfazer alterações. Então, ao trabalho.

Bifurque um repositório


Vamos começar criando um repositório exclusivo com todo o código do original. Este processo é chamado "bifurcação de repositório". Bifurcar é um processo git estendido que é ativado quando um repositório compartilhado é hospedado com um serviço de hospedagem de terceiros como o Bitbucket.

1. Clique ou insira o seguinte URL: https://bitbucket.org/atlassian/tutorial-documentation-tests/commits/all

2. Clique no símbolo + na barra lateral esquerda e selecione Bifurcar este repositório, analise a caixa de diálogo e clique em Bifurcar repositório.

3. Você deve ser levado para a visão geral do novo repositório.

4. Clique no símbolo + e selecione Clonar este repositório.

5. No seu computador, clone o repositório.

6. Navegue para o diretório que contém o repositório clonado.

Agora que você tem um repositório cheio de códigos e um histórico no sistema local, já pode desfazer algumas alterações.

Encontre alterações no sistema local


Você vai ter que encontrar e referenciar a alteração que quer desfazer. Isso pode ser feito navegando na interface de usuário do commit no Bitbucket e há alguns utilitários de linha de comando que podem localizar uma alteração específica.

git status


Você vai ter que encontrar e referenciar a alteração que quer desfazer. Isso pode ser feito navegando na interface de usuário do commit no Bitbucket e há alguns utilitários de linha de comando que podem localizar uma alteração específica.

$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
nothing to commit, working tree clean

O resultado do git status mostra que tudo está atualizado com a ramificação principal remota e não há alterações pendentes aguardando commit. No próximo exemplo, a gente vai fazer umas edições no repositório e o examinar em um estado de alterações pendentes. Ou seja, você tem alterações em arquivos no repositório do sistema local que não foram preparadas para serem adicionadas ao histórico do projeto.

Para demonstrar este próximo exemplo, primeiro abra o arquivo myquote2.html. Faça algumas modificações no conteúdo de myquote2.html, salve e saia do arquivo. Vamos executar o git status mais uma vez para examinar o repositório neste estado.

$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
 
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: myquote2.html
 
no changes added to commit (use "git add" and/or "git commit -a")
--

O resultado mostra que o repositório tem modificações pendentes em myquote2.html. Ótimo! Se a modificação que você quer desfazer, como no exemplo acima, não tiver sido adicionada à área de staging ainda, você pode apenas editar o arquivo e seguir adiante. O Git só começa a rastrear uma alteração quando você a adiciona à área de staging e a confirma no histórico do projeto.

Vamos "desfazer" as alterações em myquote2.html. Como este é um exemplo simplificado com alterações mínimas, há dois métodos disponíveis para desfazer. Se a gente executar git checkout myquote2.html, o repositório vai restaurar myquote2.html para a versão já confirmada. Uma alternativa é executar git reset --hard, que vai reverter todo o repositório para o último commit.

git log


O comando git log permite que você liste, filtre e busque no histórico do projeto por alterações específicas. Enquanto o git status permite que você inspecione o diretório de trabalho e a área de staging, o git log só exibe o histórico confirmado.

O mesmo log do histórico confirmado pode ser encontrado na interface de usuário do Bitbucket acessando a exibição de "commits" de um repositório. A exibição de commits do repositório de demonstração se encontra em: https://bitbucket.org/dans9190/tutorial-documentation-tests/commits/all. Essa exibição vai ter um resultado parecido com o utilitário de linha de comando git log. Ela pode ser usada para encontrar e identificar um commit a ser desfeito.

No exemplo a seguir, você pode ver várias coisas no histórico, mas cada modificação é, na verdade, um commit, então é isso o que a gente precisa encontrar e desfazer.

$ git status
On branch main
Your branch is up-to-date with 'origin/main'.

nothing to commit, working tree clean

$ git log

commit 1f08a70e28d84d5034a8076db9103f22ec2e982c
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Wed Feb 7 17:06:50 2018 +0000

    Initial Bitbucket Pipelines configuration

commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Fri Sep 30 15:50:58 2016 -0700

    repeated quote to show how a change moves through the process

commit 4801b87c2147dce83f1bf31acfcffa6cb1d7e0a5
Merge: 1a6a403 3b29606
Author: Dan Stevens [Atlassian] <dstevens@atlassian.com>
Date:   Fri Jul 29 18:45:34 2016 +0000

    Merged in changes (pull request #6)

    Changes

Vamos ver um pouco mais de perto um dos commits na lista.

commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Fri Sep 30 15:50:58 2016 -0700
 
    repeated quote to show how a change moves through the process

O que você pode ver é que cada mensagem de commit tem quatro elementos:

Elemento

Descrição

Hash de commit

Descrição

Uma sequência alfanumérica (codificada em SHA-1) que identifica essa alteração específica

Autor

Descrição

A pessoa que confirmou a mudança

Data

Descrição

A data em que a alteração foi confirmada no projeto

Mensagem de commit

Descrição

Uma sequência de texto que descreve as alterações.

Dica de prática recomendada: escreva mensagens de commit descritivas e curtas para ajudar a criar um repositório de trabalho mais harmonioso para todos.

Localize um commit específico


O mais provável é que a alteração que você quer desfazer vai estar em algum lugar mais para o fim do histórico do projeto, o que pode ser um tanto cansativo. Então, vamos aprender algumas operações básicas usando git log para encontrar uma alteração específica.

1. Vá até a janela de terminal e navegue pela parte superior do repositório local usando o comando cd (mudar de diretório).

$ cd ~/repos/tutorial-documentation-tests/

Digite o comando git log --oneline. Adicionar --oneline vai exibir cada commit em uma linha só que permite visualizar mais históricos no terminal.

Pressione a tecla q para sair do log de commits e voltar ao prompt de comando quando quiser.

Você deve ver algo como o exemplo a seguir:

$ git log --oneline
1f08a70 (HEAD -> main, origin/main, origin/HEAD) Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
...

2. Pressione a tecla q para voltar ao seu prompt de comando.

3. Localize o commit com o hash c5826da e mais alterações na lista que o comando git log produziu. Alguém não escreveu uma mensagem de commit descritiva, então a gente vai ter que descobrir se as alterações necessárias estão aqui.

4. Destaque e copie o hash de commit c5826da do resultado do git log na janela de terminal.

5. Digite git show e cole ou transcreva o hash de commit que você copiou e pressione Enter. Você deve ver algo assim:

$git show c5826daeb6ee3fd89e63ce35fc9f3594fe243605
commit c5826daeb6ee3fd89e63ce35fc9f3594fe243605
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Tue Sep 8 13:50:23 2015 -0700

    more changes

diff --git a/README.md b/README.md
index bdaee88..6bb2629 100644
--- a/README.md
+++ b/README.md
@@ -11,12 +11,7 @@ This README would normally document whatever steps are necessary to get your app
 ### How do I get set up? ###

 * Summary of set up
-* Configuration
-* Dependencies
-* Database configuration
-* How to run tests
-* Deployment instructions
-* more stuff and things
:

O prompt na parte inferior vai continuar sendo preenchido até que mostre toda a alteração. Pressione q para sair do prompt de comando.

Filtre o git log para encontrar um commit específico


Este filtro

Faz isso

Este comando de exemplo

Pode resultar em

-

Faz isso

Limita o número de confirmações mostradas

Este comando de exemplo

git log -10

Pode resultar em

Os 10 commits mais recentes no histórico

--after

--before

Faz isso

Limita as confirmações mostradas ao período correlacionado

Você também pode usar
--after "yyyy-mm-dd" --before "yyyy-mm-dd"

Este comando de exemplo

git log --after 2017-07-04

Pode resultar em

Todos os commits após 4 de julho de 2017

--author="name"

Faz isso

Lista todos os commits que correspondem com o nome do autor

Este comando de exemplo

git log --author="Alana"

Pode resultar em

Todos os commits feitos por qualquer autor com Alana no campo de nome

--grep="message string"

Faz isso

Retorna qualquer commit com uma mensagem que corresponda à sequência digitada

Este comando de exemplo

git log --grep="HOT-"

Pode resultar em

Todos os commits que têm HOT- como sequência de texto nas mensagens

Aqui você viu um resumo de como funciona o comando git log. Caso você goste de trabalhar com esse comando, confira o tutorial do git log avançado.

Desfaça uma alteração com git reset


Para começar, vamos apenas desfazer o commit mais recente no histórico. Neste caso, digamos que você acabou de ativar os pipelines da solução de integração e implementação contínuas do Bitbucket, mas percebeu que o script não está bem certo.

1. Digite git log --oneline na janela de terminal.

2. Copie o hash de commit do segundo commit no diretório log: 52f823c e depois pressione q para sair do Registro.

3. Digite git reset --soft 52f823c na janela de terminal. O comando deve ser executado em plano de fundo se for bem-sucedido. Pronto! Você desfez a primeira alteração. Agora, veja o resultado desta ação.

4. Digite git status na janela de terminal e você vai ver que o commit foi desfeito e agora é uma alteração não confirmada. Você deve ver algo assim:

$ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)
 
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
 
    new file:   bitbucket-pipelines.yml

5. Digite git log --oneline na janela de terminal. Você deve ver algo assim:

$ git log --oneline
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes

6. Você pode ver que o novo HEAD da ramificação é o commit 52f823c, o que é bem o objetivo.

7. Pressione q para sair do Registro. Deixe o terminal aberto, porque, agora que você aprendeu a fazer uma redefinição simples, a gente vai tentar algo um pouco mais complexo.

Desfaça várias alterações com git reset


Para começar, vamos apenas desfazer o commit mais recente no histórico. Neste caso, digamos que você acabou de ativar os pipelines da solução de integração e implementação contínuas do Bitbucket, mas percebeu que o script não está bem certo.

1. Digite git log --online

2. Copie o hash de commit 1a6a403 (myquote editado on-line com o Bitbucket) que é o commit logo abaixo da pull request nº 6 com as alterações que a gente quer desfazer.

3. Digite git reset 1a6a403 na janela de terminal. O resultado deve ser algo assim:

$ git reset 1a6a403
Unstaged changes after reset:
M README.md
M myquote2.html

Você pode ver que as alterações estão em um estado não confirmado. Isso significa que a gente removeu várias alterações, tanto do histórico do projeto como da área de staging.

4. Digite git status na janela de terminal. O resultado deve ser algo assim:

$ git status
On branch main
Your branch is behind 'origin/main' by 6 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
 
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:   README.md
    modified:   myquote2.html
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
    bitbucket-pipelines.yml
 
no changes added to commit (use "git add" and/or "git commit -a")

Agora, você pode ver que a primeira alteração que a gente desfez (o arquivo bitbucket-pipelines.yml) não tem nenhum rastreamento pelo git. Isso acontece porque invocando git reset remove a alteração do cabeçalho da ramificação e do rastreamento da área de índice de git. O processo interno é um pouco mais complexo do que o conteúdo que a gente pode explicar aqui. Leia mais em git reset.

5. Digite git log --oneline na janela de terminal.

1a6a403 myquote edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
879f965 adding to the quote file
8994332 Merged in HOT-235 (pull request #2)
b4a0b43 removed sarcastic remarks because they violate policy.
b5f5199 myquote2.html created online with Bitbucket
b851618 adding my first file
5b43509 writing and using tests

Agora, o resultado do log exibe que o histórico de commits também foi modificado e começa na confirmação 1a6a403. Para fins de demonstração e mais exemplos, a gente quer desfazer a redefinição que acabou de fazer. Depois de mais considerações, talvez a gente queira manter o conteúdo da pull request nº 6.

Como fazer push de redefinições no Bitbucket


Git resets são um dos poucos métodos de "desfazer" que o Git oferece. Redefinições são, no geral, consideradas uma opção "insegura" para desfazer alterações. Elas são boas para trabalhar no local em códigos isolados, mas são arriscadas quando compartilhadas com membros da equipe.

Para compartilhar uma ramificação redefinida com uma equipe remota, um "push forçado" deve ser executado. Um "push forçado" é iniciado executando git push -f. Um envio por push forçado destrói qualquer histórico na ramificação que foi criada após o ponto do push.

A seguir, um exemplo desse cenário "inseguro":

  • O desenvolvedor A está trabalhando em uma ramificação no desenvolvimento de uma nova função.
  • O desenvolvedor B trabalha na mesma ramificação desenvolvendo uma função separada.
  • O desenvolvedor B decide redefinir a ramificação para um estado anterior ao início do trabalho dos desenvolvedores A e B.
  • O desenvolvedor B, então, envia a ramificação de redefinição forçada para o repositório remoto.
  • O desenvolvedor A faz o pull da ramificação para receber atualizações. Durante esse pull, o desenvolvedor A recebe a atualização forçada. Isso redefine a ramificação local do desenvolvedor A para um momento anterior a qualquer trabalho de função e perde os commits.

Desfaça um git reset


Até agora, a gente passou os hashes SHA do git commit para o git reset. O resultado de git log não tem os commits redefinidos. Como ter esses commits de volta? O Git nunca exclui os commits por completo, a menos que tenha removido algum ponteiro deles. Além disso, o git armazena um log separado de todos os movimentos de referência chamado "reflog". A gente pode examinar o reflog executando git reflog.

1a6a403 HEAD@{0}: reset: moving to 1a6a403
1f08a70 HEAD@{1}: reset: moving to origin/main
1f08a70 HEAD@{2}: clone: from git@bitbucket.org:dans9190/tutorial-documentation-tests.git

O resultado de git reflog deve ser parecido com o que aparece acima. Você pode ver um histórico de ações no repositório. A linha superior é uma referência à redefinição que a gente fez para redefinir a solicitação pull nº 6. Vamos redefinir para restaurar a solicitação pull nº 6. A segunda coluna desse resultado de reflog indica um ponteiro de referência para uma ação de modificação feita no repositório. Aqui, HEAD@{0} é uma referência ao comando de redefinição que a gente já executou. É melhor não repetir esse comando de redefinição, então a gente vai restaurar o repositório para HEAD@{1}.

$ git reset --hard HEAD@{1}
HEAD is now at 1f08a70 Initial Bitbucket Pipelines configuration

Vamos examinar o histórico de commits do repositório com git log --oneline:

$git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:

Agora, o resultado do log exibe que o histórico de commits também foi modificado e começa na confirmação 1a6a403. Para fins de demonstração e mais exemplos, a gente quer desfazer a redefinição que acabou de fazer. Depois de mais considerações, talvez a gente queira manter o conteúdo da pull request nº 6.

git revert


O conjunto de exemplos anterior fez uma viagem e tanto no tempo, desfazendo operações usando git reset e git reflog. O Git contém outro utilitário de "desfazer" que é considerado, com frequência, "mais seguro" do que redefinir. A reversão cria commits novos que contêm uma inversão das alterações dos commits especificados. Esses commits de reversão podem, assim, ser enviados por push com segurança a repositórios remotos para serem compartilhados com outros desenvolvedores.

Na seção a seguir, você vai ver o uso de git revert. A gente vai continuar com o exemplo da seção anterior. Para começar, a gente vai examinar o log e encontrar um commit para reverter.

$ git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:

Para este exemplo, vamos usar o commit 1f08a70 mais recente como o commit em que a gente vai operar. Para este contexto, digamos que a gente quer desfazer as edições feitas nesse commit. Execute:

$ git revert 1f08a70

Isso vai dar a partida no fluxo de trabalho git merge. O Git vai criar um commit novo com conteúdo que é uma reversão do commit especificado para a reversão. O Git, assim, vai abrir um editor de texto configurado para preparar para uma nova mensagem de commit. As reversões são consideradas a opção mais segura de desfazer devido a esse fluxo de trabalho de commit. A criação de commits de reversão deixam um rastro visível no histórico de commits de quando uma operação de desfazer foi executada.

Você aprendeu a desfazer alterações!


Parabéns! Você terminou. Volte para este tutorial quando quiser ou veja a seção Como fazer alterações para se aprofundar mais. Continue fazendo um bom trabalho no Bitbucket!


Compartilhar este artigo

Leitura recomendada

Marque esses recursos para aprender sobre os tipos de equipes de DevOps ou para obter atualizações contínuas sobre DevOps na Atlassian.

Pessoas colaborando usando uma parede cheia de ferramentas

Blog do Bitbucket

Ilustração do DevOps

Caminho de aprendizagem de DevOps

Demonstrações de funções no Demo Den com parceiros da Atlassian

Como o Bitbucket Cloud funciona com o Atlassian Open DevOps

Inscreva-se para receber a newsletter de DevOps

Thank you for signing up