Antes de tudo, faça um backup do seu repositório local.
Suponha que sua confirmação corrompida seja <corrupted>
.
Primeiro, crie um novo objeto de confirmação baseado no objeto corrompido:
git commit-tree -m "New message line 1" -m "Line 2" <corrupt>^{tree} -p <corrupt>^1
Nota: adapte seu comando (-p para pais adicionar, -m para linhas de mensagem de commit, etc). Veja a página man do git-commit-tree para lidar com o nome / email do autor, etc.
Você receberá um novo commit SHA-1: <fixed>
.
Agora, faça uma substituição de commit (enxerto):
git replace <corrupted> <fixed>
Isto fará um "enxerto" que irá alterar artificialmente o seu commit corrompido com o fixo.
Esta modificação é reversível: você pode removê-la ou mostrá-la através do comando git-replace
(veja a man page!) ou procurando no diretório .git/refs/replace/
.
Para torná-lo permanente, use git filter-branch
, mas toda a parte alterada será feita de novos objetos de confirmação (ou seja, novos SHA-1s) .
# HEAD should point to the most recent commit (certainly master)...
git filter-branch <fixed>~1..HEAD
Por fim, delate seu substituto (agora permanente em seu histórico):
git replace -d <corrupted>
Isso funciona bem com uma ramificação mestre, mas se você tiver várias ramificações ativas (criadas depois de < corrompido >), você terá que rebase todas elas assim:
git rebase --onto <new-root-branch> <old-root-branch> <branch>
Onde:
-
<new-root-branch>
é o commit do qual o branch deve iniciar agora (nova base SHA-1); -
<old-root-branch>
é o commit do qual a ramificação foi iniciada antes da chamada da ramificação do filtro; -
<branch>
é o ramo para rebase.
Encontre estes SHA-1s com comandos de log como:
git log --graph --decorate --all --pretty=oneline
Quando você checou que tudo está OK (ramificações, etc.) e quando todo mundo vinculado ao seu repositório git está completamente ciente do que está acontecendo, você pode git push --force
suas modificações. / p>