git remove merge commit de l'historique

97

Mon histoire Git ressemble à ça:

Histoire de Git

Je voudrais écraser les commits violets en un seul. Je ne veux plus jamais les revoir dans mon journal de validation.

J'ai essayé de faire un git rebase -i 1, mais même si 1c'est sur la branche bleue (cf. image), je vois toujours tous les commit sur ma branche violette.

Comment puis-je supprimer complètement la branche violette (du journal de validation)?

Benjamin Toueg
la source
Votre repo est-il poussé là où d'autres personnes en ont tiré?
Schleis
Les deux branches sont purement locales.
Benjamin Toueg

Réponses:

100

Cela git rebase -i <sha before the branches diverged>vous permettra de supprimer la validation de fusion et le journal sera une seule ligne comme vous le souhaitez. Vous pouvez également supprimer les validations dont vous ne voulez plus. La raison pour laquelle votre rebase ne fonctionnait pas était que vous ne retourniez pas assez loin.

AVERTISSEMENT: vous réécrivez l'historique en faisant cela. Faire cela avec des modifications qui ont été transmises à un référentiel distant entraînera des problèmes. Je recommande de ne faire cela qu'avec des commits locaux.

Schleis
la source
4
Même si je choisis un sha avant que les branches aient divergé, je vois tous les commits de la branche violette -_-
Benjamin Toueg
1
Ouais, alors vous les supprimez dans l'éditeur qui vient avec git rebaseet ils seront supprimés.
Schleis
4
La suppression des validations entraînait la perte de toutes les modifications de la fusion. Mais j'ai fait une réinitialisation logicielle et j'ai pu avoir quelque chose comme je le voulais (la commande ne correspond pas aux attentes initiales).
Benjamin Toueg
2
cette réponse est incomplète en détail, à partir de quelle branche commencez-vous le rebase?
grgry
3
Assez sûr que vous ne voulez pas «supprimer» les commits. 'remove' n'est pas une option dans rebase, mais delete l'est. si vous supprimez un commit, vous perdrez les changements qu'il a introduits. Vous voulez écraser les commits.
thecoshman
70

À partir du repo dans son état d'origine

Historique du repo original

Pour supprimer le commit de fusion et écraser la branche en un seul commit dans la ligne principale

Commits écrasés, aucun commit de fusion

Utilisez ces commandes (en remplaçant 5 et 1 par les SHA des commits correspondants):

git checkout 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git rebase HEAD master

Pour conserver un commit de fusion mais écraser la branche commit en un:

Commits écrasés, commit de fusion conservé

Utilisez ces commandes (en remplaçant 5, 1 et C par les SHA des commits correspondants):

git checkout -b tempbranch 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git checkout C
git merge --no-ff tempbranch
git rebase HEAD master

Pour supprimer le commit de fusion et le remplacer par des commits individuels de la branche

La branche a été déplacée vers la ligne principale, pas de validation de fusion

Faites simplement (en remplaçant 5 par le SHA du commit correspondant):

git rebase 5 master

Et enfin, pour supprimer entièrement la branche

Branche entièrement supprimée

Utilisez cette commande (en remplaçant C et D par les SHA des commits correspondants):

git rebase --onto C D~ master
Allen Luce
la source
au git rebase 5 mastercas où, pourquoi ce n'est pas l'ordre "ABC 1 2 3 4 5 D ..."?
Roy
1
Cette commande prend les commits qui mastern'ont pas de commun avec 5et les place par-dessus 5. Le commit à Cne fait pas partie de la lignée de 5, c'est le premier à être déplacé dessus 5.
Allen Luce
2
Si vous voulez finir avec "ABC 1 2 3 4 5 D ..." vous pouvez faire:git rebase C 5; git rebase 5 master
Allen Luce
16

Il existe deux façons de résoudre ce problème en fonction de ce que vous voulez:

Solution 1 : supprimez les commits violets, en préservant l'historique (au cas où vous voudriez revenir en arrière)

git revert -m 1 <SHA of merge>

-m 1 spécifie quelle ligne parent choisir

Les commits violets seront toujours là dans l'histoire, mais puisque vous êtes revenu, vous ne verrez pas le code de ces commits.


Solution 2 : supprimer complètement les commits violets (changement perturbateur si le dépôt est partagé)

git rebase -i <SHA before branching out>

et supprimer (supprimer les lignes) correspondant aux commits violets.

Ce serait moins délicat si les validations n'étaient pas effectuées après la fusion. Les commits supplémentaires augmentent les risques de conflits pendant revert/rebase.

prem
la source
Cela ne semble pas juste. Laissant de côté le fait qu'il est difficile de dire ce que l'affiche originale voulait faire avec les commits violets en premier lieu, si vous annulez la fusion, c'est très bien, cela fera un correctif inversé des changements de ce commit et l'ajoutera comme un autre commit, annulant le commit violet. C'est comme 1 - 1 = 0. Mais si vous rebasez ensuite les commits violets, vous laissez le correctif rétabli, à moins que vous ne le rebasiez également. Si vous ne le faites pas, c'est comme s'appliquer -1à votre historique, non 0, donc vous laisserez derrière vous les changements dont vous ne voulez pas.
@Cupcake, fourni étaient deux réponses distinctes. J'ai révisé la réponse pour être moins déroutante: P
prem
AFAIK ce n'est pas ce que le PO demande. Il veut conserver les modifications, mais supprimer le bruit de son journal. Pour cela, il doit écraser les commits, la suppression supprimera les modifications.
thecoshman
Certes, on dirait que la question originale a été reformulée. Cette réponse n'est pas pour le problème des OP.
prem
16

Pour supprimer simplement une validation de fusion

Si tout ce que vous voulez faire est de supprimer un commit de fusion (2) pour que ce soit comme si cela ne s'était jamais produit, la commande est simplement la suivante

git rebase --onto <sha of 1> <sha of 2> <blue branch>

Et maintenant, la branche violette n'est pas du tout dans le journal de validation de bleu et vous avez à nouveau deux branches séparées. Vous pouvez ensuite écraser le violet indépendamment et faire toutes les autres manipulations que vous voulez sans la validation de fusion.

Garenne
la source
De toutes les réponses, je trouve que c'est à la fois la plus simple et la plus simple à faire. Je vous remercie.
Roshambo