J'ai remarqué que les deux blocs de commandes git suivantes ont des comportements différents et je ne comprends pas pourquoi.
J'ai A
une B
branche et une branche qui divergent avec unecommit
---COMMIT--- (A)
\
--- (B)
Je veux rebaser la B
branche sur le dernier A
(et avoir le commit sur la B
branche)
---COMMIT--- (A)
\
--- (B)
Pas de problème si je fais:
checkout B
rebase A
Mais si je fais:
checkout B
rebase --onto B A
Ça ne marche pas du tout, rien ne se passe. Je ne comprends pas pourquoi les deux comportements sont différents.
Le client Phpstorm git utilise la deuxième syntaxe, et me semble donc complètement cassé, c'est pourquoi je demande ce problème de syntaxe.
git
git-rebase
Xmanoux
la source
la source
Réponses:
tl; dr
La syntaxe correcte pour rebaser
B
en plus d'A
utilisergit rebase --onto
dans votre cas est:ou rebase
B
en plus deA
commencer à partir du commit qui est le parent deB
référencé avecB^
ouB~1
.Si vous êtes intéressé par la différence entre
git rebase <branch>
etgit rebase --onto <branch>
lisez la suite.Le rapide: git rebase
git rebase <branch>
va rebaser la branche que vous avez actuellement extraite, référencée parHEAD
, en plus du dernier commit accessible depuis<branch>
mais pas depuisHEAD
.C'est le cas le plus courant de rebasage et sans doute celui qui nécessite moins de planification à l'avance.
Dans cet exemple,
F
etG
sont des commits accessibles depuisbranch
mais pas depuisHEAD
. Diregit rebase branch
prendraD
, c'est le premier commit après le point de branchement, et le rebase (c'est-à-dire changer son parent ) au-dessus du dernier commit accessible depuisbranch
mais pas depuisHEAD
, c'est-à-direG
.The Precise: git rebase --onto avec 2 arguments
git rebase --onto
vous permet de rebaser à partir d'un commit spécifique . Cela vous donne un contrôle exact sur ce qui est rebasé et où. C'est pour les scénarios où vous devez être précis.Par exemple, imaginons que nous ayons besoin de rebaser
HEAD
précisément en plus deF
partir deE
. Nous sommes uniquement intéressés par l'intégrationF
dans notre branche de travail alors que, en même temps, nous ne voulons pas conserverD
car il contient des modifications incompatibles.Dans ce cas, dirions-nous
git rebase --onto F D
. Ça signifie:En d'autres termes, changez le parent de
E
deD
àF
. La syntaxe degit rebase --onto
est alorsgit rebase --onto <newparent> <oldparent>
.Un autre scénario dans lequel cela s'avère utile est lorsque vous souhaitez supprimer rapidement certains commits de la branche actuelle sans avoir à faire un rebase interactif :
Dans cet exemple, pour supprimer
C
etE
de la séquence, vous diriezgit rebase --onto B E
, ou rebasezHEAD
par-dessus l'B
emplacement de l'ancien parentE
.The Surgeon: git rebase --onto avec 3 arguments
git rebase --onto
peut aller plus loin en termes de précision. En fait, cela vous permet de rebaser une plage arbitraire de commits par-dessus une autre.Voici un exemple:
Dans ce cas, nous voulons rebaser la plage exacte
E---H
par-dessusF
, en ignorant oùHEAD
pointe actuellement. Nous pouvons le faire en disantgit rebase --onto F D H
, ce qui signifie:La syntaxe de
git rebase --onto
avec une plage de commits devient alorsgit rebase --onto <newparent> <oldparent> <until>
. L'astuce ici est de se souvenir que le commit référencé par<until>
est inclus dans la plage et deviendra le nouveau uneHEAD
fois le rebase terminé.la source
<oldparent>
nom se décompose si les deux parties de la gamme sont sur des branches différentes. En général, c'est: "Inclut chaque commit accessible<until>
mais exclut chaque commit accessible depuis<oldparent>
."git rebase --onto <newparent> <oldparent>
est la meilleure explication du comportement --onto que j'ai vu!--onto
option mais cela le rendait clair! Je ne comprends même pas comment je n'aurais pas pu le comprendre auparavant: D Merci pour l'excellent "tutoriel" :-)C'est tout ce que vous devez savoir pour comprendre
--onto
:Vous changez de parent sur un commit, mais vous ne fournissez pas le sha du commit, seulement le sha de son (ancien) parent actuel.
la source
En bref, étant donné:
Ce qui est identique à (car
--onto
prend un argument):Les moyens rebasage commits dans la gamme (D, H] au - dessus de F. Avis de la gamme est exclusive à la main gauche. Il est exclusif , car il est plus facile de spécifier le 1er commit en tapant par exemple
branch
laissergit
trouver le 1er divergé engagement debranch
dire ceD
qui conduit àH
.Cas OP
Peut être changé en commande unique:
Ce qui ressemble à une erreur ici, c'est le placement de
B
ce qui signifie "déplacer certains commits qui mènent à une brancheB
au-dessus deB
". La question est de savoir ce que sont «certains commits». Si vous ajoutez un-i
drapeau, vous verrez qu'il s'agit d'un commit unique pointé parHEAD
. Le commit est ignoré car il est déjà appliqué à la--onto
cibleB
et donc rien ne se passe.La commande n'a aucun sens dans tous les cas où le nom de la branche est répété comme ça. Ceci est dû au fait que la plage de commits sera constituée de certains commits qui sont déjà dans cette branche et pendant le rebase, tous seront ignorés.
Explication supplémentaire et utilisation applicable de
git rebase <upstream> <branch> --onto <newbase>
.git rebase
les valeurs par défaut.S'étend à:
Vérification automatique après rebase.
Lorsqu'il est utilisé de manière standard, comme:
Vous ne remarquerez pas qu'après le rebase
git
se déplacebranch
vers le dernier commit rebasé et le faitgit checkout branch
(voirgit reflog
historique). Ce qui est intéressant quand le 2ème argument est le hachage de validation au lieu de cela, le rebase de nom de branche fonctionne toujours mais il n'y a pas de branche à déplacer, donc vous vous retrouvez dans "HEAD détaché" au lieu d'être extrait vers la branche déplacée.Omettre les commits divergents principaux.
L'
master
entrée--onto
est tirée du 1ergit rebase
argument.Il peut donc s'agir de n'importe quel autre commit ou branche. De cette façon, vous pouvez limiter le nombre de commits de rebase en prenant les derniers et en laissant les commits principaux divergents.
Est-ce que rebasage simple commettras pointé par
HEAD
àmaster
et se retrouvent dans « décollée HEAD ».Évitez les caisses explicites.
La valeur par défaut
HEAD
ou l'current_branch
argument est contextuellement pris à partir de l'endroit où vous vous trouvez. C'est pourquoi la plupart des gens achètent vers la branche qu'ils veulent rebaser. Mais lorsque le deuxième argument de rebase est donné explicitement, vous n'avez pas besoin de vérifier avant le rebase pour le transmettre de manière implicite.Cela signifie que vous pouvez rebaser les commits et les branches depuis n'importe quel endroit. Donc, avec le paiement automatique après rebase. vous n'avez pas à extraire séparément la branche rebasée avant ou après le rebase.
la source
En termes simples,
git rebase --onto
sélectionne une plage de commits et les rebase sur le commit donné en paramètre.Lisez les pages de manuel pour
git rebase
, recherchez "sur". Les exemples sont très bons:Dans ce cas, vous dites à git de rebaser les commits de
topicA
àtopicB
par-dessusmaster
.la source
Pour mieux comprendre la différence entre
git rebase
etgit rebase --onto
il est bon de savoir quels sont les comportements possibles pour les deux commandes.git rebase
nous permettent de déplacer nos commits au-dessus de la branche sélectionnée. Comme ici:et le résultat est:
git rebase --onto
est plus précis. Cela nous permet de choisir un commit spécifique où nous voulons commencer et aussi où nous voulons terminer. Comme ici:et le résultat est:
Pour obtenir plus de détails, je vous recommande de consulter mon propre article sur git rebase - vue d'ensemble
la source
git rebase --onto F D
comme enfant défini du parent de D comme F , n'est-ce pas?Car
onto
vous avez besoin de deux branches supplémentaires. Avec cette commande, vous pouvez appliquer des validationsbranchB
baséesbranchA
sur une autre branche, par exemplemaster
. Dans l'exemple cibranchB
- dessous est basé surbranchA
et vous souhaitez appliquer les modifications debranchB
surmaster
sans appliquer les modifications debranchA
.en utilisant les commandes:
vous obtiendrez la hiérarchie de validation suivante.
la source
rebase --onto branchA branchB
ce que cela mettrait toute la branche principale à la tête de la branche A?checkout branchB: rebase --onto master branchA
?Il y a un autre cas où il
git rebase --onto
est difficile de saisir: lorsque vous rebasez sur un commit résultant d'un sélecteur de différence symétrique (les trois points '...
')Git 2.24 (Q4 2019) gère mieux ce cas:
Voir commit 414d924 , commit 4effc5b , commit c0efb4c , commit 2b318aa (27 août 2019) et commit 793ac7e , commit 359eceb (25 août 2019) par Denton Liu (
Denton-L
) .Aide: Eric Sunshine (
sunshineco
) , Junio C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) et Johannes Schindelin (dscho
) .Voir commit 6330209 , commit c9efc21 (27 août 2019) et commit 4336d36 (25 août 2019) par Ævar Arnfjörð Bjarmason (
avar
).Aide: Eric Sunshine (
sunshineco
) , Junio C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) et Johannes Schindelin (dscho
) .(Fusionné par Junio C Hamano -
gitster
- dans commit 640f9cd , 30 sept. 2019)À ce stade, lisez " Quelles sont les différences entre le double point '
..
' et le triple point"...
"dans les plages de validation Git diff? "Ici: "
master...
" fait référence àmaster...HEAD
, qui estB
: HEAD est le côté HEAD (actuellement extrait): vous rebasez surB
.Que rebasez-vous? Tout commit qui n'est pas dans master, et accessible depuis la
side
branche: il n'y a qu'un seul commit correspondant à cette description:D
... qui est déjà au dessus deB
!Encore une fois, avant Git 2.24, cela
rebase --onto
aurait pour conséquence d'D
être toujours rebasé, quoi qu'il arrive.Cela s'apparente à celui
rebase --onto B A
de l'OP, qui n'a rien fait.et la commande défaillante était
A
rebase --onto C F topic
signifie tout commit aprèsF
, accessible partopic
HEAD: c'estG
seulement, pasF
lui-même.Dans ce cas, une avance rapide inclurait
F
la branche rebasée, ce qui est faux.la source