git pull
crée probablement le commit. Si vous effectuez un commit local et que vous l'exécutez git pull
après que quelqu'un d'autre a poussé un commit vers le référentiel, Git télécharge le commit de l'autre développeur, puis le fusionne dans votre branche locale.
Comment éviter ces commits de fusion à l'avenir
Vous pouvez l'utiliser git pull --rebase
pour éviter que cela ne se produise à l'avenir, mais le rebasage a ses risques et je recommande d'éviter pull
complètement .
Au lieu de cela, je vous encourage à suivre ce modèle d'utilisation:
# download the latest commits
git remote update -p
# update the local branch
git merge --ff-only @{u}
# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}
Explication
git remote update -p
télécharge tous les commits dans les référentiels distants et met à jour les branches de suivi distantes (par exemple, origin/master
). Il ne touche PAS votre répertoire de travail, votre index ou vos branches locales.
L' -p
argument élague les branches en amont supprimées. Ainsi, si la foo
branche est supprimée dans le origin
référentiel, git remote update -p
supprimera automatiquement votre origin/foo
ref.
git merge --ff-only @{u}
dit à Git de fusionner la branche amont (l' @{u}
argument) dans votre branche locale, mais seulement si votre branche locale peut être "acheminée rapidement" vers la branche amont (en d'autres termes, si elle n'a pas divergé).
git rebase -p @{u}
déplace efficacement les commits que vous avez faits mais que vous n'avez pas encore poussés au-dessus de la branche amont, ce qui élimine le besoin de créer les commits de fusion stupides que vous essayez d'éviter. Cela améliore la linéarité de l'historique de développement, ce qui facilite son examen.
L' -p
option indique à Git de conserver les fusions. Cela empêche Git de linéariser les commits en cours de rebasage. Ceci est important si, par exemple, vous avez fusionné une branche de fonctionnalité dans master
. Sans -p
, chaque commit sur la branche de fonctionnalité serait dupliqué dans master
le cadre de la linéarisation effectuée par git rebase
. Cela rendrait l'historique du développement plus difficile à examiner, pas plus facile.
Attention : il se git rebase
peut que vous ne fassiez pas ce que vous attendez de lui, alors examinez les résultats avant de pousser. Par exemple:
git log --graph --oneline --decorate --date-order --color --boundary @{u}..
Je préfère cette approche git pull --rebase
aux raisons suivantes:
- Il vous permet de voir les commits amont entrants avant de modifier votre historique pour les incorporer.
- Il vous permet de passer l' option
-p
( --preserve-merges
) à git rebase
au cas où vous auriez besoin de rebaser une fusion intentionnelle (par exemple, la fusion d'une branche de fonctionnalité déjà poussée dans master
).
Sténographie: git up
au lieu degit pull
Pour faciliter les opérations ci-dessus, je recommande de créer un alias appelé up
:
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
Maintenant, tout ce que vous avez à faire pour mettre à jour votre branche est d'exécuter:
git up
au lieu de git pull
. Si vous obtenez une erreur parce que votre branche locale a divergé de la branche amont, c'est votre signal de rebase.
Pourquoi pas git pull --rebase
?
Courir git pull --rebase
équivaut à courir git fetch
suivi de git rebase
. Cela tente d'avancer rapidement vers les nouveaux commits en amont, mais si ce n'est pas possible, il rebase vos commits locaux sur les nouveaux commits en amont. C'est généralement OK, mais soyez prudent:
- Rebase est un sujet avancé, et vous devez comprendre les implications avant de rebaser.
git pull --rebase
ne vous donne pas la possibilité d'examiner les commits avant de les incorporer. En fonction de l' amont changé, il est tout à fait possible que rebasage est le mauvais fonctionnement d' un rebase --onto
, merge
, reset
ou push -f
peut - être plus approprié que d' une plaine rebase
.
- Il n'est pas (actuellement) possible de passer
--preserve-merges
à l'opération de rebase, donc toute fusion intentionnelle d'une branche de fonctionnalité sera linéarisée, rejouant (et donc dupliquant) tous les commits de branche de fonctionnalité.
"Correction" d'un commit de fusion existant créé par git pull
Si vous n'avez pas encore poussé un commit de fusion créé par git pull
, vous pouvez rebaser le commit de fusion. En supposant que vous n'ayez effectué aucune fusion intentionnelle (par exemple, la fusion d'une branche de fonctionnalité déjà poussée dans votre branche actuelle), ce qui suit devrait le faire:
git rebase @{u}
La commande ci-dessus indique à Git de sélectionner tous les commits non-merge accessibles depuis HEAD
(le commit actuel), moins tous les commits accessibles depuis @{u}
(ce qui est un raccourci pour "la branche amont", c'est-à-dire, origin/master
si HEAD
c'est le cas master
), replay (cherry-pick ) les au-dessus de la branche amont, puis déplacez la référence de branche actuelle pour qu'elle pointe vers le résultat de la relecture des validations. Cela déplace effectivement les commits non-merge vers le commit amont le plus récent, ce qui élimine la fusion créée par git pull
.
Si vous avez un commit de fusion intentionnel, vous ne voulez pas l'exécuter git rebase @{u}
car il rejouera tout depuis l'autre branche. Traiter ce cas est beaucoup plus compliqué, c'est pourquoi il est bon d'utiliser git up
et d'éviter git pull
tout à fait. Vous devrez probablement utiliser reset
pour annuler la fusion créée par pull
, puis le faire git rebase -p @{u}
. L' -p
argument de git rebase
n'a pas fonctionné de manière fiable pour moi, vous pourriez donc devoir utiliser reset
pour annuler la fusion intentionnelle, mettre à jour votre branche locale vers @{u}
, puis refaire la fusion intentionnelle (ce qui est pénible s'il y avait beaucoup de fusion poilue conflits).