Se um commit mais antigo contiver uma alteração indesejada em um arquivo, você poderá reverter a alteração desse arquivo em relação ao seu branch atual e salvar o resultado em um novo commit. Isso mantém os commits posteriores no lugar e preserva as edições deles quando o patch reverso ainda se ajusta. No macOS, use o Terminal a partir do repositório; revise o patch primeiro, especialmente se o trabalho posterior tiver modificado as mesmas linhas.

Escolha a alteração de histórico correta

Este procedimento adiciona um commit que cancela a alteração do commit de destino em um único caminho. Ele não apaga esse arquivo do commit antigo, portanto a versão antiga permanece no histórico. Essa abordagem evita a reescrita do histórico do branch e geralmente é adequada quando o commit já foi compartilhado ou commits posteriores dependem dele. O Git descreve o git revert como o registro de um novo commit que reverte um commit anterior, mas não oferece uma opção integrada para reverter apenas um caminho de um commit existente. Em vez disso, as etapas abaixo geram o patch desse caminho e o aplicam de forma reversa. Documentação do Git: git-revert

Se a alteração do arquivo precisar ser removida do próprio commit histórico, trata-se de uma tarefa de reescrita de histórico, normalmente realizada com um rebase interativo. A reescrita altera as identidades dos commits e pode prejudicar colaboradores que basearam trabalhos nos commits antigos. Este guia aborda a abordagem cumulativa, que é mais segura.

Reverter a alteração do commit de destino em um arquivo

Abra o Terminal, navegue até o repositório e verifique a árvore de trabalho antes de alterar qualquer coisa. Substitua TARGET pelo ID do commit e path/to/file pelo caminho relativo à raiz do repositório. O exemplo usa um arquivo de patch temporário no diretório /tmp do macOS; escolha um nome temporário diferente se esse arquivo já existir.

git status --short
git show --stat --oneline TARGET
git diff TARGET^ TARGET -- "path/to/file" > /tmp/remove-file-change.patch

O diff compara o commit de destino com seu primeiro commit pai e restringe o resultado ao caminho especificado. Para um commit normal, sem ser de merge, isso representa a alteração que o commit fez no arquivo. Confirme se o resumo identifica o commit desejado e se o patch não está vazio. Você pode inspecioná-lo com less /tmp/remove-file-change.patch; pressione q para sair. O Git documenta diffs de commit a commit com uma limitação opcional de caminho. Documentação do Git: git-diff

Antes de aplicá-lo, certifique-se de que não há edições não relacionadas, preparadas (staged) ou não, no arquivo de destino. O patch reverso altera a cópia de trabalho, portanto uma árvore de trabalho limpa é o ponto de partida mais simples. Se você tiver um trabalho local útil, faça commit ou guarde-o em segurança primeiro; não o sobrescreva com um comando de restauração.

Verifique se o patch reverso se ajusta e, em seguida, aplique-o:

git apply --reverse --check /tmp/remove-file-change.patch
git apply --reverse /tmp/remove-file-change.patch

--reverse aplica o diff de forma invertida, enquanto --check verifica se ele se aplica sem alterar arquivos. Por padrão, o git apply falha o patch inteiro se alguns blocos (hunks) não se ajustarem, em vez de aplicar apenas as partes compatíveis. Se a verificação falhar, pare e inspecione o arquivo e o patch. Edições posteriores podem se sobrepor à alteração de destino, de modo que o Git não consiga determinar com segurança o que deve ser removido. Resolva o conteúdo desejado manualmente ou use um fluxo de trabalho de reescrita de histórico se a preservação de uma sequência histórica editada com precisão for essencial. Não adicione --reject de forma imprudente: isso pode aplicar apenas as partes compatíveis e deixar blocos rejeitados para trás. Documentação do Git: git-apply

Revisar e comitar o resultado

Inspecione exatamente o que mudou antes de preparar (stage) as alterações. O git diff mostra as edições na árvore de trabalho; use o caminho novamente para focar a revisão. Se o resultado estiver correto, prepare esse arquivo e verifique o diff preparado antes de criar um novo commit.

git diff -- "path/to/file"
git add -- "path/to/file"
git diff --cached -- "path/to/file"
git status --short
git commit -m "Remove file change from earlier commit"

As aspas protegem o caminho da interpretação pelo shell, e -- marca o fim das opções. Elas são especialmente úteis para nomes que contêm espaços ou metacaracteres do shell. O commit registra o índice preparado; revisar com git diff --cached verifica o conteúdo exato que está prestes a ser comitado. Documentação do Git: git-commit

Depois de comitar, verifique o git status --short e inspecione o novo commit com git show --stat --oneline HEAD. Se o commit original tiver adicionado o arquivo, reverter o patch dele pode excluí-lo — isso é esperado se nenhum conteúdo posterior precisar permanecer. Se commits posteriores tiverem adicionado conteúdo útil a esse arquivo, essas adições devem permanecer quando o patch reverso for aplicado de forma limpa; revise o arquivo final e o diff para confirmar.

Casos que exigem cuidado extra

Um commit de merge tem múltiplos pais, e sua alteração depende de qual pai você toma como base para a comparação. TARGET^ significa o primeiro pai; ele pode não representar a alteração que você pretendia remover. Identifique o pai correto e compare com ele explicitamente antes de aplicar qualquer coisa. Renomeações, arquivos binários e arquivos que foram movidos desde então também podem tornar inadequado um patch restrito por caminho; verifique o diff e pare se ele não descrever a alteração desejada no arquivo. Para reversões específicas de merges, a documentação de revert do Git explica a escolha do pai da linha principal (mainline) e suas consequências. Documentação do Git: git-revert

O ponto de controle confiável é o patch revisado: ele deve mostrar apenas a alteração do commit de destino no caminho desejado. Se ele não puder ser aplicado de forma limpa ao arquivo atual, não force. Reconstrua o arquivo atual desejado com cuidado, depois prepare e comite apenas após revisar o resultado completo.

Fontes