2017-10-01 8 views
0

J'utilise git en créant une série de branches de fonctionnalité, et en les fusionnant au master quand elles ont fini avec git merge --no-ff. Cela crée des validations de fusion vides utiles pour identifier les points de début et de fin des branches de fonction précédentes.Un moyen plus rapide de `git rebase --preserve-merges`

Pour gérer plusieurs branches simultanées, ou même des branches imbriquées, j'utilise rebase. Je ne fusionne jamais en arrière, je rebase toujours mes branches sur les derniers commits, test et finalement fusionne avec --no-ff une fois que tout est fait. Avec les branches imbriquées, je fais la même chose: plusieurs branches sont fusionnées séquentiellement sur la branche principale, qui est elle-même fusionnée au master à la fin. Pour conserver des informations sur les fusions avec des branches imbriquées, j'utilise souvent git rebase --preserve-merges. Cela fait exactement ce que je veux et je n'ai aucun problème avec mon flux de travail.

Mon problème principal avec git est que git rebase --preserve-merges est très lent (prenant parfois environ 2 secondes par commit). Après avoir lu What exactly does git's "rebase --preserve-merges" do (and why?) je réalise que git doit effectuer beaucoup de travail pour préserver les fusions, puisque git doit travailler sur des graphes arbitraires. Ce que je me demandais est ceci: puisque mon flux de travail résulte à peu près en un graphique équivalent à un historique linéaire, est-il possible d'effectuer un git rebase --preserve-merge équivalent d'une manière plus rapide, étant donné que je garantis la "linéarité" de l'histoire avec seule la fusion vide est validée? Cela ne me dérange pas d'utiliser des scripts ou des commandes bizarres, tant que le résultat final est correct.

 A-B-C 
    / \ 
(1)--------D-- master 
    \ 
    \---F-----I-- feature 
     \/\ /
     E G-H 

    A-B-C E G-H 
    / \/\/ \ 
(2)--------D---F-----I-feature 
     master 

tl; dr: Comment transformer (1) en (2) sachant que l'historique sous-jacent est linéaire, donc git rebase --preserve-merges n'a pas à faire autant de travail et le fait vite?

Répondre

0

Vous pourrait être en mesure d'accélérer le tout un peu en le réécrivant à partir d'un script bash à quelque chose de plus intelligent (par exemple, en Python, exécutez git rev-list --parents et de recueillir toute l'information des parents avant de commencer les opérations de copie) , mais fondamentalement c'est juste dur. Comme la réponse dans ce lien d'autres notes en passant, git rebase -p aussi ne pas exactement préserver fusionne autant que recréer eux. Dans le cas général - que je sais que vous ignorez en faveur de cas spéciaux plus limités; Je ne mentionne que ceci pour l'exhaustivité - git rebase -p échoue complètement sur les fusions qui ont eu des options spéciales ou le traitement appliqué (--no-commit fusionne avec des modifications manuelles pour produire une "fusion maléfique", ou fusionne run avec -X rename-threshold ou -X ours ou similaire), puisque le cas spécial l'information est, en effet, seulement stockée dans l'arbre résultant. Le code de rebasage ne le recherche même pas (cela prendrait beaucoup plus de temps: il faudrait d'abord reproduire la fusion originale juste pour voir si une fusion sans option aurait recréé le résultat original). Tout cela mis à part, la vitesse (ou le manque de vitesse) de ces options dépend de la taille de votre dépôt et de ses fichiers, et si vous utilisez Windows (extrêmement lent) ou un système Unixish (beaucoup plus rapide). Il n'y a aucune raison que je sache que Windows devrait être si terriblement lent pour exécuter des scripts, mais c'est clairement le cas, car les Git continuent de réécrire des choses en C pour les faire fonctionner correctement sur Windows parce que les scripts sont si lents. Par conséquent, si vous effectuez cette opération sous Windows, l'une des manières de l'accélérer est d'arrêter d'utiliser Windows. :-) (Vous pouvez le faire juste pour la durée du rebase lui-même, en utilisant git push et git fetch pour coordonner entre Windows et Linux-ou-peu importe.

+0

Malheureusement je suis sur Ubuntu, donc je ne pense pas que ça dépende de ça. Le dépôt où j'ai eu ce problème en dernier a été utilisé par beaucoup de gens avec une histoire désordonnée, ce qui aurait pu être un facteur dans la lenteur du commandement. Cependant, je ne suis pas d'accord sur le fait que dans mon cas particulier c'est difficile: un simple 'git rebase' le fait correctement très rapidement; ma seule différence serait qu'au lieu de sauter les commits de fusion, il faudrait les copier/recréer. Ça ne devrait pas être si difficile, non? – Svalorzen

+0

Dans un grand dépôt, j'ai vu 'git merge' lui-même prendre 30 minutes. Vraisemblablement, le vôtre n'est pas * gros *, mais répéter une fusion pourrait être le coupable. Comme le rebasage interactif est (ou était surtout, ça commence à changer dans Git) un script shell, vous pouvez le découvrir en mettant le drapeau '-x' et en le regardant fonctionner, pour voir où sont les retards. – torek