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 |
---|---|
| 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. |
| Definição
Um comando
Para uma descrição completa de como o |
VER SOLUÇÃO
Tutoriais avançados 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 de 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 registro 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 | Pode resultar em Os 10 commits mais recentes no histórico |
| Faz isso Limita as confirmações mostradas ao período correlacionadoVocê também pode usar | Este comando de exemplo | Pode resultar em Todos os commits após 4 de julho de 2017 |
| Faz isso Lista todos os commits que correspondem com o nome do autor | Este comando de exemplo | Pode resultar em Todos os commits feitos por qualquer autor com Alana no campo de nome |
| Faz isso Retorna qualquer commit com uma mensagem que corresponda à sequência digitada | Este comando de exemplo | 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 registro separado de todos os movimentos de referência, chamado "registro de referências". A gente pode examinar o registro de referências 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
Próximo tópico
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.