J'ai eu une chose intéressante en utilisant git, me demandant si quelqu'un pouvait me l'expliquer afin que je puisse mieux comprendre.
Lors d'une fusion de plusieurs branches (A, B),
git merge A B
échoue en tant qu'avance non rapide, tandis que
git merge B A
a bien fonctionné. Pourquoi serait-ce?
Supposons que A est un strict, enfant direct de la branche courante. Supposons ensuite que B est un enfant strict et direct de A .
La fusion de poulpe, qui traite les têtes données comme arguments de gauche à droite , incrémentalement par rapport à l'arbre, mais indépendamment par rapport à l'index réussit sans conflit s'il essaie d'appliquer B puis A, mais rencontre un conflit s'il effectue la conversion.
Selon le git-merge
manuel, section MERGE STRATEGIES:
octopus
This resolves cases with more than two heads, but refuses to do a
complex merge that needs manual resolution.
Par exemple:
~ $ git init testdir && cd testdir && echo "This is C" > myfile
Initialized empty Git repository in /home/huitseeker/testdir/.git/
~/testdir $ git add myfile && git commit -m "C"
[master (root-commit) f0c8c82] C
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 myfile
~/testdir(master) $ git checkout -b "A" && echo "This is A1" > myfile
Switched to a new branch 'A'
~/testdir(A) $ git commit -m "A1" myfile
[A ac5b51c] A1
1 files changed, 1 insertions(+), 1 deletions(-)
~/testdir(A) $ git checkout -b "B" && echo "This is B1" >> myfile
Switched to a new branch 'B'
~/testdir(B) $ git commit -m "B1" myfile
[B 5bc838c] B1
1 files changed, 1 insertions(+), 0 deletions(-)
~/testdir(B) $ git checkout master
Switched to branch 'master'
~/testdir(master) $ git merge B A
Fast-forwarding to: B
Already up-to-date with A
Merge made by octopus.
myfile | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
~/testdir(master) $ git reset --hard HEAD^^^
HEAD is now at f0c8c82 C
~/testdir(master) $ git merge A B
Fast-forwarding to: A
Fast-forwarding to: B
error: Entry 'myfile' would be overwritten by merge. Cannot merge.
Merge with strategy octopus failed.
~/testdir(master) $ cat myfile
This is A1
En effet, lors d'une avance rapide vers A, l'étiquette de maître n'a pas été poussée en avant, contrairement à l'arborescence.
~/testdir(master) $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: myfile
#
Si, en regardant le code de ce que fait la fusion de poulpe, j'exécute ceci manuellement (regardez ci-dessus pour les hachages):
~/testdir(master) $ git reset --hard f0c8c82
HEAD is now at f0c8c82 C
~/testdir(master) $ git read-tree -u -m f0c8c82 ac5b51c
~/testdir(master) $ git read-tree -u -m f0c8c82 5bc838c
error: Entry 'myfile' would be overwritten by merge. Cannot merge.
Dans l'autre sens (merge B A
), maintenant, si vous regardez à nouveau le code de fusion-octopus, il essaie de détecter que la branche que nous essayons d'ajouter est déjà dans l'arborescence (deuxième case
du for
boucle). En effet, à la fusion de A, il voit que ac5b51c (alias la tête de A) est l'ancêtre commun de A et B, et abandonne sans faire le second read-tree
.
Ce comportement est cohérent avec la nouvelle version de git: bien que j'aie signalé la v.1.3.1, cela se produit toujours avec ma version.
~/testdir(master) $ git --version
git version 1.7.5.4
tl; dr: vous voulez que vos branches de fusion de poulpe touchent des fichiers distincts