Combine os dois primeiros commits de um repositório Git?
-
22-07-2019 - |
Pergunta
Suponha que você tenha um histórico contendo as três commits A, B e C :
A-B-C
Gostaria de combinar os dois commits A e B para um commit AB :
AB-C
Eu tentei
git rebase -i A
que abre meu editor com o seguinte conteúdo:
pick e97a17b B
pick asd314f C
Eu mudar isso para
squash e97a17b B
pick asd314f C
Em seguida, Git 1.6.0.4 diz:
Cannot 'squash' without a previous commit
Existe uma maneira ou isso é simplesmente impossível?
Solução
Use git rebase -i --root
a partir de Git versão 1.7.12 .
No arquivo rebase interativo, altere a segunda linha de cometer B e abóbora e deixar as outras linhas no escolher :
pick f4202da A
squash bea708e B
pick a8c6abc C
Isto irá combinar os dois commits A e B para um commit AB .
Outras dicas
Você tentou:
git rebase -i A
É possível começar como que se você continuar com edit
em vez de squash
:
edit e97a17b B
pick asd314f C
, em seguida, executar
git reset --soft HEAD^
git commit --amend
git rebase --continue
Feito.
A
foi o commit inicial, mas agora você quer B
ser o commit inicial. commits git são árvores inteiras, não diffs mesmo se eles são normalmente descritos e visualizadas em termos do diff que eles introduzem.
Esta receita funciona mesmo se houver vários commits entre A e B, e B e C.
# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>
# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>
# amend the initial tree using the tree from 'B'
git commit --amend
# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp
# go back to the original branch (assume master for this example)
git checkout master
# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>
# remove the temporary tag
git tag -d tmp
No caso de rebase interativo, você tem que fazê-lo antes de A para que a lista será:
pick A
pick B
pick C
para tornar-se:
pick A
squash B
pick C
Se A é o commit inicial, você tem que ter uma inicial diferente cometer antes A. Git pensa em diferenças, ele vai trabalhar sobre a diferença entre (A e B) e (B e C). Daí a abóbora não funciona no seu exemplo.
No caso que você tem centenas ou milhares de commits, usando de kostmo resposta de
git rebase -i --root
pode ser impraticável e lento, apenas devido ao grande número de commits que o script rebase tem de processo duas vezes , uma vez para gerar a lista de editor rebase interativo (onde você seleciona quais as medidas a tomar para cada commit), e uma vez para realmente executar a re-aplicação de commits.
Aqui é uma solução de alternativa que irá evitar o custo do tempo de gerar a lista editor rebase interativo por não usar um rebase interativo em primeiro lugar. Desta forma, é semelhante ao do Charles Bailey solução . Você simplesmente criar um órfão ramo a partir do segundo cometer, e depois rebase todos os commits descendentes em cima dela:
git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master
Documentação
Em uma questão relacionada, consegui chegar a uma abordagem diferente para a necessidade de esmagamento contra o primeiro commit, que é, assim, para torná-lo o segundo.
Se você estiver interessado: git: como inserir um commit como o primeiro, mudando todos os outros
comando Git para o time: git rebase -i CABEÇA ~ [número de commits]
Vamos dizer que você tem abaixo git commit história:
pegar 5152061 façanha: Adicionado suporte para salvar imagem. (UMA)
escolher 39c5a04 Fix: correções de bugs. (B)
escolher 839c6b3 correção: conflito resolvido. (C)
Agora você quer esmagar A e B AB, execute os passos abaixo:
pegar 5152061 façanha: Adicionado suporte para salvar imagem. (UMA)
é 39c5a04 Fix: correções de bugs. (B)
escolher 839c6b3 correção: conflito resolvido. (C)
Nota: para esmagar cometer podemos usar squash ou s.
O resultado final será:
pegar 5152061 façanha: Adicionado suporte para salvar imagem. (AB)
escolher 839c6b3 correção: conflito resolvido. (C)
Você tem que executar um pouco de magia de linha de comando.
git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a
Isso deve deixá-lo com um ramo que tem AB e C como commits.