En utilisant gitk log
, je ne pouvais pas distinguer les deux. Comment puis-je observer la différence (avec une commande git ou un outil)?
L'indicateur --no-ff
empêche git merge
d'exécuter une "avance rapide" s'il détecte que votre HEAD
actuel est un ancêtre du commit que vous essayez de fusionner. Une avance rapide a lieu lorsque, au lieu de construire une validation de fusion, git déplace simplement le pointeur de votre branche sur la validation entrante. Cela se produit généralement lorsque vous faites un git pull
sans aucune modification locale.
Toutefois, vous souhaitez parfois empêcher ce problème de se produire, généralement parce que vous souhaitez conserver une topologie de branche spécifique (par exemple, vous fusionnez dans une branche de sujet et vous souhaitez vous assurer que cela ressemble de cette manière lors de la lecture de l'historique). Afin de faire cela, vous pouvez passer le drapeau --no-ff
et git merge
va 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 renoncer s’il ne peut pas avancer rapidement, 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 y penser, et si cela se produit, vous pouvez revenir en arrière et décider si vous souhaitez fusionner ou rebaser.
Voici un site avec une explication claire et une illustration graphique de l’utilisation de git merge --no-ff:
Jusqu'à ce que je voie cela, j'étais complètement perdu avec git. En utilisant --no-ff permet à quelqu'un qui passe en revue l'historique de clairement voir la branche que vous avez extraite sur lequel travailler. (ce lien pointe vers l'outil de visualisation "réseau" de github) Et voici ne autre excellente référence avec des illustrations. Cette référence complète bien la première en mettant davantage l’accent sur ceux qui sont moins familiarisés avec git.
Si vous êtes comme moi et non comme un git-gourou, ma réponse ici décrit le traitement de la suppression des fichiers du suivi 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.
J'ai mis à jour un paquet sur mon site Web et je devais revenir à mes notes pour voir mon flux de travail. J'ai pensé qu'il serait 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
Ci-dessous: utilisation réelle, y compris les explications.
Remarque: la sortie ci-dessous est extraite; git est assez prolixe.
$ 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 le résultat, vous pouvez voir les modifications apportées par la mise à niveau du package ECC, y compris l'ajout de nouveaux fichiers.
2) Notez également qu'il y a deux fichiers (pas dans le dossier /ecc
) que j'ai supprimés indépendamment de cette modification. Au lieu de confondre ces suppressions de fichiers avec ecc
, je créerai ultérieurement une autre branche cleanup
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 la ecc à nouveau.
Ci-dessous: plutôt que de faire _ tout-inclus git commit -am "updated ecc package"
comme d'habitude, je voulais uniquement ajouter les fichiers dans le dossier /ecc
. Ces fichiers supprimés ne faisaient pas spécifiquement partie de mon git add
, mais comme ils ont déjà été suivis dans git, je dois les supprimer du commit 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 [email protected]:me/mywebsite.git
8a0d9ec..333eff5 master -> master
Ayant utilisé ce processus plus de 10 fois par jour, j'ai commencé à écrire des scripts batch pour exécuter les commandes. J'ai donc créé un script presque correct git_update.sh <branch> <"commit message">
pour effectuer les étapes ci-dessus. Voici la source Gist pour ce script.
Au lieu de git commit -am
, je sélectionne des fichiers dans la liste "modifiée" générée via git status
, puis je les colle dans ce script. Cela est dû au fait que j'ai effectué des dizaines de modifications, mais que je voulais divers noms de branches pour aider à regrouper les modifications.
L'option --no-ff
garantit qu'une fusion rapide ne se produira pas et que n nouvel objet de validation sera toujours créé. Cela peut être souhaitable si vous voulez que git maintienne un historique des branches de fonctionnalités. Dans l'image ci-dessus, le côté gauche est un exemple de l'historique de git après l'utilisation de git merge --no-ff
et le côté droit est un exemple d'utilisation de git merge
dans lequel une fusion ff était possible.
EDIT: une version précédente de cette image indiquait un seul parent pour la validation de fusion. Les commits de fusion ont plusieurs commits parents que git utilise pour conserver un historique de la "branche de fonctionnalité" et de la branche d'origine. Les liens parent multiples sont surlignés en vert.
Fusion explicite : crée un nouveau commit de fusion (c'est ce que vous obtiendrez si vous utilisiez --no-ff
.)
Fusion rapide: Transférez rapidement, sans créer de nouveau commit:
Rebase : Établit un nouveau niveau de base:
Squash: Écrasez ou écrasez (quelque chose) avec force pour qu'il devienne plat:
C'est une vieille question, et cela est mentionné de manière assez subtile dans les autres articles, mais l'explication qui a fait ce clic pour moi est que les fusions sans avance rapide nécessiteront un commit séparé.
L'indicateur --no-ff fait que la fusion crée toujours un nouvel objet de validation, même si la fusion peut être effectuée avec une avance rapide. Cela évite de perdre des informations sur l'existence historique d'une branche de fonctionnalité et de regrouper tous les commits ayant ajouté la fonctionnalité.