web-dev-qa-db-fra.com

Les validations de fusion n'apparaissent pas dans git rebase --interactive

git log révèle ce qui suit:

commit 1abcd[...]
Author: [...]
Date: [...]

    [Useful commit]

commit 2abcd[...]
Author: [...]
Date: [...]

    Merge branch [...] of [etc. etc.]

commit 3abcd[...]
Author: [...]
Date: [...]

    [Useful commit]

Ce commit de fusion est inutile pour moi - il ne représente pas un état significatif de la branche et a été généré à partir d'un pull distant, j'ai donc les vrais commits de l'historique distant - pas besoin d'un commit pour marquer le fait que j'ai tiré . Je voudrais annuler ce commit de fusion. Ma technique habituelle pour faire un squash est:

git rebase --interactive HEAD~2 (ou aussi loin que je doive y aller)

Et puis je l'écraserais dans un commit voisin. Je le fais parfois si, par exemple, je fais un commit, je me rends compte que j'ai raté un petit détail important (un seul fichier ou que je n'ai pas changé de ligne dans l'un des fichiers) et que je fais un autre commit qui n'est en fait qu'un rapide oups. De cette façon, lorsque je repousse mes modifications vers la télécommande, tout est agréable et propre et raconte une narration cohérente.

Cependant, dans ce cas, lorsque j'exécute le git rebase ... commande, commit 2abcd n'apparaît pas! Il semble sauter directement 2abcd et affiche à la place 1abcd et 3abcd. Y a-t-il quelque chose de spécial dans un commit de fusion qui l'empêche d'apparaître dans git rebase --interactive? Quelle autre technique pourrais-je utiliser pour écraser ce commit de fusion?

MISE À JOUR selon la demande de @ Cupcake:

La sortie de git log --graph --oneline --decorate ressemble à ça:

* 1abcd (useful commit)
* 2abcd (merge)
|  \ <-- from remote
|   * 3abcd (useful commit)
|   |

Utile?

29
NWard

Rebase ne conserve normalement pas les validations de fusion sans --preserve-merges

Ok, donc je ne suis pas sûr de ce qui se passerait si vous tentiez d'écraser un commit de fusion en utilisant une rebase interactive avec --preserve-merges... mais c'est ainsi que je supprimerais le commit de fusion dans votre cas et que votre historique serait linéaire:

  1. Rebase tout avant le commit de fusion au-dessus de la branche distante.

  2. Cherry-pick ou rebase tout après la validation de fusion en plus des validations précédemment rebasées.

Si vous n'avez qu'un seul commit après le commit de fusion

Donc, en termes de commandes, cela ressemblerait à ceci:

# Reset to commit before merge commit
git reset --hard <merge>^

# Rebase onto the remote branch
git rebase <remote>/<branch>

# Cherry-pick the last commit
git cherry-pick 1abcd 

Si vous avez plus d'un commit après le commit de fusion

# Leave a temporary branch at your current commit
git branch temp

# Reset to commit before merge commit
git reset --hard <merge>^

# Rebase onto the remote branch
git rebase <remote>/<branch>

# Cherry-pick the last commits using a commit range.
# The start of the range is exclusive (not included)
git cherry-pick <merge>..temp

# Alternatively to the cherry-pick above, you can instead rebase everything
# from the merge commit to the tip of the temp branch onto the other
# newly rebased commits.
#
# You can also use --preserve-merges to preserve merge commits following
# the first merge commit that you want to get rid of...but if there were
# any conflicts in those merge commits, you'll need to re-resolve them again.
git rebase --preserve-merges --onto <currentBranch> <merge> temp

# These next steps are only necessary if you did the rebase above,
# instead of using the cherry-pick range.
#
# Fast-forward your previous branch and delete temp
git checkout <previousBranch>
git merge temp
git branch -d temp

Documentation

32
user456814