Je fusionne dans une branche distante qui peut avoir beaucoup de conflits. Comment puis-je savoir s'il y aura des conflits ou non?
Je ne vois rien comme un --dry-run
sur git-merge
.
Je fusionne dans une branche distante qui peut avoir beaucoup de conflits. Comment puis-je savoir s'il y aura des conflits ou non?
Je ne vois rien comme un --dry-run
sur git-merge
.
Réponses:
Comme indiqué précédemment, passez le --no-commit
drapeau, mais pour éviter une validation rapide, passez également --no-ff
, comme ceci:
$ git merge --no-commit --no-ff $BRANCH
Pour examiner les modifications par étapes:
$ git diff --cached
Et vous pouvez annuler la fusion, même s'il s'agit d'une fusion à avance rapide:
$ git merge --abort
git merge --only-if-there-wont-be-any-conflicts
ou git diff --show-conflicts <commit>
serait vraiment pratique. Dommage que ce ne soit pas encore possible, ou manque-t-il quelque chose?
git pull --ff-only
!
Je viens de mettre en œuvre une méthode qui détecte automatiquement les conflits entre un référentiel et sa télécommande. Cette solution effectue la fusion en mémoire afin qu'elle ne touche pas l'index, ni l'arborescence de travail. Je pense que c'est la façon la plus sûre possible de résoudre ce problème. Voici comment ça fonctionne:
git fetch origin master
git merge-base FETCH_HEAD master
git merge-tree mergebase master FETCH_HEAD
( mergebase est l'identifiant hexadécimal imprimé par la base de fusion à l'étape précédente)Supposons maintenant que vous souhaitiez fusionner le maître distant avec votre maître local, mais vous pouvez utiliser n'importe quelle branche. git merge-tree
exécutera la fusion en mémoire et imprimera le résultat sur la sortie standard. Grep pour le motif <<
ou >>
. Ou vous pouvez imprimer la sortie dans un fichier et vérifier cela. Si vous trouvez une ligne commençant par «changé dans les deux», il y aura très probablement un conflit.
git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"
simplement génial! +100
+<<<<<<< .our
grep -q '^+<* \.our$'
Ma solution brute-force simple à ceci est:
Créer une branche "pré-master" (à partir du master bien sûr)
Fusionnez tout ce que vous voulez dans ce pré-master.
Ensuite, vous pouvez voir comment la fusion s'est produite sans toucher au maître.
Quoi qu'il en soit, je suivrais les conseils de @ orange80.
git merge --abort
cas de conflit, en git reset --hard HEAD~1
cas de fusion ou git reset --hard origin/master
. Créer une autre branche vous donne un sentiment de sécurité mais si vous apprenez comment fonctionne git, vous comprendrez que c'est une peur mal placée. Lorsque le souci est de ne pas modifier la copie de travail, cela n'offre aucune solution.
git merge --no-commit
n'interrompra pas une fusion si elle peut être transmise rapidement. git merge --abort
ne fonctionne pas s'il a été fusionné. Si vous voulez écrire cela sous forme de script, c'est gênant, car git merge
il ne répond pas avec des codes d'erreur suffisamment bons pour expliquer les différents types de conflits. Travailler avec une nouvelle branche empêche un script cassé de laisser votre dépôt dans un état qui nécessite une intervention manuelle. Bien sûr, vous ne pouvez rien perdre. Mais il est plus facile de construire autrement.
Annuler une fusion avec git est si facile que vous ne devriez même pas vous soucier du run à sec:
$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world
EDIT: Comme indiqué dans les commentaires ci-dessous, si vous avez des changements dans votre répertoire de travail ou votre zone de transit, vous voudrez probablement les ranger avant de faire ce qui précède (sinon ils disparaîtront après ce qui git reset
précède)
git branch --contains HEAD
ou même plus directement, utilisez simplementgit merge --ff-only
--dry-run
ne "vérifierait pas simplement si une fusion sera rapide". Cela retournerait la sortie exacte d'une fusion: fichiers, conflits, etc. Si will ff n'est pas vraiment intéressant, n'est-ce pas?
git stash; git reset --hard
? @BrianPhillips
J'ai fait un alias pour faire ça et ça marche comme un charme, je fais ça:
git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '
Maintenant j'appelle
git mergetest <branchname>
Pour savoir s'il y a des conflits.
Il suffit de comparer votre branche actuelle à la branche distante, cela vous dira ce qui va changer lorsque vous effectuez un pull / merge.
#see diff between current master and remote branch
git diff master origin/master
J'utilise la commande request-pull git pour ce faire. Il vous permet de voir tous les changements qui se produiraient lors de la fusion, mais sans rien faire sur vos référentiels locaux ou distants .
Par exemple, imaginez que vous souhaitez fusionner une branche nommée "feature-x" dans votre branche principale
git request-pull master origin feature-x
vous montrera un résumé de ce qui se passerait (sans rien faire):
The following changes since commit fc01dde318:
Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
Adding some layout
Refactoring
ioserver.js | 8 +++---
package.json | 7 +++++-
server.js | 4 +--
layout/ldkdsd.js | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js
Si vous ajoutez le -p
paramètre, vous obtiendrez également le texte complet du patch, exactement comme si vous faisiez un diff git sur chaque fichier modifié.
master
et origin
faire dans les options de ligne de commande, et qu'en est-il si je suis par exemple sur un local branch1
et que je veux faire request-pull
sur une branche de fonctionnalité locale branch2
? Ai-je encore besoin origin
? Bien sûr, on peut toujours lire la documentation.
Je suis surpris que personne n'ait encore suggéré d'utiliser des correctifs.
Imaginons que vous souhaitiez tester une fusion depuis your_branch
dans master
(je suppose que vous avez master
vérifié):
$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch
Cela devrait faire l'affaire.
Si vous obtenez des erreurs comme
error: patch failed: test.txt:1
error: test.txt: patch does not apply
cela signifie que le patch n'a pas réussi et qu'une fusion entraînerait des conflits. Aucune sortie signifie que le patch est propre et vous pourrez facilement fusionner la branche
Notez que cela ne changera pas réellement votre arbre de travail (à part la création du fichier de patch bien sûr, mais vous pouvez le supprimer en toute sécurité par la suite). De la documentation git-apply:
--check
Instead of applying the patch, see if the patch is applicable to the
current working tree and/or the index file and detects errors. Turns
off "apply".
Remarque à tous ceux qui sont plus intelligents / plus expérimentés avec git que moi: faites-le moi savoir si je me trompe ici et cette méthode montre un comportement différent d'une fusion régulière. Il semble étrange qu'au cours des 8 ans et plus que cette question ait existé, personne ne suggérerait cette solution apparemment évidente.
git diff master your_branch | git apply --check
.
Cela pourrait être intéressant: De la documentation:
Si vous avez essayé une fusion qui a entraîné des conflits complexes et que vous souhaitez recommencer, vous pouvez récupérer avec git merge --abort .
Mais vous pouvez aussi le faire de manière naïve (mais lente):
rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)
(Remarque: cela ne fonctionnera pas simplement en clonant vers / tmp, vous auriez besoin d'une copie, afin d'être sûr que les modifications non validées n'entreront pas en conflit).
cp -r repository/.git /tmp/repository/.git
, cd /tmp/repository
, git reset --hard
, git add --all
, git reset --hard
(pour faire bonne mesure), git status
(pour vérifier qu'il est propre).
Je sais que c'est une vieille question, mais c'est la première à apparaître sur une recherche Google.
Git a introduit une option --ff-only lors de la fusion.
De: http://git-scm.com/docs/git-merge
--ff-only
Refusez de fusionner et de quitter avec un état différent de zéro à moins que le HEAD actuel ne soit déjà à jour ou que la fusion puisse être résolue comme une avance rapide.
Cette opération tentera de fusionner et d'avancer rapidement, et si elle ne le peut pas, elle abandonne et vous indique que l'avance rapide n'a pas pu être effectuée, mais laisse votre branche de travail intacte. S'il peut avancer rapidement, il effectuera la fusion sur votre branche de travail. Cette option est également disponible sur git pull
. Ainsi, vous pouvez effectuer les opérations suivantes:
git pull --ff-only origin branchA #See if you can pull down and merge branchA
git merge --ff-only branchA branchB #See if you can merge branchA into branchB
J'utilise git log pour voir ce qui a changé sur une branche de fonctionnalité de la branche principale
git log does_this_branch..contain_this_branch_changes
par exemple - pour voir les validations dans une branche de fonctionnalité qui a / n'a pas été fusionnée avec master:
git log master..feature_branch
Si vous voulez avancer rapidement de B vers A, alors vous devez vous assurer que le journal de git B..A ne vous montre rien, c'est-à-dire que A n'a rien que B n'a pas. Mais même si B..A a quelque chose, vous pourrez peut-être fusionner sans conflits, donc ce qui précède montre deux choses: qu'il y aura une avance rapide, et donc vous n'obtiendrez pas de conflit.
Ma solution est de fusionner en arrière.
Au lieu de fusionner votre branche dans la branche "cible" distante, fusionnez cette branche dans la vôtre.
git checkout my-branch
git merge origin/target-branch
Vous verrez s'il y a des conflits et pouvez planifier comment les résoudre.
Après cela, vous pouvez soit abandonner la fusion via git merge --abort
, ou (s'il n'y a pas eu de conflits et de fusion) revenir à la validation précédente viagit reset --hard HEAD~1