Depuis que le temps a git cherry-pick
appris à pouvoir appliquer plusieurs commits, la distinction est en effet devenue quelque peu théorique, mais c'est quelque chose qu'on appelle une évolution convergente ;-)
La véritable distinction réside dans l'intention initiale de créer les deux outils:
git rebase
La tâche du développeur est de transférer une série de changements qu'un développeur a dans son référentiel privé, créés contre la version X d'une branche amont, vers la version Y de cette même branche (Y> X). Cela change effectivement la base de cette série de commits, d'où le «rebasage».
(Cela permet également au développeur de transplanter une série de commits sur n'importe quel commit arbitraire, mais c'est d'une utilité moins évidente.)
git cherry-pick
est pour amener un commit intéressant d'une ligne de développement à une autre. Un exemple classique est le rétroportage d'un correctif de sécurité effectué sur une branche de développement instable vers une branche stable (maintenance), où a merge
n'a aucun sens, car cela entraînerait de nombreux changements indésirables.
Depuis sa première apparition, git cherry-pick
a pu choisir plusieurs commits à la fois, un par un.
Par conséquent, la différence la plus frappante entre ces deux commandes est peut-être la manière dont elles traitent la branche sur laquelle elles travaillent: git cherry-pick
apporte généralement un commit d'un autre endroit et l'applique au-dessus de votre branche actuelle, enregistrant un nouveau commit, tandis que git rebase
prend votre branche actuelle et réécrit une série de son propre tip s'engage d'une manière ou d'une autre. Oui, c'est une description très stupide de ce qui git rebase
peut faire, mais c'est intentionnel, d'essayer de faire pénétrer l'idée générale.
Mettre à jour pour expliquer plus en détail un exemple d'utilisation en git rebase
cours de discussion.
Compte tenu de cette situation,
The Book déclare:
Cependant, il existe un autre moyen: vous pouvez prendre le patch du changement qui a été introduit dans C3 et le réappliquer par-dessus C4. Dans Git, cela s'appelle le rebasage. Avec la commande rebase, vous pouvez prendre toutes les modifications qui ont été validées sur une branche et les appliquer sur une autre.
Dans cet exemple, vous exécuteriez ce qui suit:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
"Le hic" ici est que dans cet exemple, la branche "expérimentation" (le sujet du rebasage) a été à l'origine bifurquée de la branche "maître", et par conséquent, elle partage les commits C0 à C2 avec elle - effectivement, "expérience" est " master "jusqu'à, et y compris, C2 plus engager C3 par-dessus. (C'est le cas le plus simple possible; bien sûr, "experiment" pourrait contenir plusieurs dizaines de commits en plus de sa base d'origine.)
Il git rebase
est maintenant dit de rebaser "experiment" sur la pointe actuelle de "master", et git rebase
va comme ceci:
- S'exécute
git merge-base
pour voir quel est le dernier commit partagé à la fois par "experiment" et "master" (quel est le point de diversion, en d'autres termes). C'est C2.
- Enregistre tous les commits effectués depuis le point de diversion; dans notre exemple de jouet, c'est juste C3.
- Rembobine le HEAD (qui pointe vers le commit tip de "experiment" avant que l'opération ne commence à s'exécuter) pour pointer vers le bout de "master" - nous rebasons dessus.
- Tente d'appliquer chacun des commits enregistrés (comme avec
git apply
) dans l'ordre. Dans notre exemple de jouet, il ne s'agit que d'un seul commit, C3. Disons que son application produira un commit C3 '.
- Si tout s'est bien passé, la référence "expérience" est mise à jour pour pointer vers le commit résultant de l'application du dernier commit enregistré (C3 'dans notre cas).
Revenons maintenant à votre question. Comme vous pouvez le voir, ici, techniquement, en git rebase
effet, transplante une série de commits de "experiment" à la pointe de "master", donc vous pouvez à juste titre dire qu'il y a effectivement "une autre branche" dans le processus. Mais l'essentiel est que le commit tip de "experiment" a fini par être le nouveau commit tip dans "experiment", il a juste changé sa base:
Encore une fois, techniquement, vous pouvez dire git rebase
qu'ici incorporé certains commits de "master", et c'est tout à fait correct.
Avec cherry-pick, les commits / branches d'origine restent et de nouveaux commits sont créés. Avec rebase, la branche entière est déplacée avec la branche pointant vers les commits rejoués.
Disons que vous avez commencé avec:
Rebase:
Vous obtenez:
Cueillette de cerises:
Vous obtenez:
pour plus d'informations sur git, ce livre en a la plupart (http://git-scm.com/book)
la source
topic
rebasé par-dessusmaster
, il ne contient pas les commits laissés de côté, alors de quelle branche feront-ils partie?git checkout topic
et ensuitegit reset --hard C'
après la cueillette des cerises, vous obtenez le même résultat qu'après le rebasage. Je me suis sauvé de beaucoup de conflits de fusion en utilisant la sélection de cerises plutôt que le rebasage, car l'ancêtre commun était très ancien.git
-guru mais cecirebase
/cherry-pick
est sur tous les détails avecgit
que j'avais un problème de compréhension.git checkout -b
, qui n'a rien à voir avecgit cherry-pick
. Une meilleure façon d'expliquer ce que vous essayez de dire serait «vous courezgit rebase
sur latopic
branche et la transmettezmaster
; vous exécutezgit cherry-pick
sur lamaster
branche et la transmettez (commits à partir de)topic
. »La sélection des cerises fonctionne pour les commits individuels .
Lorsque vous rebasez, il applique toutes les validations de l'historique au HEAD de la branche qui y manque.
la source
git cherry-pick foo~3..foo
et obtenir les commits de la cime de l'arbre de "foo" choisis un par un.git am
dessus. Alors qu'un choix cerise applique la validation par validation (éventuellement en créant une boîte aux lettres à message unique pour chaque patch). Mon rebase échouait car le fichier de boîte aux lettres qu'il créait manquait d'espace sur le lecteur, mais la sélection avec la même plage de révision a réussi (et semble fonctionner plus rapidement).Une réponse courte:
Les réponses données ci-dessus sont bonnes, je voulais juste donner un exemple pour tenter de démontrer leur interrelation.
Il n'est pas recommandé de remplacer "git rebase" par cette séquence d'actions, c'est juste "une preuve de concept" qui, je l'espère, aide à comprendre comment les choses fonctionnent.
Compte tenu du référentiel de jouets suivant:
Disons que nous avons des changements très importants (commits # 2 à # 5) dans master que nous voulons inclure dans notre test_branch_1. Habituellement, nous passons simplement à une branche et faisons "git rebase master". Mais comme nous prétendons être équipés uniquement de "git cherry-pick", nous faisons:
Après toutes ces opérations, notre graphe de validation ressemblera à ceci:
Comme nous pouvons le voir, les commits # 6 et # 7 ont été appliqués à 7254931 (un commit tip de master). HEAD a été déplacé et pointe un commit qui est, essentiellement, une pointe d'une branche rebasée. Il ne nous reste plus qu'à supprimer un ancien pointeur de branche et en créer un nouveau:
test_branch_1 est maintenant enraciné à partir de la dernière position de maître. Terminé!
la source
cherry-pick
est capable d'appliquer une gamme de commits, je pense que oui. Bien que ce soit une manière un peu étrange de faire les choses, rien ne vous empêche de sélectionner tous les commits dans votre branche de fonctionnalité par-dessusmaster
, puis de supprimer la branche de fonctionnalité et de la recréer de manière à ce qu'elle pointe vers la pointe demaster
. Vous pouvez pensergit rebase
à une séquence degit cherry-pick feature_branch
,git branch -d feature_branch
etgit branch feature_branch master
.Ce sont toutes les deux des commandes pour réécrire les commits d'une branche sur une autre: la différence est dans quelle branche - "la vôtre" (actuellement extraite
HEAD
) ou "la leur" (la branche passée en argument à la commande) - est la base de cette réécriture.git rebase
prend un commit de départ et rejoue vos commits comme venant après le leur (le commit de départ).git cherry-pick
prend un ensemble de commits et rejoue leurs commits comme venant après le vôtre (votreHEAD
).En d'autres termes, les deux commandes sont, dans leur comportement de base (ignorant leurs caractéristiques de performance divergentes, leurs conventions d'appel et leurs options d'amélioration), symétriques : l'extraction de la branche
bar
et l'exécutiongit rebase foo
définit labar
branche sur le même historique que l'extraction de la branchefoo
et l'exécutiongit cherry-pick ..bar
définiraitfoo
à (les changements defoo
, suivis des changements debar
).En ce qui concerne le nom, la différence entre les deux commandes peut être mémorisée en ce que chacune décrit ce qu'elle fait à la branche actuelle :
rebase
fait de l'autre tête la nouvelle base de vos modifications, tandis quecherry-pick
choisit les modifications de l'autre branche et les place au-dessus de votreHEAD
(comme des cerises sur un sundae).la source
Les deux font des choses très similaires; la principale différence conceptuelle est (en termes simplifiés) que:
rebase déplace les commits de la branche actuelle vers une autre branche .
des copies de sélection cerise commits d' une autre branche à la branche actuelle .
En utilisant des diagrammes similaires à la réponse de @Kenny Ho :
Compte tenu de cet état initial:
... et en supposant que vous voulez que les commits de la
topic
branche soient rejoués au-dessus de lamaster
branche actuelle , vous avez deux options:Utilisation de rebase: vous devez d'abord aller
topic
en faisantgit checkout topic
, puis déplacer la branche en exécutantgit rebase master
, en produisant:Résultat: votre branche actuelle a
topic
été rebasée (déplacée) surmaster
.La
topic
succursale a été mise à jour, tandis que lamaster
succursale est restée en place.Utilisation de cherry-pick : vous devez d'abord aller
master
en faisantgit checkout master
, puis copier la branche en exécutantgit cherry-pick topic~3..topic
(ou, de manière équivalente,git cherry-pick B..G
), en produisant:Résultat: les commits de
topic
ont été copiés dansmaster
.La
master
succursale a été mise à jour, tandis que latopic
succursale est restée en place.Bien sûr, ici, vous deviez explicitement dire à cherry-pick de choisir une séquence de commits , en utilisant la notation de plage
foo..bar
. Si vous aviez simplement passé le nom de la branche, comme dansgit cherry-pick topic
, il n'aurait ramassé que le commit à la pointe de la branche, ce qui aurait donné:la source