La documentationrebase
de Git pour la commande est assez brève:
--preserve-merges
Instead of ignoring merges, try to recreate them.
This uses the --interactive machinery internally, but combining it
with the --interactive option explicitly is generally not a good idea
unless you know what you are doing (see BUGS below).
Alors, que se passe-t-il réellement lorsque vous utilisez --preserve-merges
? En quoi diffère-t-il du comportement par défaut (sans cet indicateur)? Que signifie «recréer» une fusion, etc.
git
git-rebase
Chris
la source
la source
git --rebase-merges
finira par remplacer l'anciengit --preserve-merges
. Voir ma réponse ciRéponses:
Comme avec un rebase git normal, git with
--preserve-merges
identifie d'abord une liste de validations effectuées dans une partie du graphe de validation, puis relit ces validations au-dessus d'une autre partie. Les différences--preserve-merges
concernant les validations sont sélectionnées pour la relecture et comment cette relecture fonctionne pour les validations de fusion.Pour être plus explicite sur les principales différences entre le rebasage normal et le maintien de la fusion:
git checkout <desired first parent>
relecture des validations de fusion nécessite également de vérifier explicitement des validations particulières ( ), alors que le rebase normal n'a pas à s'en soucier.Je vais d'abord essayer de décrire "suffisamment exactement" ce que
--preserve-merges
fait rebase , puis il y aura quelques exemples. On peut bien sûr commencer par les exemples, si cela semble plus utile.L'algorithme en "bref"
Si vous voulez vraiment entrer dans les mauvaises herbes, téléchargez la source git et explorez le fichier
git-rebase--interactive.sh
. (Rebase ne fait pas partie du noyau C de Git, mais est plutôt écrit en bash. Et, dans les coulisses, il partage le code avec "rebase interactif".)Mais ici, je vais esquisser ce que je pense en être l'essence. Afin de réduire le nombre de choses à penser, j'ai pris quelques libertés. (par exemple, je n'essaie pas de capturer avec une précision de 100% l'ordre précis dans lequel les calculs ont lieu, et d'ignorer certains sujets moins centraux, par exemple ce qu'il faut faire à propos des commits qui ont déjà été choisis entre les branches).
Tout d'abord, notez qu'un rebase sans préservation de fusion est plutôt simple. C'est plus ou moins:
Le rebase
--preserve-merges
est relativement compliqué. Voici aussi simple que j'ai pu le faire sans perdre des choses qui semblent assez importantes:Rebaser avec un
--onto C
argument devrait être très similaire. Juste au lieu de commencer la lecture de validation à la TÊTE de B, vous commencez plutôt la lecture de validation à la TÊTE de C. (Et utilisez C_new au lieu de B_new.)Exemple 1
Par exemple, prenez le graphe de validation
m est un engagement de fusion avec les parents E et G.
Supposons que nous ayons rebasé le sujet (H) au-dessus du maître (C) à l'aide d'un rebase normal, sans conservation de fusion. (Par exemple, rubrique de paiement; maître de rebase .) Dans ce cas, git sélectionnerait les validations suivantes pour la relecture:
puis mettez à jour le graphique de validation comme suit:
(D 'est l'équivalent rejoué de D, etc.)
Notez que la validation de fusion m n'est pas sélectionnée pour la relecture.
Si nous faisions plutôt une
--preserve-merges
rebase de H au-dessus de C. (Par exemple, rubrique de paiement; rebase --preserve-merges master .) Dans ce nouveau cas, git sélectionnerait les validations suivantes pour la relecture:Maintenant, m a été choisi pour la relecture. Notez également que les parents de fusion E et G ont été sélectionnés pour inclusion avant la validation de fusion m.
Voici le graphe de validation résultant:
Encore une fois, D 'est une version sélectionnée de D. (c'est-à-dire recréée) de D. Idem pour E', etc. Chaque commit qui n'est pas sur master a été rejoué. E et G (les parents de fusion de m) ont été recréés en tant que E 'et G' pour servir de parents de m '(après rebase, l'histoire de l'arbre reste la même).
Exemple 2
Contrairement au rebase normal, le rebase préservant la fusion peut créer plusieurs enfants de la tête en amont.
Par exemple, considérez:
Si nous rebase H (sujet) au-dessus de C (maître), alors les commits choisis pour rebaser sont:
Et le résultat est comme ça:
Exemple 3
Dans les exemples ci-dessus, la validation de fusion et ses deux parents sont des validations rejouées, plutôt que les parents d'origine que la validation de fusion d'origine possède. Cependant, dans d'autres rebases, une validation de fusion rejouée peut se retrouver avec des parents qui étaient déjà dans le graphique de validation avant la fusion.
Par exemple, considérez:
Si nous rebasons le sujet sur le maître (préservant les fusions), les validations de relecture seront
Le graphique de validation réécrit ressemblera à ceci:
Ici, le commit de fusion rejoué m 'obtient les parents qui préexistaient dans le graphe de commit, à savoir D (la tête de maître) et E (l'un des parents du commit de fusion d'origine m).
Exemple 4
Le rebase préservant la fusion peut être confus dans certains cas de «commit vide». Au moins, cela n'est vrai que pour certaines anciennes versions de git (par exemple 1.7.8.)
Prenez ce graphique de validation:
Notez que les commit m1 et m2 auraient dû incorporer toutes les modifications de B et F.
Si nous essayons de faire
git rebase --preserve-merges
de H (sujet) sur D (maître), les commits suivants sont choisis pour être rejoués:Notez que les changements (B, F) unis dans m1 devraient déjà être incorporés dans D. (Ces changements devraient déjà être incorporés dans m2, car m2 fusionne les enfants de B et F.) Par conséquent, conceptuellement, rejouer m1 au-dessus de D devrait probablement être un no-op ou créer un commit vide (c'est-à-dire un où la différence entre les révisions successives est vide).
Au lieu de cela, cependant, git peut rejeter la tentative de rejouer m1 sur D. Vous pouvez obtenir une erreur comme ceci:
Il semble que l'on ait oublié de passer un indicateur à git, mais le problème sous-jacent est que git n'aime pas créer des commits vides.
la source
git rebase --preserve-merges
c'est beaucoup plus lent qu'unrebase
sans--preserve-merges
. Est-ce un effet secondaire de trouver les bons engagements? Peut-on faire quelque chose pour l'accélérer? (Au fait… merci pour la réponse très détaillée!)Git 2.18 (Q2 2018) améliorera considérablement l'
--preserve-merge
option en ajoutant une nouvelle option."
git rebase
" appris "--rebase-merges
" pour transplanter toute la topologie du graphe de validation ailleurs .(Remarque: Git 2.22, Q2 2019, devient obsolète
--preserve-merge
, et Git 2.25, Q1 2020, cesse de le publier dans lagit rebase --help
sortie " " )Voir commettre 25cff9f , engager 7543f6f , engager 1131ec9 , engager 7ccdf65 , engager 537e7d6 , commettre a9be29c , commettre 8f6aed7 , commettre 1644c73 , commettre d1e8b01 , commettre 4c68e7d , engager 9055e40 , engager cb5206e , engager a01c2a5 , engager 2f6b1d1 , engager bf5c057 (25 avril 2018) par Johannes Schindelin (
dscho
) .Voir commit f431d73 (25 avril 2018) par Stefan Beller (
stefanbeller
) .Voir commit 2429335 (25 avril 2018) par Phillip Wood (
phillipwood
) .(Fusionné par Junio C Hamano -
gitster
- en commit 2c18e6a , 23 mai 2018)git rebase
La page de manuel contient désormais une section complète dédiée au rebasage de l'historique avec les fusions .Extrait:
Voir commit 1644c73 pour un petit exemple:
Quelle est la différence avec
--preserve-merge
?Le commit 8f6aed7 explique:
Et par "le vôtre vraiment", l'auteur se réfère à lui-même: Johannes Schindelin (
dscho
) , qui est la raison principale (avec quelques autres héros - Hannes, Steffen, Sebastian, ...) que nous avons Git pour Windows (même si à l'époque - 2009 - ce n'était pas facile ).Il travaille chez Microsoft depuis septembre 2015 , ce qui est logique étant donné que Microsoft utilise désormais fortement Git et a besoin de ses services.
Cette tendance a commencé en 2013 avec TFS . Depuis lors, Microsoft gère le plus grand référentiel Git de la planète ! Et, depuis octobre 2018, Microsoft a acquis GitHub .
Vous pouvez voir Johannes parler dans cette vidéo pour Git Merge 2018 en avril 2018.
Ici, Jonathan parle d' Andreas Schwab de Suse.
Vous pouvez voir certaines de leurs discussions en 2012 .
(Le script Git garden shears est référencé dans ce patch dans commit 9055e40 )
Git 2.19 (Q3 2018) améliore la nouvelle
--rebase-merges
option en la faisant fonctionner avec--exec
.L'
--exec
option " " pour "git rebase --rebase-merges
" a placé les commandes exec aux mauvais endroits, ce qui a été corrigé.Voir commit 1ace63b (09 août 2018) et commit f0880f7 (06 août 2018) par Johannes Schindelin (
dscho
) .(Fusionné par Junio C Hamano -
gitster
- dans commit 750eb11 , 20 août 2018)Git 2.22 (Q2 2019) corrige l'utilisation de refs / rewritten / hierarchy pour stocker un état intermédiaire de rebase, ce qui rend intrinsèquement la hiérarchie par arbre de travail.
Voir commit b9317d5 , commit 90d31ff , commit 09e6564 (07 mars 2019) par Nguyễn Thái Ngọc Duy (
pclouds
) .(Fusionné par Junio C Hamano -
gitster
- dans commit 917f2cd , 09 avr.2019 )a9be29c (séquenceur: créer des références générées par la
label
commande worktree-local, 2018-04-25, Git 2.19) ajouterefs/rewritten/
comme espace de référence par arbre de travail.Malheureusement (ma mauvaise), il y a quelques endroits qui ont besoin d'une mise à jour pour s'assurer que c'est vraiment par arbre de travail.
Avec Git 2.24 (Q4 2019), "
git rebase --rebase-merges
" a appris à piloter différentes stratégies de fusion et à leur transmettre des options spécifiques.Voir commit 476998d (04 sept. 2019) par Elijah Newren (
newren
) .Voir commettre e1fac53 , engager a63f990 , engager 5dcdd74 , engager e145d99 , engager 4e6023b , engager f67336d , engager a9c7107 , engager b8c6f24 , engager d51b771 , engager c248d32 , engager 8c1e240 , engager 5efed0e , engager 68b54f6 , engager 2e7bbac , engager 6180b20 , engager d5b581f (31 Juil.2019) parJohannes Schindelin (
dscho
) .(Fusionné par Junio C Hamano -
gitster
- en commit 917a319 , 18 sept. 2019)Avec Git 2.25 (T1 2020), la logique utilisée pour différencier les références globales locales et référentielles de Worktree est fixe, pour faciliter la conservation-fusion.
Voir commit f45f88b , commit c72fc40 , commit 8a64881 , commit 7cb8c92 , commit e536b1f (21 octobre 2019) par SZEDER Gábor (
szeder
) .(Fusionné par Junio C Hamano -
gitster
- dans commit db806d7 , 10 nov.2019 )la source
--preserve-merges
ne "conserve" pas réellement les fusions comme vous le souhaitez, c'est très naïf. Cela vous permet de conserver les validations de fusion et leurs relations de validation parentes tout en vous offrant la flexibilité d'un rebase interactif. Cette nouvelle fonctionnalité est géniale et sinon pour cette réponse SO bien écrite, je ne l'aurais pas su!