Quelle est la différence entre "git merge" et " git merge --no-ff`?
5 réponses
le drapeau --no-ff
empêche git merge
d'exécuter un "fast-forward" s'il détecte que votre courant HEAD
est un ancêtre de la propagation que vous essayez de fusionner. Un fast-forward est quand, au lieu de construire une commit de fusion, git déplace juste votre pointeur de branche pour pointer vers la commit entrante. Cela se produit souvent quand on fait un git pull
sans aucun changement local.
cependant, de temps en temps vous voulez empêcher ce comportement de se produire, généralement parce que vous voulez maintenir une topologie de branche spécifique (par exemple, vous fusionnez dans une branche de sujet et vous voulez vous assurer qu'il ressemble de cette façon lors de la lecture de l'histoire). Pour ce faire, vous pouvez passer le drapeau --no-ff
et git merge
will toujours construire une fusion au lieu de fast-forwarding.
de Même, si vous voulez exécuter un git pull
ou utiliser git merge
afin explicitement avance rapide, et vous voulez caution si elle ne peut pas accélérer, alors vous pouvez utiliser le drapeau --ff-only
. De cette façon, vous pouvez régulièrement faire quelque chose comme git pull --ff-only
sans penser, et puis si elle se trompe, vous pouvez revenir en arrière et décider si vous voulez fusionner ou rebase.
réponse graphique à cette question
Ici est un site avec une explication claire et l'illustration graphique de l'utilisation de git merge --no-ff :
Jusqu'à ce que je vois ça, j'étais complètement perdu avec git. L'utilisation de -- Non-ff permet à quelqu'un qui passe en revue l'histoire de voir la branche que vous avez cochée à travailler. (ce lien pointe vers l'outil de visualisation "réseau" de github) et voici une autre grande référence avec des illustrations. Cette référence complète bien la première en mettant davantage l'accent sur les personnes moins familiarisées avec le git.
infos de Base pour les newbs comme moi
si vous êtes comme moi, et non pas un gourou, ma réponse ici décrit la manipulation de la suppression de fichiers du tracking de git sans les supprimer du système de fichiers local, ce qui semble mal documenté mais se produit souvent. Une autre situation newb est obtenir le code actuel , qui parvient toujours à m'échapper.
Exemple De Flux De Travail
j'ai mis à jour un paquet sur mon site et a dû revenir à mes notes pour voir mon travail; j'ai pensé utile d'ajouter un exemple de cette réponse.
mon workflow de commandes git:
git checkout -b contact-form
(do your work on "contact-form")
git status
git commit -am "updated form in contact module"
git checkout master
git merge --no-ff contact-form
git branch -d contact-form
git push origin master
ci-dessous: usage actuel, y compris les explications.
Note: la sortie ci-dessous est ébréchée; git est assez verbeux.
$ git status
# On branch master
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: ecc/Desktop.php
# modified: ecc/Mobile.php
# deleted: ecc/ecc-config.php
# modified: ecc/readme.txt
# modified: ecc/test.php
# deleted: passthru-adapter.igs
# deleted: shop/mickey/index.php
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# ecc/upgrade.php
# ecc/webgility-config.php
# ecc/webgility-config.php.bak
# ecc/webgility-magento.php
noter 3 choses d'en haut:
1) dans la sortie, vous pouvez voir les changements de la mise à niveau du paquet ECC, y compris l'ajout de nouveaux fichiers.
2) notez aussi qu'il y a deux fichiers (pas dans le dossier /ecc
) que j'ai supprimés indépendamment de ce changement. Au lieu de confondre ces suppressions de fichiers avec ecc
, je ferai une branche différente cleanup
plus tard pour refléter la suppression de ces fichiers.
3) je n'ai pas suivi mon travail! J'ai oublié git pendant que j'essayais de faire fonctionner l'ecc.
ci-dessous: plutôt que de faire le tout compris git commit -am "updated ecc package"
Je normalement je voulais juste ajouter les fichiers dans le dossier /ecc
. Ces fichiers supprimés ne faisaient pas spécifiquement partie de mon git add
, mais parce qu'ils étaient déjà traqués dans git, je dois les supprimer de la propagation de cette branche:
$ git checkout -b ecc
$ git add ecc/*
$ git reset HEAD passthru-adapter.igs
$ git reset HEAD shop/mickey/index.php
Unstaged changes after reset:
M passthru-adapter.igs
M shop/mickey/index.php
$ git commit -m "Webgility ecc desktop connector files; integrates with Quickbooks"
$ git checkout master
D passthru-adapter.igs
D shop/mickey/index.php
Switched to branch 'master'
$ git merge --no-ff ecc
$ git branch -d ecc
Deleted branch ecc (was 98269a2).
$ git push origin master
Counting objects: 22, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (14/14), 59.00 KiB, done.
Total 14 (delta 10), reused 0 (delta 0)
To git@github.com:me/mywebsite.git
8a0d9ec..333eff5 master -> master
Script pour l'automatisation de ce qui précède
ayant utilisé ce processus plus de 10 fois dans la journée, j'ai pris à l'écriture de lot scripts pour exécuter les commandes, donc j'ai fait un script presque approprié git_update.sh <branch> <"commit message">
pour faire les étapes ci-dessus. Voici la source Gist pour ce script.
au lieu de git commit -am
je sélectionne des fichiers de la liste" modifiée "produite par git status
et puis je les colle dans ce script. Cela s'est produit parce que j'ai fait des douzaines de modifications, mais je voulais des noms de branches variés pour aider à grouper les changements.
l'option --no-ff
garantit qu'une fusion rapide ne se produira pas, et que un nouvel objet commit sera toujours créé . Cela peut être souhaitable si vous voulez git pour conserver un historique de branches.
Dans l'image ci-dessus, le côté gauche est un exemple de l'histoire de git après avoir utilisé git merge --no-ff
et le côté droit est un exemple d'utilisation de git merge
où une fusion ff était possible.
EDIT : une version précédente de cette image indiquait seulement un parent unique pour la propagation de la fusion. Fusion s'engage plusieurs parent s'engage à qui git utilise pour conserver un historique de la "branche" et de l'origine de la branche. Les liens parents multiples sont surlignés en vert.
C'est une vieille question, et cela est quelque peu subtilement mentionné dans les autres Billets, mais l'explication qui a fait ce clic pour moi est que Non fast forward merges nécessitera une propagation séparée .
- Explicite, non d'avance rapide, de fusion
- Implicite via rebase ou avancer rapidement dans la fusion
- Squash sur la fusion