web-dev-qa-db-fra.com

Autoriser la fusion d'histoires non liées dans git rebase

Lorsque vous souhaitez rebaser une branche en conservant les validations de fusion, vous passez le --preserve-merges drapeau. Lorsque vous fusionnez un historique non lié dans git, vous devez passer le --allow-unrelated-histories drapeau.

Si vous faites git rebase --preserve-merges lorsqu'une fusion existante provient d'un historique indépendant, elle échoue:

fatal: refus de fusionner des histoires indépendantes

Si tu essayes git rebase --preserve-merges --allow-unrelated-histories il échoue avec:

erreur: option inconnue 'allow-unrelated-histories'

Existe-t-il un autre moyen de dire à rebase d'autoriser la fusion?


Edit: voici une reproduction minimale: https://github.com/vossad01/rebase-unrelated-merge-reproduction

Pour reproduire l'extraction master puis exécutez:

git rebase --preserve-merges --onto Origin/a-prime HEAD~2
17
vossad01

La méthode de la force brute consiste à forcer une racine commune - puisque vous essayez de rebaser des racines, sans historique de contenu, effectuez un commit nonce vide et dites à git que c'est le parent des historiques que vous fusionnez:

git rev-list --all --max-parents=0 \
| awk '{print $0,empty}' empty=`:|git mktree|xargs git commit-tree` \
> .git/info/grafts
git rebase here
rm .git/info/grafts
6
jthill

Quand git rebase échoue lors de la fusion, il n'interrompt pas le rebase, vous avez donc la possibilité d'intervenir manuellement.

Si vous souhaitez résoudre ce problème à la main, vous pouvez effectuer la fusion comme suit:

git merge --allow-unrelated ORIGINAL_BRANCH_THAT_WAS_MERGED --no-commit
git commit -C ORIGINAL_MERGE_COMMIT
git rebase --continue

Idéalement, il y aurait un moyen pour Git de gérer cela sans intervention manuelle.

9
vossad01

Pour reproduire le checkout master puis exécutez:

git rebase --preserve-merges --onto Origin/a-prime HEAD~2 -i

Les documents git-rebase disent de ne pas combiner -i et --preserve-merges.

[--preserve-merges] utilise la machine --interactive en interne, mais la combiner explicitement avec l'option --interactive n'est généralement pas une bonne idée à moins que vous sachiez ce que vous faites (voir BOGUES ci-dessous).

Mais même sans le -i il échoue toujours avec fatal: refusing to merge unrelated histories.

Une partie du problème est HEAD~2 est un ancêtre direct de Origin/a-prime. Votre repo de test ressemble à ceci:

1 [master]
|
2
|\
| |  3 [Origin/a-prime]
| |  |
| 4 / [Origin/b]
|  /
| /
|/
5 [Origin/a]

HEAD~2 sur master vaut 5. Origin/a-prime est 3. Votre commande équivaut à:

git rebase -p --onto 3 5

5 est un ancêtre direct de 3, de sorte que la commande n'a pas beaucoup de sens. Si ça marche, ça va faire quelque chose de bizarre.


les cas que j'ai rencontrés à quelques reprises récemment ont concerné le déplacement de la documentation d'un projet de GitHub Wiki vers GitHub Pages (lorsque le site Web existe déjà).

Il s'agit d'une utilisation inappropriée de rebase. Rebase transforme les histoires parallèles en histoires linéaires, prétendant fondamentalement qu'un ensemble de modifications a été effectué au-dessus d'un autre ensemble tout au long. C'est bon pour des choses comme la mise à jour des branches de fonctionnalités pendant qu'elles sont en cours de traitement, la comptabilité et la révision sont plus faciles si vous n'avez pas un tas de validations de fusion intermédiaires qui ne font que mettre à jour la branche. Ce ne sont que du bruit pour quiconque lit le code et valide l'historique à l'avenir.

Mais lorsque vous avez deux histoires vraiment divergentes, il est préférable de les laisser comme des histoires divergentes. Leur fusion raconte la bonne histoire: le site Web et les documents ont été développés séparément, mais ensuite réunis en une seule unité.

1 - 3 - 5
         \
  2 - 4 - 6 - 7 - 8 [master]

Vous pouvez les regarder séparément dans l'ordre topologique (8, 7, 6, 5, 3, 1, 4, 2) en utilisant git log --topo-order ou vous pouvez les regarder entrelacées par ordre de date (8, 7, 6, 5, 4, 3, 2, 1), le git log défaut. Un visualiseur d'historique comme gitk ou GitX affichera les deux commandes simultanément.

Repenser l'un au-dessus de l'autre est un mensonge: nous avons travaillé sur le site, puis nous avons travaillé sur la documentation, puis à un moment donné (un point que vous devrez trouver) et pour une raison quelconque, nous avons travaillé sur le site et documentation ensemble.

1 - 3 - 5 - 2 - 4 - 6 - 7 - 8 [master]

Cela perd des informations vitales et rend perplexe pourquoi certains changements ont été rendus plus difficiles à l'avenir.

Faites une fusion, c'est la bonne chose.

1
Schwern