15. Removendo um commit de um branch

Metas

  • Aprender a deletar os commits mais recentes de um branch.

Revert é um comando poderoso da seção anterior que te permite cancelar quaisquer commits para um repositório. Apesar disso, tanto os commits originais quanto os cancelados permanecem visíveis no histórico do branch (quando usamos o comando git log).

Frequentemente depois que um commit é feito percebemos que ele era um erro. Seria legal ter um comando de desfazer que permitisse deletar o commit incorreto imediatamente. Esse comando preveniria a aparição de um commit indesejado no histórico do git log.

01 O comando reset

Já vimos o comando reset e o usamos para definir a área de preparação para ser consistente com um determinado commit (usamos o commit HEAD em nossa lição anterior).

Quando você executa o comando reset junto com uma referência de commit (ou seja, um branch, hash ou nome de tag), o comando...

  1. Aponta o ramo atual para o commit especificado.
  2. Opcionalmente, redefinirá a área de preparação para que ela esteja em conformidade com o commit especificado.
  3. Opcionalmente, redefina o diretório de trabalho para que ele corresponda ao commit especificado.

02 Cheque nosso histórico

Vamos fazer um rápido scan do nosso histórico de commits.

Execute

git log

Resultado

$ git log
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]

Nós vemos que os dois últimos commits desse branch são "Oops" and "Revert Oops". Vamos removê-los com o comando reset.

03 Marque esse branch primeiro

Vamos marcar nosso último commit com tag, para que possamos achá-lo após remover commits.

Execute

git tag oops

Resultado

$ git log
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main, tag: oops) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]

04 Resete o commit para o oops anterior

No log de histórico (veja acima), o commit com tag v1 está fazendo commit sobre um commit anterior incorreto. Vamos resetar o branch para aquele ponto. Como o branch tem uma tag, podemos usar o nome da tag no comando reset (se não possuir uma tag, podemos usar o valor hash).

Execute

git reset --hard v1
git log

Resultado

$ git reset --hard v1
HEAD is now at b7614c1 Added HTML header
$ git log
b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]

Nosso branch main está apontando para o commit v1 e "Revert Oops", e commits "Oops" não mais existem no branch. O parâmetro --hard aponta que o diretório de trabalho deve ser atualizado para refletir o novo head do branch.

05 Nada é perdido para sempre

O que acontece com os commits errados? Eles ainda estão no repositório. Na verdade, ainda podemos nos referir a eles. No início da lição, criamos a tag oops para o commit cancelado. Vamos dar uma olhada em all (todos) commits.

Execute

git log --all

Resultado

$ git log --all
b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets]
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (tag: oops) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]

Podemos ver que os commits errados não foram embora. Eles não estão listados mais no branch main mas ainda permanecem no repositório. Eles ainda estariam no repositório caso não tivéssemos colocado uma tag neles, mas só poderíamos referenciá-los por seus nomes hash. Commits não referenciados continuam no repositório até que um software coletor de lixo é acionado pelo sistema.

06 Perigos de resetar

Resets em branches locais geralmente são inofensivos. As consequências de quaisquer "acidentes" podem ser revertidos usando um commit apropriado.

Apesar disso, outros usuários que compartilham o branch podem ficar confusos se o branch compartilhado fica armazenado em repositórios remotos.