Shopping cart

Subtotal $0.00

View cartCheckout

Building better devs

TnewsTnews
Programação

git history: O Novo Comando do Git que Aposentou o rebase -i

Email : 10

Quem nunca quis voltar no tempo e corrigir aquele commit errado?

Você sabe a sensação. Acabou de dar push, olhou o diff e percebeu: a mensagem do commit está errada, tem um console.log esquecido no meio, ou pior, duas mudanças completamente diferentes entraram no mesmo commit. A solução clássica? git rebase -i. E aí começa o circo: editor abrindo, pick virando edit, conflitos aparecendo do nada, branches quebrando. Todo mundo que já usou rebase interativo sabe que funciona, mas é como fazer cirurgia com um canivete suíço.

O Git finalmente resolveu atacar esse problema de frente. Nas versões 2.54 (abril de 2026) e 2.55 (junho de 2026), chegou o git history: um comando experimental que faz reescrita de historico de forma cirurgica, sem tocar no seu working tree e sem aquele ritual do rebase interativo. Se voce ja ouviu falar do Jujutsu (jj) e ficou com inveja de quem usa, essa e a resposta do Git.

O que e o git history (e por que voce deveria ligar)

O git history e um comando experimental que oferece tres operacoes especificas para reescrever historico: reword, split e fixup. Cada uma resolve um problema que antes exigia malabarismo com git rebase -i.

A grande sacada: o comando foi construido sobre o motor do git replay, o que significa que ele opera sem modificar o working tree nem o index. Traduzindo: voce pode reescrever um commit antigo sem perder o que esta fazendo agora. Nada de stash, nada de “salva ai que eu preciso fazer um rebase”.

Ah, e tem mais: ele atualiza automaticamente todas as branches locais que descendem do commit modificado. Se voce trabalha com stacked branches (aquele workflow onde uma feature branch depende de outra), isso muda tudo.

git history reword: corrija mensagens sem drama

Quantas vezes voce escreveu “fix typo” e queria ter escrito algo mais descritivo? Ou pior, commitou com a mensagem errada e so percebeu tres commits depois?

Antes, o caminho era:


git rebase -i HEAD~5
# achar o commit, trocar pick por reword
# editor abre, voce edita
# rezar pra nao dar conflito

Agora:


git history reword abc1234

Pronto. O editor abre com a mensagem do commit abc1234, voce edita, salva, e o Git reconstroi toda a pilha de commits acima dele. As branches que descendem daquele commit sao atualizadas automaticamente.

O detalhe que faz diferenca: o reword nao toca no working tree. Voce pode estar no meio de uma implementacao, com arquivos modificados, e rodar o comando sem medo. Ele opera puramente no grafo de commits.

Funciona ate em repositorios bare, o que abre possibilidades interessantes pra automacao em servidores.

git history split: separando commits que nunca deveriam ter ficado juntos

Esse e o cenario classico: voce esta codando, entra no flow, e quando vai commitar percebe que fez tres coisas diferentes no mesmo commit. Refatorou uma funcao, corrigiu um bug E adicionou um teste novo. Tudo no mesmo git commit -m "misc fixes".

Separar isso depois era um pesadelo. Envolvia git rebase -i, trocar pra edit, fazer git reset HEAD~1, git add -p pra selecionar pedacos, commitar de novo, e dar git rebase --continue. Se desse conflito no meio, boa sorte.

Agora:


git history split abc1234

O comando abre uma interface interativa (estilo git add -p) mostrando os hunks daquele commit:


diff --git a/src/app.js b/src/app.js
(1/3) Stage addition [y,n,q,a,d,p,?]? y

Voce escolhe quais mudancas vao pro primeiro commit. O resto vira automaticamente o segundo commit. A pilha inteira e reconstruida por cima, branches atualizadas, sem conflitos (o comando se recusa a operar se detectar que vai dar problema).

Metodo antigo Com git history split
git rebase -i + edit + reset + add -p + commit + continue git history split
6 passos manuais 1 comando
Modifica working tree Working tree intacto
Pode gerar conflitos no meio Atomico: recusa se tiver conflito

git history fixup: o autosquash que voce sempre quis

Esse chegou no Git 2.55 e talvez seja o mais util dos tres. O cenario: voce encontrou um bug num commit antigo. Precisa corrigir aquele commit especifico, nao criar um commit novo de “fix”.

O workflow antigo:


git add arquivo-corrigido.js
git commit --fixup=abc1234
git rebase -i --autosquash abc1234^

Tres comandos, um rebase interativo no meio, e a possibilidade real de conflitos. Patrick Steinhardt, o autor da implementacao, descreveu esse processo como “desajeitado, especialmente porque exige um rebase interativo”.

O novo jeito:


git add arquivo-corrigido.js
git history fixup abc1234

Dois passos. O Git pega as mudancas staged, aplica no commit alvo, e reconstroi tudo por cima. Todas as branches locais que contem aquele commit sao atualizadas.

A flag --only-on-current-branch limita o escopo caso voce nao queira atualizar todas as branches descendentes. E a flag --reedit-message abre o editor pra voce ajustar a mensagem do commit junto com o fixup.

Por dentro do motor: como o git history funciona

O git history foi construido sobre o git replay, uma ferramenta interna do Git que sabe reconstruir sequencias de commits sem tocar no working tree. Isso e fundamental porque significa que:

  1. Nenhum arquivo e modificado no disco durante a operacao
  2. O index permanece intacto, entao voce nao perde mudancas staged
  3. A operacao e atomica: ou tudo da certo, ou nada muda

Essa atomicidade e a diferenca mais importante em relacao ao rebase -i. Quem ja ficou preso num rebase --continue / rebase --abort sabe a dor de um rebase que deu errado no meio. Com o git history, isso nao existe. Se a operacao detectar que vai gerar um conflito, ela simplesmente se recusa a executar.

O fluxo interno e mais ou menos assim:


1. Le o commit alvo e seus descendentes
2. Calcula a nova versao do commit (com reword/fixup/split)
3. Tenta replay de todos os descendentes sobre o novo commit
4. Se qualquer replay gerar conflito -> aborta tudo, nada muda
5. Se tudo der certo -> atualiza refs de todas as branches afetadas

git history vs jj (Jujutsu): precisamos mesmo trocar?

O Jujutsu vem ganhando tracao entre power users do Git que querem um workflow mais moderno. Ele trata conflitos como cidadaos de primeira classe, modela o working copy como um commit, tem um operation log com undo, e faz rebase automatico quando voce reescreve historico.

O git history importa algumas dessas ideias, mas nao todas:

Feature git history jj (Jujutsu)
Rebase automatico de descendentes Sim Sim
Atualizacao de branches Sim (locais) Sim (todas)
Conflitos first-class Nao Sim
Operation log / undo Nao Sim
Working copy como commit Nao Sim
Requer ferramenta externa Nao (nativo) Sim
Merge commits Nao suporta Suporta

A documentacao do Git deixa uma porta aberta: “essa limitacao pode ser removida quando (se) o Git aprender sobre conflitos de primeira classe”. Entao o futuro pode trazer mais convergencia.

Mas aqui vai minha opiniao: pra 90% dos devs, o git history ja resolve. A maioria nao precisa de operation log nem de conflitos first-class. Precisa de um jeito rapido de corrigir um commit antigo sem quebrar tudo. E isso o git history entrega.

Se voce ja usa jj e esta feliz, nao tem motivo pra voltar. Mas se a barreira de entrada do jj (instalar, aprender, convencer o time) era o que te segurava, agora voce tem 80% dos beneficios sem sair do Git.

Como comecar a usar hoje

Primeiro, verifique sua versao:


git --version

Voce precisa do Git 2.54+ para reword e split, ou Git 2.55+ para fixup. No Ubuntu/Debian:


sudo add-apt-repository ppa:git-core/ppa
sudo apt update && sudo apt install git

No macOS com Homebrew:


brew upgrade git

Como o comando e experimental, ele nao aparece no git help padrao. Voce pode conferir a documentacao oficial em git help history ou na pagina do man:


git history --help

Workflow pratico: stacked branches com git history

Vamos a um cenario real. Voce esta desenvolvendo uma feature que depende de outra que ainda esta em review:


main
  └── feature/auth (em review)
        └── feature/dashboard (voce esta aqui)

Voce descobre um bug no branch feature/auth. Antes, voce teria que:

  1. Fazer checkout pra feature/auth
  2. Corrigir e commitar
  3. Voltar pra feature/dashboard
  4. Fazer rebase de feature/dashboard sobre feature/auth
  5. Resolver conflitos (se houver)

Com git history:


# Continue no feature/dashboard, sem trocar de branch
git add arquivo-corrigido.js
git history fixup <commit-do-auth>

O Git corrige o commit no feature/auth e automaticamente reconstroi o feature/dashboard por cima. Sem checkout, sem rebase manual, sem conflitos surpresa.

Limitacoes que voce precisa conhecer

O git history nao e bala de prata. Aqui vai o que ele nao faz (ainda):

Merge commits: se o historico entre o commit alvo e o HEAD contem um merge commit, o git history se recusa a operar. Isso e uma limitacao do git replay por baixo. Se voce usa merge commits no seu workflow (em vez de rebase), vai continuar precisando do rebase -i.

Conflitos: diferente do jj, o Git nao sabe “carregar” conflitos adiante. Se a reescrita gerar conflito em qualquer descendente, a operacao inteira e abortada. Isso e seguro (nada quebra), mas pode ser frustrante se voce sabe que o conflito e trivial.

Branches remotas: o comando so atualiza branches locais. Se voce ja deu push de uma branch que foi afetada, vai precisar de um git push --force-with-lease depois.

Experimental: a interface pode mudar. O Git nao garante estabilidade da API ate sair do status experimental. Use em projetos pessoais primeiro.

Tabela de referencia rapida

Tarefa Comando antigo Com git history
Corrigir mensagem de commit antigo git rebase -i + reword git history reword
Separar commit em dois git rebase -i + edit + reset + add -p git history split
Aplicar fix em commit antigo git commit --fixup + git rebase -i --autosquash git add + git history fixup
Corrigir commit em outra branch (stacked) checkout + fix + rebase manual git history fixup (sem trocar de branch)

Dicas pra quem vai adotar no time

Se voce quer introduzir o git history no workflow do seu time, aqui vao algumas dicas praticas:

Comece pelo reword. E o subcomando mais seguro e que todo mundo entende. Mensagem de commit errada? git history reword. Ninguem vai reclamar.

Use fixup pra code review. Quando o reviewer pede uma mudanca num commit especifico do seu PR, em vez de criar um commit novo “address review feedback” (que polui o historico), faca o fix e rode git history fixup. O historico fica limpo como se voce tivesse acertado de primeira.

Cuidado com push –force. O git history reescreve hashes. Se voce ja deu push dos commits afetados, vai precisar de force push. Use sempre --force-with-lease pra evitar sobrescrever trabalho de colegas:


git push --force-with-lease origin feature/minha-branch

Crie um alias. Como o comando ainda e verboso, vale criar atalhos:


git config --global alias.hf 'history fixup'
git config --global alias.hr 'history reword'
git config --global alias.hs 'history split'

Agora voce pode usar git hf abc1234, git hr abc1234, git hs abc1234. Muito mais rapido.

Nao use em branches compartilhadas. O mesmo conselho do rebase vale aqui: nunca reescreva historico que outras pessoas ja puxaram. O git history reescreve commits, o que significa novos hashes. Se alguem esta trabalhando numa branch que descende do commit que voce modificou (e ja fez pull), vai dar conflito no proximo pull.

O Git esta aprendendo com a concorrencia

Vamos ser honestos: o git history nao existiria sem a pressao do Jujutsu e de ferramentas como o git absorb. O ecossistema de controle de versao finalmente saiu da inercia, e o Git esta respondendo. O git replay veio no 2.44, o git history no 2.54/2.55, e a documentacao ja fala abertamente sobre “conflitos de primeira classe” como objetivo futuro.

A proxima vez que alguem te perguntar “por que nao usa jj?”, voce pode responder: “porque o Git ta ficando bom o suficiente”. E pela primeira vez em anos, isso nao e copium.

Quer testar? Atualiza o Git, abre um repo de teste, faz alguns commits bagunca, e brinca com git history split e git history fixup. Em cinco minutos voce vai se perguntar como viveu sem isso.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts