Étant donné que le branchement est bon marché avec Git, pourquoi ne pas extraire une copie et vous n'avez donc pas besoin de faire un essai à sec? Vous pouvez simplement jeter la copie par la suite.
C'est très bien, mais cela modifiera toujours votre copie de travail. Si votre dépôt est un serveur Web en direct, vous pouvez alors servir des fichiers avec des conflits.
dave1010
21
Vous ne pouvez pas vraiment faire une fusion sans affecter la copie de travail.
mipadi
55
C'est vrai, mais quelque chose comme git merge --only-if-there-wont-be-any-conflictsou git diff --show-conflicts <commit>serait vraiment pratique. Dommage que ce ne soit pas encore possible, ou manque-t-il quelque chose?
dave1010
344
@ dave1010 Vous ne devriez jamais gérer les fusions sur un serveur Web en direct !!! C'est à ça que sert votre box de développement! Corrigez la branche "prod", puis poussez-la vers le vrai serveur Web.
jpswain
52
Si vous travaillez sur un serveur live / production, vous ne voulez jamais rien faire d'autre git pull --ff-only!
ThiefMaster
237
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:
Récupérez la télécommande dans votre référentiel. Par exemple:
git fetch origin master
Exécutez git merge-tree: 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-treeexé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.
Cette réponse est bien sous-estimée, à mon humble avis, car c'est une solution propre sans toucher à la copie de travail ou à l'index.
sschuberth
23
BTW, les étapes 2 et 3 peuvent être fusionnées en une seule étape, en utilisant l'opérateur backtick de la console Linux, qui évalue sur place son contenu:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g
15
Ajoutez à [alias] dans .gitconfig: dry = "! F () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "#vérifiez comment se fera la fusion de dev dans master: git dry dev master
Noel
8
Ma nouvelle ligne GIT fav: tout git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"simplement génial! +100
Rudie
4
En testant cela, j'ai trouvé que la fusion des drapeaux «changé dans les deux» fusionne lorsque les deux branches modifient le même fichier, même si elles n'entraînent pas de conflit de fusion. Pour identifier uniquement les conflits réels, j'ai trouvé nécessaire de grep pour le balisage de conflit qui commence comme ceci +<<<<<<< .ourgrep -q '^+<* \.our$'
Guy
55
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.
Fusionner le pré-master en master OR
Fusionner toutes les branches libérées par wannabe en master
Quoi qu'il en soit, je suivrais les conseils de @ orange80.
J'aime la solution @akostajti, mais c'est encore une autre option sous-estimée. En fait, je préfère être défensif et créer une nouvelle branche temporaire (bien sûr uniquement lorsque j'attends des conflits, sinon ce sera une surpuissance), et si quelque chose ne va pas, supprimez-le simplement.
jakub.g
1
ne sais pas si c'est une solution "sale" ou pas, mais ça fait vraiment l'affaire. Je l'aime! (Y)
sara
3
Cela devrait être la solution acceptée, imo. C'est rapide, facile, sûr, réversible, intuitif et tant qu'il n'y aura pas de changements non validés avant de commencer, cela n'aura aucun effet secondaire.
Bob Ray
3
Cette solution vous indique que vous ne comprenez pas comment fonctionne git. Les branches ne sont que des pointeurs et vous créez uniquement un pointeur redondant. Vous avez un mauvais pressentiment que vous pouvez en quelque sorte blesser la fusion de votre succursale, mais vous ne pouvez pas. Vous pouvez toujours le faire en git merge --abortcas de conflit, en git reset --hard HEAD~1cas 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.
Thibault D.
@ thibault-d Réfléchissez à la complexité de la solution lorsque vous ne commencez pas avec une branche propre. git merge --no-commitn'interrompra pas une fusion si elle peut être transmise rapidement. git merge --abortne fonctionne pas s'il a été fusionné. Si vous voulez écrire cela sous forme de script, c'est gênant, car git mergeil 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.
Erik Aronesty
47
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 resetprécède)
Vérifier simplement si une fusion sera rapide (FF) est une question de vérifier la liste git branch --contains HEADou même plus directement, utilisez simplementgit merge --ff-only
Brian Phillips
7
git reset --hard est l'une des rares commandes de suppression d'informations sans suppression de git, elle doit donc être utilisée avec une extrême prudence. En tant que tel, -1
Kzqai
8
@Tchalvak il y a toujours reflog.
Kissaki
3
--dry-runne "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?
Rudie
3
que diriez-vous git stash; git reset --hard? @BrianPhillips
Code Whisperer
41
J'ai fait un alias pour faire ça et ça marche comme un charme, je fais ça:
Idée intéressante. Comment pourrais-je regarder cette sortie et déterminer si la fusion va fonctionner ou non?
MatrixFrog
6
Cela ne vous dira pas si des conflits se produiront ... mais cela vous donnera une idée générale de ce qui se passera si vous faites un pull / merge.
timh
10
Cela ne vous indiquera que la différence entre les deux branches, il ne vous dira pas quel sera le résultat de la fusion. Il s'agit d'une distinction importante car la fusion entraînera dans certains cas automatiquement des modifications de différentes branches selon le moment où elles ont été validées. Donc, en substance, faire un diff peut vous faire penser que certaines de vos modifications seront annulées alors qu'en réalité, le processus de fusion prendra automatiquement les modifications les plus récentes par rapport aux anciennes. J'espère que cela a du sens.
Markquezada
3
Pour s'appuyer sur le commentaire de @ mirthlab, il y aura une différence significative entre diff et la fusion si quelqu'un a précédemment effectué une fusion avec la stratégie de fusion «la nôtre» (ou d'autres corrections de fusion manuelles); le diff vous montrera également les différences qui sont déjà comptées comme "fusionnées".
Tao
21
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 -pparamètre, vous obtiendrez également le texte complet du patch, exactement comme si vous faisiez un diff git sur chaque fichier modifié.
Vous pourriez rendre cela un peu plus clair en ajoutant quoi masteret originfaire dans les options de ligne de commande, et qu'en est-il si je suis par exemple sur un local branch1et que je veux faire request-pullsur une branche de fonctionnalité locale branch2? Ai-je encore besoin origin? Bien sûr, on peut toujours lire la documentation.
Ela782
Malheureusement, cette commande ne fonctionne que si Rev # 2 est un nom de branche, elle ne fonctionne pas pour les hachages: /
Jared Grubb
20
Je suis surpris que personne n'ait encore suggéré d'utiliser des correctifs.
Imaginons que vous souhaitiez tester une fusion depuis your_branchdans master(je suppose que vous avez mastervérifié):
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.
Cette méthode est la réponse acceptée à cette question et il y a quelques mises en garde dans les commentaires tels que "git n'a pas pu utiliser la stratégie de fusion" récursive "" et "le fichier patch donne une erreur pour les nouveaux fichiers". Sinon, ça semble super.
neno
1
Une façon plus courte sans créer un fichier correctif temporaire: git diff master your_branch | git apply --check.
ks1322
9
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).
Nettoyer copie peut être obtenue avec 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).
2017 ADTC
8
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.
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
Cela fera la fusion si cela peut être fait avec une avance rapide qui n'est pas ce que je voulais dans la question d'origine. Je pense que la réponse acceptée a l'autre moitié qui le corrige.
Otto
Vraiment cependant, les invites de fantaisie git évitent le besoin que j'ai pour ce genre de chose.
Otto
2
Ce n'est pas vraiment pareil. Quitter avec un état différent de zéro car la fusion ne peut pas être résolue car l'avance rapide ne signifie pas qu'il y a des conflits . Cela signifie simplement que l'histoire a divergé et qu'un commit de fusion est nécessaire.
2017 ADTC
7
J'utilise git log pour voir ce qui a changé sur une branche de fonctionnalité de la branche principale
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.
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
Réponses:
Comme indiqué précédemment, passez le
--no-commit
drapeau, mais pour éviter une validation rapide, passez également--no-ff
, comme ceci:Pour examiner les modifications par étapes:
Et vous pouvez annuler la fusion, même s'il s'agit d'une fusion à avance rapide:
la source
git merge --only-if-there-wont-be-any-conflicts
ougit 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.la source
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.
la source
git merge --abort
cas de conflit, engit reset --hard HEAD~1
cas de fusion ougit 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, cargit 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:
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)la source
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
? @BrianPhillipsJ'ai fait un alias pour faire ça et ça marche comme un charme, je fais ça:
Maintenant j'appelle
Pour savoir s'il y a des conflits.
la source
Il suffit de comparer votre branche actuelle à la branche distante, cela vous dira ce qui va changer lorsque vous effectuez un pull / merge.
la source
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
vous montrera un résumé de ce qui se passerait (sans rien faire):
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é.la source
master
etorigin
faire dans les options de ligne de commande, et qu'en est-il si je suis par exemple sur un localbranch1
et que je veux fairerequest-pull
sur une branche de fonctionnalité localebranch2
? Ai-je encore besoinorigin
? 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
dansmaster
(je suppose que vous avezmaster
vérifié):Cela devrait faire l'affaire.
Si vous obtenez des erreurs comme
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:
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.
la source
git diff master your_branch | git apply --check
.Cela pourrait être intéressant: De la documentation:
Mais vous pouvez aussi le faire de manière naïve (mais lente):
(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).
la source
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.
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:la source
J'utilise git log pour voir ce qui a changé sur une branche de fonctionnalité de la branche principale
par exemple - pour voir les validations dans une branche de fonctionnalité qui a / n'a pas été fusionnée avec master:
la source
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.
la source
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.
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
la source
Faites une copie temporaire de votre copie de travail, puis fusionnez-la et différez les deux.
la source