Est-il une différence entre git rebase et git merge --ff-seulement
De ce que j'ai lu, tous les deux de nous aider à obtenir une histoire linéaire.
De ce que j'ai testé, cela fonctionne tout le temps. Mais la fusion --ff-ne fonctionne que dans les cas où il peut être rapidement transmis.
J'ai aussi remarqué, git merge crée une fusion s'engager, mais si nous utilisons --ff-seulement, il donne une histoire linéaire qui est essentiellement égal à git de rebasage. Donc, - ff-tue uniquement les fins de git merge, droit?
Alors, quelle est la réelle différence entre eux?
Vous devez vous connecter pour publier un commentaire.
Noter que
git rebase
a un autre travail quegit merge
(avec ou sans--ff-only
). Cerebase
n'est à prendre s'engage et copie eux. Supposons, par exemple, que vous êtes surbranch1
et ont fait deux commitsA
etB
:et que vous décidez que vous préférez avoir ces deux commits sur
branch2
à la place. Vous pouvez:A
(diffA
contre son parent)B
(diffB
contreA
)branch2
A
et de les valider, de la copie de votre message de validation deA
; appelons à ce commitA'
B
et de les valider, de la copie de votre message de validation deB
; appelons cetteB'
.Il y a une commande git que cette diff-et-puis-copie-et-de s'engager pour vous:
git cherry-pick
. Donc:Maintenant, vous avez ceci:
Maintenant, vous pouvez revenir à
branch1
et supprimer votre originalA
etB
, à l'aide degit reset
(je vais utiliser--hard
ici, c'est plus pratique que comme il nettoie le travail-les arbres):Cela supprime l'original
A
etB
,1 alors maintenant, vous avez:Maintenant, vous avez juste besoin de re-check-out
branch2
à continuer à y travailler.C'est ce que
git rebase
: il "bouge" s'engage (mais pas par le fait de les déplacer, car il ne peut pas: dans git, un commit peut jamais être modifié, de sorte que même en changeant simplement le parent-ID nécessite de le copier à nouveau et différent commettre).En d'autres termes, alors que
git cherry-pick
est un système automatisé de diff-et-refaire de un commettre,git rebase
est un processus automatisé de refaire plusieurs s'engage, de plus, à la fin, déplacer les étiquettes autour de "oublier" ou dissimuler les originaux.Ci-dessus illustre le déplacement s'engage à partir d'une branche locale
branch1
à une autre branche localebranch2
, mais git utilise le exactement le même processus pour déplacer s'engage lorsque vous avez une distance de suivi de branche qui acquiert des nouvelles validations lorsque vous faites ungit fetch
(y compris lesfetch
qui est la première étape degit pull
). Vous pourriez commencer par un travail sur la branchefeature
, qu'il y a un amont deorigin/feature
, et de faire une couple de validations de votre propre:Mais alors, vous décidez que vous devez voir ce qui s'est passé en amont, de sorte que vous exécutez
git fetch
,2 et, aha, quelqu'un en amont a écrit un commitC
:À ce stade, vous pouvez simplement rebase votre
feature
'sA
etB
surC
, donnant:Ce sont les copies de l'original de votre
A
etB
, avec les originaux étant jetés (mais voir la note de bas de page 1) après les copies sont complètes.Parfois, il n'y a rien de cela, c'est à dire, pas de travail que vous avez vous-même fait. Qui est, le graphe avant la
fetch
ressembler à ceci:Si vous
git fetch
et de s'engagerC
arrive, cependant, vous êtes de gauche avec votrefeature
direction de pointage de l'ancien commit, tandis queorigin/feature
n'a cessé de progresser:C'est là que
git merge --ff-only
vient: si vous demandez à fusionner votre branche courantefeature
avecorigin/feature
, git voit que c'est possible il suffit de glisser la flèche vers l'avant, comme c'était le cas, de sorte quefeature
points directement à commettreC
. Pas de fusion est nécessaire.Si vous aviez votre propre s'engage
A
etB
, cependant, et vous a demandé de faire fusionner ces avecC
, git faire une véritable fusion, la fabrication d'une nouvelle fusion de commettreM
:Ici,
--ff-only
va s'arrêter et vous donnera une erreur. Rebase, d'autre part, vous pouvez copierA
etB
àA'
etB'
puis cacher l'origineA
etB
.Donc, en résumé (ok, trop tard 🙂 ), ils se contentent de faire des choses différentes. Parfois, le résultat est le même, et parfois il ne l'est pas. Si c'est OK pour copier
A
etB
, vous pouvez utilisergit rebase
; mais s'il y a une bonne raison pas de copier, vous pouvez utilisergit merge
, peut-être avec--ff-only
, de fusionner ou de l'échec tant que de besoin.1Git conserve en fait originaux pour un certain temps—normalement un mois dans ce cas—, mais il les cache à l'écart. La meilleure façon de les trouver est avec git du "reflogs", qui permettent de garder un historique de chaque branche pointue, et où
HEAD
souligné, avant chaque changement de la mise à jour de la branche et/ouHEAD
.Finalement le reflog les entrées de l'historique expire, à quel point ces s'engage à devenir admissibles à l' la collecte des ordures.
2Ou, encore, vous pouvez utiliser
git pull
, qui est une commodité script qui commence par l'exécution degit fetch
. Une fois que le téléchargement est terminé, la commodité script s'exécutegit merge
ougit rebase
, selon la façon dont vous configurez et exécutez-le.git cherry-pick
pour expliquergit rebase
. Ressemble beaucoup!--no-ff
ici.Oui, il y a une différence.
git merge --ff-only
échouera si elle ne peut pas avancer plus rapidement, et prend un commit (normalement une branche) à se fusionner. Il ne fera que créer une fusion engager si elle ne peut pas rapide vers l'avant (c'est à dire ne sera jamais le faire avec--ff-only
).git rebase
réécrit l'histoire de la branche courante, ou peut être utilisé pour rebaser une branche sur une branche. Dans ce cas, il ne crée pas une fusion s'engager parce que c'est complet, plutôt que de fusion.git merge
jamais réécrit l'histoire (avec ou sans--ff-only
).--ff-only
empêche toute fusion d'autres qu'une avance rapide de fusion (pas fusionne réécrire l'histoire). Fusionne les autres que l'avance rapide des fusions sont en général simplement l'application du changement-ensembles de l'ordre (c'est une simplification, mais assez bon pour aller avec), en plus de l'enregistrement de métadonnées d'un ensemble de modifications a été fusionnées; pas d'histoire de réécriture impliqués.Oui,
--ff-only
échouera toujours où une plainegit merge
serait un échec, et peut-être ne où une plainegit merge
allait réussir. C'est le point - si vous êtes en essayant de garder une histoire linéaire, et que la fusion ne peut pas être fait de cette façon, vous voulez échouer.Une option qui ajoute le cas d'une commande n'est pas inutile; c'est une façon de valider une condition préalable, de sorte que si l'état actuel du système, ce n'est pas ce que vous attendez, vous n'avez pas d'aggraver le problème.
merge --ff-only
vous supprimez s'engage à partir d'un seul endroit dans l'histoire de l'arbre et de la réinsertion (avec des modifications) à un endroit différent. Ceci est appelé "réécrire l'histoire", et c'est très bien si vous êtes sur un inédit de la branche, mais après vous avez publié votre direction et d'autres personnes ont cloné il, la réécriture de l'histoire provoque des problèmes pour eux.