Question

Lors de la fusion d'une branche de sujet " B " dans " A " En utilisant git merge , il y a des conflits. Je sais que tous les conflits peuvent être résolus en utilisant la version "B".

Je connais l'existence de git merge -s our . Mais ce que je veux, c’est quelque chose comme git merge -s leurs .

Pourquoi ça n'existe pas? Comment puis-je obtenir le même résultat après la fusion en conflit avec les commandes git existantes? ( git checkout tous les fichiers non fusionnés de B)

UPDATE: La "solution" de ne rien supprimer de la branche A (le point de validation de la fusion avec la version B de l’arbre) n’est pas ce que je recherche.

Était-ce utile?

La solution

Ajoutez l'option -X à leur . Par exemple:

git checkout branchA
git merge -X theirs branchB

Tout va fusionner de la manière souhaitée.

La seule chose qui me pose problème, c’est que les fichiers soient supprimés de branchB. Ils apparaissent comme des conflits si quelque chose d'autre que git a été supprimé.

La solution est facile. Il suffit de lancer git rm avec le nom de tous les fichiers supprimés:

git rm {DELETED-FILE-NAME}

Après cela, le -X leurs devrait fonctionner comme prévu.

Bien sûr, la suppression effective avec la commande git rm empêchera le conflit de se produire en premier lieu.

Remarque : une option de formulaire plus long existe également. Pour l'utiliser, remplacez:

-X theirs

avec:

--strategy-option=theirs

Autres conseils

Une solution possible et testée pour la fusion de branchB dans notre branche extraiteA:

# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

Pour l’automatiser, vous pouvez l’envelopper dans un script en utilisant BranchA et BranchB comme arguments.

Cette solution conserve les premier et deuxième parents de la validation de fusion, exactement comme vous le souhaiteriez de git merge -s leur brancheB .

Les anciennes versions de git vous permettaient d'utiliser le "leur" " stratégie de fusion:

git pull --strategy=theirs remote_branch

Mais cela a depuis été supprimé, comme expliqué dans ce message par Junio ??Hamano . (le mainteneur Git). Comme indiqué dans le lien, faites plutôt ceci:

git fetch origin
git reset --hard origin

Attention, cela est différent de la fusion réelle. Votre solution est probablement l'option que vous recherchez réellement.

J'ai utilisé la réponse de Paul Pladijs depuis maintenant. J'ai découvert que vous pouvez faire un "normal". fusion, les conflits se produisent, de sorte que vous

git checkout --theirs <file>

pour résoudre le conflit en utilisant la révision de l’autre branche. Si vous faites cela pour chaque fichier, vous avez le même comportement que celui attendu de

git merge <branch> -s theirs

Quoi qu’il en soit, l’effort dépasse la stratégie de fusion! (Ceci a été testé avec la version 1.8.0 de Git)

Les résultats souhaités ne sont pas tout à fait clairs. Il existe donc une certaine confusion quant au résultat "correct". manière de le faire dans les réponses et leurs commentaires. J'essaie de donner un aperçu et de voir les trois options suivantes:

Essayez de fusionner et d'utiliser B pour les conflits

Ceci n'est pas la "version de leur code pour git merge -s our ". mais la " leur version pour la fusion git -X notre " (qui est l'abréviation de git merge -s récursif -X our ):

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

C’est ce que p.ex. La réponse d’Alan W. Smith le fait.

Utiliser le contenu de B uniquement

Ceci crée une validation de fusion pour les deux branches, mais annule toutes les modifications de brancheA et conserve uniquement le contenu de brancheB .

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB

# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA

# Set branchA to current commit and check it out.
git checkout -B branchA

Notez que la fusion valide le premier parent, à présent, provient de brancheB et que le deuxième ne provient que de brancheA . C'est ce que par exemple La réponse de Gandalf458 le fait.

Utiliser le contenu de B uniquement et conserver l'ordre parent correct

Il s'agit de la version "leur" pour git merge -s our ". Il a le même contenu que dans l'option précédente (c'est-à-dire uniquement celui de branchB ) mais l'ordre des parents est correct, c'est-à-dire que le premier parent provient de branchA et le second de brancheB .

git checkout branchA

# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB

# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB

# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA

# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA

# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

C’est ce que la réponse de Paul Pladijs (sans nécessiter de branche temporaire).

J'ai résolu mon problème en utilisant

git checkout -m old
git checkout -b new B
git merge -s ours old

Si vous vous trouvez sur la branche A:

git merge -s recursive -X theirs B

Testé sur la version 1.7.8 de Git

  

Lors de la fusion d'une branche de sujet " B " dans " A " en utilisant git merge, je rencontre des conflits. Je sais que tous les conflits peuvent être résolus à l'aide de la version "B".

     

Je suis au courant de la fusion de notre société. Mais ce que je veux, c'est quelque chose comme git merge > -s leur.

Je suppose que vous avez créé une branche à partir du maître et que vous souhaitez maintenant fusionner de nouveau dans le maître, en remplaçant les anciens éléments du maître. C'est exactement ce que je voulais faire quand je suis tombé sur ce post.

Faites exactement ce que vous voulez faire, sauf que vous fusionnez d'abord une branche dans l'autre. Je viens de faire cela et cela a très bien fonctionné.

git checkout Branch
git merge master -s ours

Ensuite, passez à la caisse principale et fusionnez-y votre branche (tout ira bien maintenant):

git checkout master
git merge Branch

Vous pouvez effectuer une fusion qui prend seulement de la branche que vous fusionnez

.

git fusionner --strategy = notre ref-à-fusionner

git diff --binary ref-to-be-merged | git apply --reverse --index

git commit --amend

Il n'y aura pas de conflit dans tous les scénarios que je connaisse, vous n'avez pas à créer de branches supplémentaires et cela fonctionne comme un commit de fusion normal.

Cela ne fonctionne pas bien avec les sous-modules cependant.

Voir la réponse largement citée de Junio ??Hamano : si vous envisagez de supprimer le résultat final contenu, supprimez simplement les commits, ou du moins maintenez-le hors de l'histoire principale. Pourquoi gêner tout le monde à l'avenir en lisant des messages de commits qui n'ont rien à offrir?

Mais il y a parfois des exigences administratives, ou peut-être une autre raison. Pour les situations où vous devez vraiment enregistrer des commits qui ne contribuent en rien, vous voulez:

(edit: wow, est-ce que j'ai réussi à me tromper avant? Celui-ci fonctionne.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard
  

Pourquoi n’existe-t-il pas?

Bien que je mentionne dans la commande git permettant de créer une branche semblable à une autre " comment simuler la fusion de git - la leur , notez que Git 2.15 (Q4 2017) est maintenant plus clair:

  

La documentation de ' -X < option > ' pour les fusions était trompeuse.   écrit pour suggérer que " -s leurs " existe, ce qui n'est pas le cas.

Voir commit c25d98b (25 sept. 2017) de Junio ??C Hamano ( gitster ) .
(Fusionné par Junio ??C Hamano - gitster - dans commit 4da3e23 , 28 sept. 2017)

  

fusionner les stratégies: évitez de laisser entendre que " est leur " existe

     

La description de l'option de fusion -Xours a une note entre parenthèses   qui dit aux lecteurs qu'il est très différent de -nos ,   ce qui est correct, mais la description de -Xtheirs qui le suit   dit négligemment "c’est le contraire de notre ", donnant un faux   impression que les lecteurs doivent également être avertis qu'il est très   différent de -s leurs , ce qui en réalité n’existe même pas.

-Xtheirs est une option de stratégie appliquée à la stratégie récursive. Cela signifie que la stratégie récursive fusionnera tout ce qui est en son pouvoir et ne fera que revenir à " le leur ". logique en cas de conflit.

Ce débat sur la pertinence ou non d’une stratégie de fusion pour leur a été récemment rappelé dans ce fil de discussion de septembre 2017 .
Il reconnaît des discussions plus anciennes (2008)

  

En résumé, la discussion précédente peut être résumée comme suit: "nous ne voulons pas de -s leurs " car cela encourage le mauvais flux de travail ".

Il mentionne l'alias:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

Yaroslav Halchenko tente à nouveau de plaider en faveur de cette stratégie, mais Junio ??C. Hamano ajoute :

  

La raison pour laquelle les nôtres et les leurs ne sont pas symétriques est qu’ils sont vous et pas eux --- le contrôle et la propriété de notre histoire et leur histoire ne sont pas symétriques.

     

Une fois que vous décidez que leur historique constitue la ligne principale, vous souhaitez plutôt traiter votre ligne de développement comme une branche secondaire et procéder à une fusion dans cette direction, c'est-à-dire que le premier parent de la fusion résultante est un commit de leur historique. et le deuxième parent est le dernier mauvais de votre histoire. Ainsi, vous finirez par utiliser le code " extraire leur historique & amp; & amp; & amp; fusionner votre historique " à   garder la première parenté sensible.

     

Et à ce moment-là, utilisez " -s our ". n’est plus une solution de contournement faute de " -s leurs ". "    C’est une partie appropriée de la sémantique souhaitée, c’est-à-dire que du point de vue de la ligne historique canonique survivante, vous souhaitez conserver ce qu’elle a fait, en annulant celle de l’autre ligne de l’histoire .

>

Celui-ci utilise une commande de lecture git plumbing, mais permet un flux de travail global plus court.

git checkout <base-branch>

git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit

# Check your work!
git diff <their-branch>

Ceci fusionnera votre newBranch dans la base existante

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

Je pense que ce que vous voulez réellement, c'est:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

Cela semble maladroit, mais cela devrait fonctionner. La seule chose qui me déplaise le plus à propos de cette solution, c’est que l’histoire de git sera confuse ... Mais au moins, l’histoire sera complètement préservée et vous n’aurez pas besoin de faire quelque chose de spécial pour les fichiers supprimés.

L'équivalent (qui conserve l'ordre parent) de "git merge -s leur brancheB"

Avant la fusion:  entrez la description de l'image ici

!!! Assurez-vous d'être en état de propreté !!!

Faites la fusion:

git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command

Qu'est-ce que nous avons fait?  Nous avons créé un nouveau commit dont les deux parents, le nôtre et le leur, et le contenu de ce commit est branchB - le leur

Après la fusion:  entrer la description de l'image ici

Plus précisément:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

Cette réponse a été donnée par Paul Pladijs. Je viens de prendre ses commandes et de faire un alias git pour plus de commodité.

Modifiez votre fichier .gitconfig et ajoutez les éléments suivants:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

Ensuite, vous pouvez "fusionner leurs fusions A". en exécutant:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

Je venais juste de faire cela pour deux référentiels distincts qui partagent un historique commun. J'ai commencé avec:

  • Maître de l'organisation / référentiel1
  • Maître Org / repository2

Je souhaitais que toutes les modifications apportées par maître de référentiel2 soient appliquées à maître de référentiel1 , en acceptant toutes les modifications apportées par référentiel2. En termes de git, cela devrait être une stratégie appelée -s leurs MAIS elle n’existe pas. Soyez prudent, car -X leur porte le même nom que ce que vous voulez, mais PAS le même (il est même indiqué dans la page de manuel).

Pour résoudre ce problème, il fallait aller dans repository2 et créer une nouvelle branche repo1-merge . Dans cette branche, j’ai exécuté git pull git@gitlab.com: Org / repository1 - le nôtre et la fusion s’effectue sans problème. Je le pousse ensuite vers la télécommande.

Ensuite, je retourne à repository1 et crée une nouvelle branche repo2-merge . Dans cette branche, j'exécute git pull git@gitlab.com: Org / repository2 repo1-merge , ce qui entraînera des problèmes.

Enfin, vous devrez soit émettre une demande de fusion dans repository1 pour en faire le nouveau maître, ou simplement le conserver sous forme de branche.

Une façon simple et intuitive (à mon avis) de le faire en deux étapes est

git checkout branchB .
git commit -m "Picked up the content from branchB"

suivi de

git merge -s ours branchB

(qui marque les deux branches comme étant fusionnées)

Le seul inconvénient est qu’il ne supprime pas les fichiers supprimés dans branchB de votre branche actuelle. Un simple diff entre les deux branches indiquera s’il existe de tels fichiers.

Cette approche indique également à partir du journal de révision ce qui a été fait et ce qui était prévu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top