Je voudrais rebaser sur un commit spécifique, pas sur un HEAD de l'autre branche:
A --- B --- C master
\
\-- D topic
à
A --- B --- C master
\
\-- D topic
au lieu de
A --- B --- C master
\
\-- D topic
Comment puis-je y parvenir?
git
version-control
rebase
git-rebase
Ondra Žižka
la source
la source
git checkout B
avant de courirgit rebase
?rebase
commande sont ce qui compte.Réponses:
Vous pouvez éviter d'utiliser le paramètre --onto en créant une branche temporaire sur le commit que vous aimez, puis en utilisant rebase sous sa forme simple:
la source
git rebase temp
(quand sur le groupe ) abandonne avec "Les groupes de branche actuels sont à jour.".git rebase --onto <target> <from> <to>
pour pouvoir spécifier le commit <from>.Vous pouvez même adopter une approche directe:
la source
topic
etcommitB
.It works by going to the common ancestor of the two branches (the one you’re on and the one you’re rebasing onto), getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn.
je l'ai réessayé maintenant et semblait fonctionner très bien.m > n
.Utilisez l'option "sur":
la source
D
etD^
serait le hachage du dernier et de l'avant-dernier commit de "topic"?git rebase --onto <new-parent> <old-parent>
. Voir Définition du pointeur de parent git sur un autre parent . Dans votre cas, <new-parent> est B, et <old-parent> est A.git rebase --onto <commit-ID> master
git rebase --onto master <commit-ID-of-old-parent>
et pour OPgit rebase --onto B A
.Le commentaire de jsz ci-dessus m'a sauvé des tonnes de douleur, alors voici une recette étape par étape basée sur celle-ci que j'ai utilisée pour rebaser / déplacer tout commit par-dessus tout autre commit:
git rebase --onto <new parent> <old parent>
Dans l'exemple ci-dessus, c'est aussi simple que:
la source
git rebase --onto B master
, voir ma réponse pour une explication plus approfondie.Sujet Solution
La commande correcte pour répondre à la question posée peut être l'une des suivantes (en supposant que la branche
topic
est déjà extraite):Si
topic
n'est pas extrait, vous ajoutez simplementtopic
à la commande (sauf la dernière) comme suit:Sinon, vérifiez d'abord la branche avec:
Rebase toute chaîne de validations vers une validation cible
La forme de base de la commande dont nous avons besoin, tirée de la documentation, est:
<Branch>
est facultatif et il ne fait que vérifier la branche spécifiée avant d'exécuter le reste de la commande. Si vous avez déjà extrait la branche que vous souhaitez rebase, vous n'en avez pas besoin. Notez que vous devez avoir spécifié<Upstream>
pour spécifier<Branch>
ou git pensera que vous spécifiez<Upstream>
.<Target>
est le commit auquel nous attacherons notre chaîne de commits. Lorsque vous fournissez un nom de branche, vous spécifiez simplement le commit principal de cette branche.<Target>
peut être n'importe quel commit qui ne sera pas contenu dans la chaîne de commits déplacés. Par exemple:Pour déplacer l'ensemble de la branche de fonction, vous ne pouvez pas sélectionner
X
,Y
,Z
oufeature
comme<Target>
puisque ce sont tous les commits à l' intérieur du groupe déplacé.<Upstream>
est spécial car cela peut signifier deux choses différentes. S'il s'agit d'un commit qui est un ancêtre de la branche extraite, alors il sert de point de coupure. Dans l'exemple que j'ai fourni, ce serait tout ce qui est pasC
,D
oumaster
. Tous les commits après<Upstream>
jusqu'à ce que la tête de la branche extraite soient ceux qui seront déplacés.Cependant, si
<Upstream>
n'est pas un ancêtre, alors git sauvegarde la chaîne à partir du commit spécifié jusqu'à ce que if trouve un ancêtre commun avec la branche extraite (et abandonne s'il n'en trouve pas). Dans notre cas, un<Upstream>
deB
,C
,D
oumaster
generera COMMITB
servant de point de coupe.<Upstream>
est elle-même une commande facultative et si elle n'est pas spécifiée, alors git regarde le parent de la branche extraite, ce qui équivaut à entrermaster
.Maintenant que git a sélectionné les commits qu'il va couper et déplacer, il les applique dans l'ordre
<Target>
, en ignorant ceux qui sont déjà appliqués à la cible.Exemples et résultats intéressants
En utilisant ce point de départ:
git rebase --onto D A feature
Appliquera commits
B
,C
,X
,Y
,Z
de commettreD
et finissent par sauterB
etC
parce qu'ils ont déjà été appliquées.git rebase --onto C X feature
Appliquera les commits
Y
etZ
s'engageraC
, supprimant effectivement le commitX
la source
Une solution plus simple est
git rebase <SHA1 of B> topic
. Cela fonctionne indépendamment de l'endroit où vous vous trouvezHEAD
.Nous pouvons confirmer ce comportement à partir de git rebase doc
Vous pensez peut-être à ce qui se passera si je mentionne SHA1 de
topic
trop dans la commande ci-dessus?git rebase <SHA1 of B> <SHA1 of topic>
Cela fonctionnera également, mais le rebase ne fera pas
Topic
pointer vers la nouvelle branche ainsi créée etHEAD
sera à l'état détaché. Donc, à partir de là, vous devez supprimer manuellement l'ancienneTopic
et créer une nouvelle référence de branche sur la nouvelle branche créée par rebase.la source
J'ai utilisé un mélange de solutions décrites ci-dessus:
J'ai trouvé cela beaucoup plus facile à lire et à comprendre. La solution acceptée m'a conduit à un conflit de fusion (trop paresseux pour être résolu à la main):
la source
Puisque le rebasage est si fondamental, voici une extension de la réponse de Nestor Milyaev . Combinaison des commentaires de jsz et de Simon South à partir de la réponse d' Adam Dymitruk donne cette commande qui fonctionne sur la
topic
branche indépendamment du fait qu'elle se branche à partirmaster
du commit de la brancheA
ouC
:Notez que le dernier argument est obligatoire (sinon, il rembobine votre branche pour valider
B
).Exemples:
Donc, la dernière commande est celle que j'utilise généralement.
la source
Il existe une autre façon de le faire ou si vous souhaitez revenir à plus d'un seul commit.
Voici un exemple pour revenir au
n
nombre de commits:Pour répondre à cette question, cela peut également être fait:
La commande fonctionne parfaitement
git version 2.7.4
. Je ne l'ai testé sur aucune autre version.la source