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 la git 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)
pull
: accepter --rebase-merges
de recréer la topologie de branche
Semblable au preserve
mode passant simplement l' --preserve-merges
option à la rebase
commande, le merges
mode passe simplement l'
--rebase-merges
option.
Cela permettra aux utilisateurs de rebaser facilement les topologies de validation non triviales lors de l'extraction de nouvelles validations, sans les aplatir.
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:
Il existe des raisons légitimes pour lesquelles un développeur peut vouloir recréer des validations de fusion: pour conserver la structure de branche (ou «validation de la topologie») lorsqu'il travaille sur plusieurs branches liées entre elles.
Dans l'exemple suivant, le développeur travaille sur une branche de rubrique qui réorganise la façon dont les boutons sont définis, et sur une autre branche de rubrique qui utilise cette refactorisation pour implémenter un bouton "Signaler un bogue".
La sortie de git log --graph --format=%s -5
peut ressembler à ceci:
* Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one
Le développeur peut vouloir rebaser ces validations vers une version plus récente master
tout en conservant la topologie de branche, par exemple lorsque la première branche de sujet devrait être intégrée master
beaucoup plus tôt que la seconde, par exemple, pour résoudre les conflits de fusion avec les modifications apportées à la
DownloadButton
classe qui a fait il en master
.
Ce rebase peut être effectué à l'aide de l' --rebase-merges
option.
Voir commit 1644c73 pour un petit exemple:
rebase-helper
--make-script
: introduire un drapeau pour rebaser les fusions
Le séquenceur vient d'apprendre de nouvelles commandes destinées à recréer la structure des branches ( similaire dans l'esprit --preserve-merges
, mais avec une conception sensiblement moins cassée ).
Laissons le rebase--helper
générer des listes de tâches en utilisant ces commandes, déclenchées par la nouvelle --rebase-merges
option.
Pour une topologie de validation comme celle-ci (où le HEAD pointe vers C):
- A - B - C (HEAD)
\ /
D
la liste de tâches générée ressemblerait à ceci:
# branch D
pick 0123 A
label branch-point
pick 1234 D
label D
reset branch-point
pick 2345 B
merge -C 3456 D # C
Quelle est la différence avec --preserve-merge
?
Le commit 8f6aed7 explique:
Il était une fois, ce développeur pensait: ce ne serait pas bien si, disons, les correctifs de Git pour Windows au-dessus du noyau Git pouvaient être représentés comme un bosquet de branches, et être rebasés au-dessus du noyau Git afin de maintenir un ensemble de patchs sélectionnables?
La tentative originale pour répondre à c'était: git rebase --preserve-merges
.
Cependant, cette expérience n'a jamais été conçue comme une option interactive, et elle n'a été soutenue git rebase --interactive
que parce que l'implémentation de cette commande semblait déjà très, très familière: elle a été conçue par la même personne qui a conçu --preserve-merges
: la vôtre vraiment.
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.
Quelque temps plus tard, un autre développeur (je vous regarde, Andreas! ;-)) a décidé que ce serait une bonne idée de permettre --preserve-merges
d'être combiné avec --interactive
(avec des mises en garde!) Et le mainteneur Git (enfin, le mainteneur intérimaire Git pendant l'absence de Junio, c'est-à-dire) d'accord, et c'est alors que le glamour du --preserve-merges
design a commencé à s'effondrer assez rapidement et sans glamour.
Ici, Jonathan parle d' Andreas Schwab de Suse.
Vous pouvez voir certaines de leurs discussions en 2012 .
La raison? En --preserve-merges
mode, les parents d'un commit de fusion (ou d'ailleurs, de n'importe quel commit) n'étaient pas indiqués explicitement, mais étaient
impliqués par le nom de commit passé à la pick
commande .
Cela a rendu impossible, par exemple, la réorganisation des commits .
Sans oublier de déplacer les commits entre les branches ou, Dieu ne plaise, de diviser les branches du sujet en deux.
Hélas, ces lacunes ont également empêché ce mode (dont le but initial était de répondre aux besoins de Git pour Windows, avec l'espoir supplémentaire qu'il pourrait être utile à d'autres aussi) de répondre aux besoins de Git pour Windows.
Cinq ans plus tard, quand il est devenu vraiment intenable d'avoir une grande série de patchs Hodge-Podge peu maniables de Git pour Windows partiellement liés et partiellement non liés qui a été rebasé de temps en temps sur les balises Git de base (gagnant la colère imméritée du développeur de la git-remote-hg
série malheureuse
qui a d'abord obsédé l'approche concurrentielle de Git pour Windows, pour ensuite être abandonnée sans responsable plus tard) était vraiment intenable, les " cisailles de jardin Git " étaient nées : un script, le ferroutage au-dessus du rebase interactif, qui déterminerait d'abord la topologie de branche des correctifs à rebaser, créerait une pseudo liste de tâches à éditer, transformerait le résultat en une véritable liste de tâches (faisant un usage intensif de laexec
pour "implémenter" les commandes de liste de tâches manquantes) et enfin recréer la série de correctifs au-dessus du nouveau commit de base.
(Le script Git garden shears est référencé dans ce patch dans commit 9055e40 )
C'était en 2013.
Et il a fallu environ trois semaines pour arriver à la conception et l'implémenter en tant que script hors arbre. Inutile de dire que la mise en œuvre a eu besoin de quelques années pour se stabiliser, tout en garantissant que la conception elle-même a fait ses preuves.
Avec ce patch, la bonté des ciseaux de jardin Git revient à git
rebase -i
elle-même .
Passer l' --rebase-merges
option générera une liste de tâches qui peut être facilement comprise et où il est évident de réorganiser les commits .
De nouvelles branches peuvent être introduites en insérant des label
commandes et en appelant merge <label>
.
Et une fois que ce mode sera devenu stable et universellement accepté, nous pouvons déprécier l'erreur de conception qui était--preserve-merges
.
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)
rebase --exec
: faire fonctionner avec --rebase-merges
L'idée --exec
est d'ajouter un exec
appel après chacun pick
.
Depuis l'introduction de fixup!
/ s quash!
commits, cette idée a été étendue pour s'appliquer à "pick, éventuellement suivi d'une chaîne fixup / squash", c'est-à-dire qu'un exec ne serait pas inséré entre a pick
et aucune de ses lignes fixup
ou correspondantes
squash
.
L'implémentation actuelle utilise une sale astuce pour y parvenir: elle suppose qu'il n'y a que des commandes pick / fixup / squash, puis
insère les exec
lignes avant tout pick
sauf la première, et ajoute une dernière.
Avec les listes de tâches générées par git rebase --rebase-merges
, cette implémentation simple montre ses problèmes: elle produit exactement la mauvaise chose quand il y en a label
, reset
et les merge
commandes.
Modifions l'implémentation pour faire exactement ce que nous voulons: rechercher des
pick
lignes, ignorer les chaînes de correction / squash, puis insérer la exec
ligne . Faire mousser, rincer, répéter.
Remarque: nous nous efforçons d'insérer avant les lignes de commentaire chaque fois que possible, car les validations vides sont représentées par des lignes de sélection commentées (et nous voulons insérer la ligne d'exécution d'un choix précédent avant une telle ligne, pas après).
Pendant que vous y êtes , ajoutez également des exec
lignes après les merge
commandes, car elles sont similaires dans leur esprit aux pick
commandes: elles ajoutent de nouveaux commits.
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 )
Assurez-vous que refs / réécrit / est per-worktree
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) ajoute refs/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.
- add_per_worktree_entries_to_dir()
est mis à jour pour s'assurer que la liste des références examine l'arborescence par travail refs/rewritten/
plutôt que celle par repo.
common_list[]
est mis à jour afin de git_path()
renvoyer l'emplacement correct. Cela inclut " rev-parse --git-path
".
Ce gâchis est créé par moi.
J'ai commencé à essayer de le réparer avec l'introduction de l' refs/worktree,
endroit où toutes les références seront par arbre de travail sans traitements spéciaux.
Des références malheureuses / réécrites sont venues avant refs / worktree donc c'est tout ce que nous pouvons faire.
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 )
path.c
: n'appelle pas la match
fonction sans valeur danstrie_find()
Signé par: SZEDER Gábor
'logs / refs' n'est pas un chemin spécifique à l'arborescence de travail, mais depuis la validation b9317d55a3 (assurez-vous que refs / réécrit / est par arbre de travail, 2019-03-07, v2.22.0-rc0) ' git rev-parse --git-path
' a renvoyé un faux chemin si un ' /
' de fin est présent:
$ git -C WT/ rev-parse --git-path logs/refs --git-path logs/refs/
/home/szeder/src/git/.git/logs/refs
/home/szeder/src/git/.git/worktrees/WT/logs/refs/
Nous utilisons une trie
structure de données pour décider efficacement si un chemin appartient au répertoire commun ou s'il est spécifique à l'arborescence.
En l' occurrence, b9317d55a3 a déclenché un bogue aussi ancien que l' trie
implémentation elle-même, ajouté dans 4e09cf2acf (" path
: optimisation de la vérification du répertoire commun", 2015-08-31, Git v2.7.0-rc0 - fusion répertoriée dans le lot # 2 ).
Selon le commentaire décrivant trie_find()
, il ne devrait appeler la fonction de correspondance donnée 'fn' que pour un "préfixe terminé par / / ou - \ 0 de la clé pour laquelle le trie contient une valeur".
Ce n'est pas vrai: il y a trois endroits où trie_find () appelle la fonction de correspondance, mais l'un d'eux manque la vérification de l'existence de la valeur.
b9317d55a3 a ajouté deux nouvelles clés à trie
:
- '
logs/refs/rewritten
', et
- '
logs/refs/worktree
', à côté de l'existant ' logs/refs/bisect
'.
Cela a abouti à un trie
nœud avec le chemin d'accès ' logs/refs/
', qui n'existait pas auparavant et auquel aucune valeur n'est attachée.
Une requête pour ' logs/refs/
' trouve ce nœud, puis frappe ce site d'appel de la match
fonction qui ne vérifie pas l'existence de la valeur, et appelle ainsi la match
fonction avec NULL
comme valeur.
Lorsque la match
fonction check_common()
est invoquée avec une NULL
valeur, elle retourne 0, ce qui indique que le chemin interrogé n'appartient pas au répertoire commun, résultant finalement le faux chemin indiqué ci-dessus.
Ajoutez la condition manquante à trie_find()
afin qu'elle n'invoque jamais la fonction de correspondance avec une valeur inexistante.
check_common()
n'aura alors plus à vérifier qu'elle a obtenu une valeur non NULL, donc supprimez cette condition.
Je crois qu'il n'y a aucun autre chemin qui pourrait provoquer une sortie bidon similaire.
AFAICT la seule autre clé entraînant l'appel de la fonction de correspondance avec une NULL
valeur est ' co
' (en raison des touches ' common
' et ' config
').
Cependant, comme ils ne se trouvent pas dans un répertoire qui appartient au répertoire commun, le chemin spécifique à l'arborescence de travail résultant est attendu.
git --rebase-merges
finira par remplacer l'anciengit --preserve-merges
. Voir ma réponse ci