Je ne veux pas d'outil de fusion visuelle, et je ne veux pas non plus devoir vier le fichier en conflit et choisir manuellement entre HEAD (le mien) et le changement importé (le leur). La plupart du temps, je veux tous leurs changements ou tous les miens. Généralement, c'est parce que mon changement est arrivé en amont et qu'il me revient par traction, mais peut être légèrement modifié à divers endroits.
Existe-t-il un outil en ligne de commande permettant de supprimer les marqueurs de conflit et de choisir toutes les méthodes en fonction de mon choix? Ou un ensemble de commandes git que je peux me nommer pour faire chacune.
# accept mine
alias am="some_sequence;of;commands"
alias at="some_other_sequence;of;commands"
Faire cela est plutôt ennuyant. Pour 'accepter le mien' j'ai essayé:
randy@Sabotage ~/linus $ git merge test-branch
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
Automatic merge failed; fix conflicts and then commit the result.
randy@Sabotage ~/linus $ git checkout Makefile
error: path 'Makefile' is unmerged
andy@Sabotage ~/linus $ git reset --hard HEAD Makefile
fatal: Cannot do hard reset with paths.
Comment suis-je supposé me débarrasser de ces marqueurs de changement?
Je peux faire:
git reset HEAD Makefile; rm Makefile; git checkout Makefile
Mais cela semble plutôt rond, il doit y avoir un meilleur moyen. Et à ce stade, je ne sais pas si git pense même que la fusion a eu lieu, alors je ne pense pas que cela fonctionne nécessairement.
Aller de l’autre côté, faire "accepter les leurs" est également désordonné. La seule façon de le comprendre est de faire:
git show test-branch:Makefile > Makefile; git add Makefile;
Cela me donne également un message de commit gâché, qui contient Conflicts: Makefile dedans deux fois.
Quelqu'un peut-il s'il vous plaît indiquer comment faire les deux actions ci-dessus d'une manière plus simple? Merci
La solution est très simple. git checkout <filename>
essaie d'extraire le fichier de l'index, et échoue donc lors de la fusion.
Ce que vous devez faire est (c.-à-d. Commander a commit):
Pour commander votre propre version vous pouvez utiliser un de:
git checkout HEAD -- <filename>
ou
git checkout --ours -- <filename>
ou
git show :2:<filename> > <filename> # (stage 2 is ours)
Pour acheter l'autre version vous pouvez utiliser l'un de:
git checkout test-branch -- <filename>
ou
git checkout --theirs -- <filename>
ou
git show :3:<filename> > <filename> # (stage 3 is theirs)
Vous devez également exécuter 'add' pour le marquer comme résolu:
git add <filename>
Essaye ça:
Pour accepter leurs modifications: git merge --strategy-option theirs
Pour accepter le vôtre: git merge --strategy-option ours
Sur la base de la réponse de Jakub, vous pouvez configurer les alias git suivants pour plus de commodité:
accept-ours = "!f() { git checkout --ours -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
accept-theirs = "!f() { git checkout --theirs -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
Ils prennent éventuellement un ou plusieurs chemins de fichiers à résoudre et résolvent par défaut à tout résoudre dans le répertoire en cours si aucun n’est indiqué.
Ajoutez-les à la section [alias]
de votre ~/.gitconfig
ou exécutez
git config --global alias.accept-ours '!f() { git checkout --ours -- "${@:-.}"; git add -u "${@:-.}"; }; f'
git config --global alias.accept-theirs '!f() { git checkout --theirs -- "${@:-.}"; git add -u "${@:-.}"; }; f'
D'après la réponse de kynan, voici les mêmes alias, modifiés pour pouvoir gérer les espaces et les tirets initiaux dans les noms de fichiers:
accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f"
accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"
La situation idéale pour résoudre les conflits est lorsque vous savez à l'avance quelle méthode vous souhaitez résoudre et que vous pouvez passer les options de stratégie de fusion récursive _-Xours
_ ou _-Xtheirs
_. En dehors de cela, je peux voir trois scénarios:
Pour résoudre ces trois scénarios, vous pouvez ajouter les lignes suivantes à votre fichier _.gitconfig
_ (ou équivalent):
_[merge]
conflictstyle = diff3
[mergetool.getours]
cmd = git-checkout --ours ${MERGED}
trustExitCode = true
[mergetool.mergeours]
cmd = git-merge-file --ours ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
trustExitCode = true
[mergetool.keepours]
cmd = sed -I '' -e '/^<<<<<<</d' -e '/^|||||||/,/^>>>>>>>/d' ${MERGED}
trustExitCode = true
[mergetool.gettheirs]
cmd = git-checkout --theirs ${MERGED}
trustExitCode = true
[mergetool.mergetheirs]
cmd = git-merge-file --theirs ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
trustExitCode = true
[mergetool.keeptheirs]
cmd = sed -I '' -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' ${MERGED}
trustExitCode = true
_
L'outil get(ours|theirs)
ne conserve que la version respective du fichier et supprime toutes les modifications de l'autre version (de sorte qu'aucune fusion ne se produit).
L'outil merge(ours|theirs)
répète la fusion à trois voies à partir des versions locale, de base et distante du fichier, en choisissant de résoudre les conflits dans la direction indiquée. Cela comporte certaines réserves, notamment: il ignore les options diff qui ont été transmises à la commande de fusion (telles que la gestion des algorithmes et des espaces); fusionne proprement des fichiers d'origine (de sorte que toute modification manuelle du fichier est supprimée, ce qui peut être bon ou mauvais); et a l’avantage de ne pas pouvoir être confondu avec les marqueurs diff supposés être dans le fichier.
L'outil keep(ours|theirs)
édite simplement les marqueurs diff et les sections fermées, en les détectant par une expression régulière. Cela présente l'avantage de préserver les options de diff de la commande de fusion et de vous permettre de résoudre certains conflits à la main, puis de résoudre automatiquement le reste. L'inconvénient est que s'il y a d'autres marqueurs de conflit dans le fichier, cela pourrait être confus.
Ceux-ci sont tous utilisés en exécutant git mergetool -t (get|merge|keep)(ours|theirs) [<filename>]
où, si _<filename>
_ n'est pas fourni, il traite tous les fichiers en conflit.
En règle générale, à supposer que vous sachiez qu'il n'y a pas de marqueur diff pour confondre l'expression régulière, les variantes _keep*
_ de la commande sont les plus puissantes. Si vous laissez l'option _mergetool.keepBackup
_ non définie ou true, après la fusion, vous pouvez comparer le fichier _*.orig
_ au résultat de la fusion afin de vérifier sa pertinence. Par exemple, je lance ce qui suit après le mergetool
juste pour vérifier les modifications avant de valider:
_for f in `find . -name '*.orig'`; do vimdiff $f ${f%.orig}; done
_
Note: Si le _merge.conflictstyle
_ n'est pas _diff3
_, alors le modèle _/^|||||||/
_ dans la règle sed
doit être _/^=======/
_.