Question Quelle est la différence entre `git merge` et` git merge --no-ff`?


En utilisant gitk log, Je ne pouvais pas faire la différence entre les deux. Comment puis-je observer la différence (avec une commande git ou un outil)?


628
2018-01-30 18:45


origine


Réponses:


le --no-ff drapeau empêche git merge d'exécuter un "avance rapide" s'il détecte que votre courant HEAD est un ancêtre du commit que vous essayez de fusionner. Une avance rapide est quand, au lieu de construire un commit de fusion, git déplace juste votre pointeur de branche pour pointer sur le commit entrant. Cela se produit généralement lors d'un git pull sans aucun changement local.

Cependant, vous souhaitez parfois empêcher ce comportement, généralement parce que vous souhaitez conserver une topologie de branche spécifique (par exemple, vous fusionnez dans une branche de rubrique et vous voulez vous assurer qu'elle ressemble à cela lors de la lecture de l'historique). Pour ce faire, vous pouvez passer le --no-ff drapeau et git merge volonté toujours Construire une fusion au lieu de l'avance rapide.

De même, si vous voulez exécuter un git pull Ou utiliser git merge afin d'avancer explicitement, et vous voulez renflouer s'il ne peut pas avancer rapidement, alors vous pouvez utiliser le --ff-only drapeau. De cette façon, vous pouvez régulièrement faire quelque chose comme git pull --ff-only sans réfléchir, et ensuite, s'il y a des erreurs, vous pouvez revenir en arrière et décider si vous voulez fusionner ou rebaser.


723
2018-01-30 18:51



Réponse graphique à cette question

Voici un site avec une explication claire et une illustration graphique de l'utilisation git merge --no-ff:

difference between git merge --no-ff and git merge

Jusqu'à ce que je voyais ça, j'étais complètement perdu avec git. En utilisant --no-ff permet à quelqu'un d'examiner l'histoire clairement voir la branche que vous avez vérifiée travailler sur. (ce lien pointe vers l'outil de visualisation "réseau" de github) Et voici une autre excellente référence avec des illustrations. Cette référence complète bien le premier avec plus d'attention sur ceux qui connaissent moins git.


Informations de base pour les newbs comme moi

Si vous êtes comme moi, et pas un Git-guru, ma réponse ici décrit la gestion de la suppression de fichiers du suivi de git sans les supprimer du système de fichiers local, ce qui semble peu documenté mais souvent survenu. Une autre situation newb est Obtenir le code actuel, qui parvient toujours à me échapper.


Exemple de flux de travail

J'ai mis à jour un paquet sur mon site Web et j'ai dû revenir à mes notes pour voir mon flux de travail. J'ai trouvé utile d'ajouter un exemple à cette réponse.

Mon flux de travail des 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

Au dessous de: utilisation réelle, y compris les explications.
Note: la sortie ci-dessous est coupé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

Notez 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 également qu'il y a deux fichiers (pas dans le /ecc dossier) J'ai supprimé indépendamment de ce changement. Au lieu de confondre ces suppressions de fichiers avec ecc, Je vais faire un autre cleanupbranche plus tard pour refléter la suppression de ces fichiers.
3) Je n'ai pas suivi mon flux de travail! J'ai oublié git pendant que j'essayais de faire fonctionner ECC encore.

Ci-dessous: plutôt que de faire le tout compris git commit -am "updated ecc package" Je le ferais normalement, je voulais seulement ajouter les fichiers dans le /ecc dossier. Ces fichiers supprimés ne faisaient pas partie de mon git add, mais parce qu'ils ont déjà été suivis dans git, j'ai besoin de les retirer de la validation 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 automatiser le dessus

Ayant utilisé ce processus plus de 10 fois dans une journée, j'ai pris l'habitude d'écrire des scripts batch pour exécuter les commandes, donc j'ai fait un presque-correct git_update.sh <branch> <"commit message"> script pour faire les étapes ci-dessus. Voici la source Gist pour ce script.

Au lieu de git commit -am Je sélectionne les fichiers de la liste "modifiée" produite via git status puis coller ceux dans ce script. Cela est dû au fait que j'ai fait des dizaines de modifications mais que je voulais des noms de branches variés pour aider à regrouper les changements.


733
2018-02-14 00:08



le --no-ff option garantit qu'une fusion avant rapide ne se produira pas, et que un nouvel objet commit sera toujours créé. Cela peut être souhaitable si vous voulez que git conserve un historique des branches d'entités. git merge --no-ff vs git merge Dans l'image ci-dessus, le côté gauche est un exemple de l'histoire git après l'utilisation git merge --no-ff et le côté droit est un exemple d'utilisation git merge où une fusion ff était possible.

MODIFIER: Une version précédente de cette image indiquait un seul parent pour la validation de fusion. Commandes de fusion ont plusieurs commits parent que git utilise pour maintenir un historique de la "branche d'entité" et de la branche d'origine. Les liens de plusieurs parents sont surlignés en vert.


150
2018-02-12 02:33



C'est une vieille question, et ceci est quelque peu subtilement mentionné dans les autres articles, mais l'explication qui m'a fait ce déclic est que les fusions avant non rapides nécessitent un commit séparé.


32
2018-04-02 19:56