我无法理解git rebase - 的行为 [英] I can't understand the behaviour of git rebase --onto
问题描述
我注意到以下两个git命令块有不同的行为,我不明白为什么。
我有一个A和B分支,一次提交
---分支A ------- COMMIT1 -----
\\ \\ - BRANCH B--
我想在最新的A上重新分配B分支(并且拥有B分支上的commit1)
--- BRANCH A ------- COMMIT1 -----
\ - BRANCH B--
如果我这样做,没问题:
结帐B
rebase A
但是,如果我这样做:
结帐B
rebase --onto BA
完全不起作用,没有任何反应。我不明白为什么这两种行为是不同的。
Phpstorm git客户端使用第二种语法,在我看来完全破坏了,这就是为什么我要求这种语法问题。
tl; dr
在 A
上使用 git rebase --onto
, B
你的情况是:
git checkout B
git rebase --onto AB ^
$在$ 之上的c $ c>
或 rebase B
从 B> $ c $引用的
的父项提交开始如果您对 B
或
B〜1
。
git rebase< branch> 和 git rebase --onto< branch>
继续阅读
Quick:git rebase
git rebase< branch>
目前已经检查过从< branch> $ c 可到达的最新提交的顶部,由
。 HEAD
。
这是最常见的重新折合,并且可以说是需要更少的
之前之后
A --- B --- C --- F --- G(分支)A --- B --- C --- F --- G(分支)
\\\
D --- E(HEAD)D --- E HEAD)
在这个例子中, F
和 G
是可从分支
但不是从 HEAD
。说 git rebase branch
会取 D
,这是分支点之后的第一次提交,并且将它转换为分支
但不是从 HEAD 可达到的最新提交 / code>,即
G
。
精确:git rebase - 带2个参数
git rebase --onto
允许您从特定提交开始重新分配 。它授予您对正在重新组装和在哪里进行精确控制。例如,我们假设我们需要重新分配 HEAD
这是用于需要精确的场景。 正好在从 E
开始的 F
之上。我们只关注 F
进入我们的工作分支,同时我们不想保留 D $ c
前后
A --- B --- C- --F --- G(分支)A --- B --- C --- F --- G(分支)
\\
D --- E --- H --- I(HEAD)E --- H --- I(HEAD)
在这种情况下,我们会说 git rebase --onto FD
。这意味着:
重新实现可从
HEAD
访问的提交,其父<
$ b $ <换句话说,将E
的父母 从D
更改为˚F
。然后,git rebase --onto
的语法是git rebase --onto< newparent> < oldparent>
。
另一种方法是,当你想从当前分支中快速移除一些提交而不必做一个交互式重新组织:
:
之前之后
A --- B --- C --- E --- F(HEAD)A --- B --- F(HEAD)
在这个例子中,为了从序列中删除
C
和E
,你会说<$ c $在B
之上的c> git rebase - 在BE 或rebaseHEAD
之处旧的父母是E
。
外科医生:git rebase - 带3个参数
git rebase --onto
可以在精度方面更进一步。实际上,它允许您将任意范围的提交重新绑定到另一个提交之上。
以下是一个示例:
前后
A --- B --- C --- F --- G(分支)A --- B --- C --- F --- G(分支)
\\\
D --- E --- H --- I(HEAD)E --- H(HEAD )
在这种情况下,我们想重新确定
E-- -H
在F
之上,忽略HEAD
当前指向的位置。我们可以通过说git rebase --onto FDH
,这意味着:
在
F
上重新提交父元素 D
至H
/ code>。
git rebase --onto
使用范围的提交然后变成git rebase --onto< newparent> < oldparent> <直到>
。这里的技巧是记住< until> 引用的提交包含,并且将成为新的 HEAD
完成rebase之后。I have noticed that the two blocks of following git commands have different behaviours and I don't understand why.
I have a A and a B branch that diverge with one commit
---BRANCH A-------COMMIT1----- \--BRANCH B--
I want to rebase B branch on the lastest A (and have the commit1 on the B branch)
---BRANCH A-------COMMIT1----- \--BRANCH B--
No problem if I do:
checkout B rebase A
But if I do:
checkout B rebase --onto B A
It doesn't work at all, nothing happens. I don't understand why the two behaviours are different.
Phpstorm git client use the second syntax, and so seems to me completely broken, that's why I ask for this syntax issue.
解决方案tl;dr
The correct syntax to rebase
B
on top ofA
usinggit rebase --onto
in your case is:git checkout B git rebase --onto A B^
or rebase
B
on top ofA
starting from the commit that is the parent ofB
referenced withB^
orB~1
.If you're interested in the difference between
git rebase <branch>
andgit rebase --onto <branch>
read on.The Quick: git rebase
git rebase <branch>
is going to rebase the branch you currently have checked out, referenced byHEAD
, on top of the latest commit that is reachable from<branch>
but not fromHEAD
.
This is the most common case of rebasing and arguably the one that requires less planning up front.Before After A---B---C---F---G (branch) A---B---C---F---G (branch) \ \ D---E (HEAD) D---E (HEAD)
In this example,
F
andG
are commits that are reachable frombranch
but not fromHEAD
. Sayinggit rebase branch
will takeD
, that is the first commit after the branching point, and rebase it (i.e. change its parent) on top of the latest commit reachable frombranch
but not fromHEAD
, that isG
.The Precise: git rebase --onto with 2 arguments
git rebase --onto
allows you to rebase starting from a specific commit. It grants you exact control over what is being rebased and where. This is for scenarios where you need to be precise.For example, let's imagine that we need to rebase
HEAD
precisely on top ofF
starting fromE
. We're only interested in bringingF
into our working branch while, at the same time, we don't want to keepD
because it contains some incompatible changes.Before After A---B---C---F---G (branch) A---B---C---F---G (branch) \ \ D---E---H---I (HEAD) E---H---I (HEAD)
In this case, we would say
git rebase --onto F D
. This means:Rebase the commit reachable from
HEAD
whose parent isD
on top ofF
.In other words, change the parent of
E
fromD
toF
. The syntax ofgit rebase --onto
is thengit rebase --onto <newparent> <oldparent>
.Another scenario where this comes in handy is when you want to quickly remove some commits from the current branch without having to do an interactive rebase:
Before After A---B---C---E---F (HEAD) A---B---F (HEAD)
In this example, in order to remove
C
andE
from the sequence you would saygit rebase --onto B E
, or rebaseHEAD
on top ofB
where the old parent wasE
.The Surgeon: git rebase --onto with 3 arguments
git rebase --onto
can go one step further in terms of precision. In fact, it allows you to rebase an arbitrary range of commits on top of another one.Here's an example:
Before After A---B---C---F---G (branch) A---B---C---F---G (branch) \ \ D---E---H---I (HEAD) E---H (HEAD)
In this case, we want to rebase the exact range
E---H
on top ofF
, ignoring whereHEAD
is currently pointing to. We can do that by sayinggit rebase --onto F D H
, which means:Rebase the range of commits whose parent is
D
up toH
on top ofF
.The syntax of
git rebase --onto
with a range of commits then becomesgit rebase --onto <newparent> <oldparent> <until>
. The trick here is remembering that the commit referenced by<until>
is included in the range and will become the newHEAD
after the rebase is complete.这篇关于我无法理解git rebase - 的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!