Remover antigos commits do git

88

Eu sou muito novo no git e gostaria de saber se algo assim é possível?

>git log --pretty=oneline --abbrev-commit
2f05aba Added new feature
3371cec Fixed screw up    <-- I want to remove this
daed25c Screw up          <-- and remove this.
e2b2a84 First.                So it's like they never happend.

Isso é possível?

Josh
fonte

Respostas:

63

Isso é possível com git rebase. Tente o seguinte

git rebase -i HEAD~4

e, em seguida, siga as instruções interativas em seu editor. Na primeira etapa, você "esmaga" os commits. Deve ser parecido com isto:

pick 2f05aba ... will be preserved
squash 3371cec ... will be squashed with daed25c
squash daed25c ... will be squashed with e2b2a84
pick e2b2a84 .. will contain this and 3371cec and daed25c

Na segunda etapa, você pode editar as mensagens de confirmação.

Deve
fonte
25
A questão não é deletar os commits ao invés de esmagá-los?
Richard,
3
@Stony: Bem, provavelmente você também poderia excluí-los. Mas a partir dos comentários de commit no OP ("Screw up" e "Fixed screw up") eu assumi que um está desfazendo o outro e que você poderia simplesmente esmagar os dois.
Deve,
85

Se você realmente deseja excluí-los (apagando-os da história, para nunca mais serem vistos), você pode

executar rebase:

git rebase -i HEAD~4

e então, apenas exclua (ou comente) as linhas correspondentes aos commits que você deseja excluir, assim:

pick 2f05aba ... #will be preserved
#pick 3371cec ... #will be deleted
#pick daed25c ... #will be deleted
pick e2b2a84 ... #will be preserved
Shathur
fonte
2
Eu sou novo no github, como você empurra as alterações depois disso (quando eu clico em Sincronizar, isso apenas reverte o que eu fiz) Acho que entendi: git push origin HEAD --force
Nicolas Thery
@NicolasThery, você não. É por isso que o git push se recusa a funcionar sem --force, porque você está reescrevendo a história e quebrará os repositórios de outras pessoas. Se você já fez push, sua única opção é fazer um git revert. O que, quando você pensa sobre isso, é sensato porque se você puxou o código de outra pessoa, você não gostaria que ela fosse capaz de apagar seus antigos commits sem algum tipo de histórico, não é?
Dan irritado
Presumo que isso simplesmente funcione no repositório Git atual e não mude nada no upstream / qualquer outro nó Git?
Alexander Mills de
2
@AlexanderMills Isso não muda nada no upstream, contanto que você não empurre-o (e se você fizer isso, você tem que adicionar o sinalizador --force como o Angry Dan disse).
Shathur
dou dropé o comando para remover commits do histórico.
Carrinho abandonado
5

Para deletar completamente o (s) commit (s), há uma nova opção droppara rebases interativo do git agora. Primeira corrida:

git rebase -i HEAD~4

Em seguida, substitua pickpor droppara que os commits sejam descartados:

pick 2f05aba ... #will be preserved
drop 3371cec ... #will be dropped
drop daed25c ... #will be dropped
pick e2b2a84 ... #will be preserved

Isso funcionou no Fedora para mim com a seguinte versão:

$ git version
git version 2.21.0
russoue
fonte
2

Squash é útil quando você deseja gerar uma lista de commits mesclados em um único hash, mas se você está procurando pegar três commits separados e ter uma saída final que pareça ser um único commit, eu recomendo fixup

git rebase -i HEAD~4

pick 2f05aba ... will be preserved
fixup 3371cec ... will be merged with daed25c
fixup daed25c ... will be merged with e2b2a84
pick e2b2a84 .. will include 3371cec and daed25c, but only the commit message of e2b2a84

Você pode encontrar mais informações na lista de comandos da IU do rebase interativo.

Carrinho Abandonado
fonte