Se sua intenção é somente corrigir o erro, a melhor prática é fazer um novo commit F com a correção e uma descrição adequada.
Porém, se sua intenção é remover o erro do histórico fingindo que nunca aconteceu, existe uma opção (mas ela só é adequada se você é o único trabalhando na branch onde existe o erro, pois é necessário fazer um push forçado): utilizar o rebase. O meu fluxo em geral é:
- Abro uma nova branch local no commit em que o erro foi adicionado:
git checkout -b removendoErroXYZ hashDoCommitC - Corrijo o erro. Não altero as coisas que foram feitas corretamente.
- Altero o commit que inseria o erro:
git commit --amend - Volto para a branch anterior:
git checkout branchOriginal - Resolvo o rebase:
git rebase removendoErroXYZ. Em geral, o primeiro commit (o C) vai dar conflito, depois é só rodar git rebase --skip para que ele continue o processo automaticamente. Se houver outros conflitos, resolvo manualmente. - Faço o
push para o repositório remoto. Se o erro já tiver sido pushado anteriormente, uso git push -f para forçar a sobrescrever o remoto. MUITO CUIDADO com essa opção. Não use levianamente. - Apago a branch temporária do erro
git branch -D removendoErroXYZ
Lembrando que tudo isso só é válido mesmo se só você estiver trabalhando na branch. O push -f pode ser problemático para trabalho em equipe e o mais adequado é criar um commit novo com a descrição do erro.