209 votes

Combiner les deux premiers commits d'un dépôt Git ?

Supposons que vous disposiez d'un historique contenant les trois commits suivants A, B y C :

A-B-C

Je voudrais combiner les deux engagements A y B à un seul engagement AB :

AB-C

J'ai essayé

git rebase -i A

ce qui ouvre mon éditeur avec le contenu suivant :

pick e97a17b B
pick asd314f C

Je le remplace par

squash e97a17b B
pick asd314f C

Ensuite, Git 1.6.0.4 dit :

Cannot 'squash' without a previous commit

Existe-t-il un moyen ou est-ce tout simplement impossible ?

0 votes

0 votes

187voto

kostmo Points 2265

Utilice git rebase -i --root à partir de Git version 1.7.12 .

Dans le fichier rebase interactif, modifiez la deuxième ligne du commit B a courge et laisser les autres lignes à choisir :

pick f4202da A
squash bea708e B
pick a8c6abc C

Ceci combinera les deux commits A y B à un engagement AB .

Trouvé dans cette réponse .

126voto

David Lichteblau Points 2973

Vous avez essayé :

git rebase -i A

Il est possible de commencer comme cela si vous continuez avec edit plutôt que squash :

edit e97a17b B
pick asd314f C

puis exécuter

git reset --soft HEAD^
git commit --amend
git rebase --continue

Fait.

4 votes

Si vous faites cela pour corriger discrètement une gist github, vous devrez ajouter -m "initial" au commit ;-)

1 votes

git rebase --abort de recommencer à zéro et de faire les choses correctement (sans écraser le premier commit dans l'éditeur)

66voto

Charles Bailey Points 244082

A était le commit initial, mais maintenant vous voulez B pour être le commit initial. Les commits git sont des arbres entiers, pas des diffs même s'ils sont normalement décrits et vus en termes de diff qu'ils introduisent.

Cette recette fonctionne même s'il y a plusieurs commits entre A et B, et B et 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

1 votes

Cela déclenche un rebasement interactif massif lorsque je fais le git rebase --onto tmp <sha1_for_B>

0 votes

Considérant que j'avais un tout nouveau repo avec seulement deux commits (que je voulais regrouper en un seul), cela a parfaitement fonctionné pour moi. Merci @CB Bailey

10voto

Loki Points 7801

Dans le cas d'un rebasement interactif, il faut le faire avant A pour que la liste soit :

pick A
pick B
pick C

devenir :

pick A
squash B
pick C

Si A est le commit initial, vous devez avoir un commit initial différent avant A. Git pense en différences, il travaillera sur la différence entre (A et B) et (B et C). C'est pourquoi le squash ne fonctionne pas dans votre exemple.

9voto

Cupcake Points 22154

Dans le cas où vous avez des centaines ou des milliers de commits, l'utilisation de Réponse de kostmo de

git rebase -i --root

peut s'avérer peu pratique et lent, en raison du grand nombre de modifications que le script rebase script doit traiter. deux fois Une fois pour générer la liste interactive de l'éditeur de rebase (où vous sélectionnez l'action à entreprendre pour chaque livraison), et une fois pour exécuter la réapplication des livraisons.

Voici un exemple solution alternative qui évitera le coût en temps de la génération de la liste interactive de l'éditeur de rebase en n'utilisant pas de rebase interactive en premier lieu. En ce sens, il est similaire à La solution de Charles Bailey . Il suffit de créer un branche orpheline à partir du deuxième commit, puis rebase tous les commits descendants par-dessus :

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

Documentation

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X