使用 git 2.11,git rebase文档说:
The current branch is reset to <upstream>, or <newbase> if the --onto option was supplied. This has the exact same effect as git reset --hard (or ). ORIG_HEAD is set to point at the tip of the branch before the reset.
我理解的好像
upstream
和 newbase
指向相同的“基本引用”,那么这意味着下面的两个 rebase 语法是等效的:git rebase ABC
git rebase --onto ABC
这是我设置的演示。假设当前分支是
FeatureABC
它与远程分支完全同步。#---create two identical branches, behind current branch by 5 commits
(FeatureABC) git branch Demo1-Rebase-ABC HEAD~4
(FeatureABC) git branch Demo2-Rebase-onto-ABC HEAD~4
#---Make a new commit in branch Demo1
git checkout Demo1-Rebase-ABC
echo "Demo of: git rebase FeatureABC Demo1-Rebase-ABC" > ./Demo1_BogusFile.txt
git add ./Demo1_BogusFile.txt
git commit -m "Create file Demo1_BogusFile.txt"
git rebase FeatureABC
First, rewinding head to replay your work on top of it
... Applying: Create file Demo1_BogusFile.txt
git log --oneline -3
显示分支 Demo1-Rebase-ABC
与 FeatureABC 的 HEAD 同步。并且在其上正确应用了提交“创建文件 Demo1_BogusFile.txt”。#---Make a new commit in branch Demo2
git checkout Demo2-Rebase-onto-ABC
echo "Demo of: git rebase --onto FeatureABC Demo2-Rebase-onto-ABC" > ./Demo2_Onto_BogusFile.txt
git add ./Demo2_Onto_BogusFile.txt
git commit -m "Create file Demo2_Onto_BogusFile.txt"
git rebase --onto FeatureABC
There is no tracking information for the current branch. Please specify which branch you want to rebase against. See git-rebase(1) for details.
git rebase <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> Demo2-Rebase-onto-ABC
我误解了警告信息。认为 git 在使用 --onto 时在默认值中被混淆了。所以我只想通过告诉 git 我要重新设置的当前分支来“帮助”
git rebase --onto FeatureABC Demo2-Rebase-onto-ABC
First, rewinding head to replay your work on top of it...
git log --oneline -3
显示分支 Demo2-Rebase-onto-ABC
变成 相同 比FeatureABC
.最后一次提交“创建文件 Demo2_Onto_BogusFile.txt”已经消失,文件 ./Demo2_Onto_BogusFile.txt
被删除。问题 :
git rebase --onto FeatureABC Demo2-Rebase-onto-ABC
是什么原因没有应用对 Demo2-Rebase-onto-ABC
所做的新提交分支?
最佳答案
它们不一样,这可能会因 --fork-point
而变得复杂。选项。我认为这可能是您的问题,尽管无法确定,仅从您所描述的内容来看,因为您概述的步骤之一只会产生错误。
我从一个合理的猜测开始,但这是一个猜测
要查看真正发生的事情,绘制(部分)提交图非常有帮助,特别注意标记,因为您使用了多个名称,所有名称都指向单个提交。
Let's assume the current branch is
FeatureABC
it is perfectly in sync with the remote branch.
因此,我们有这样的东西——但这样的东西还不够好;您有存储库,因此您应该绘制图形;我不得不猜测:
...--o--A--B--C--D--E <-- FeatureABC (HEAD), origin/FeatureABC
现在你运行:
#---create two identical branches, behind current branch by 5 commits (FeatureABC) git branch Demo1-Rebase-ABC HEAD~4 (FeatureABC) git branch Demo2-Rebase-onto-ABC HEAD~4
自
HEAD~4
名称提交 A
( HEAD~1
是 D
, HEAD~2
是 C
,等等),我们需要做一些事情来标记这两个新名称指向提交 A
的事实.我将把名字缩短为 Demo1
和 Demo2
尽管。 (此时我已经创建了一个仅提交 o
到 E
的存储库,并在此处实际运行 git branch Demo1 HEAD~4; git branch Demo2 HEAD~4
。)...--o--A <-- Demo1, Demo2
\
B--C--D--E <-- FeatureABC (HEAD), origin/FeatureABC
顺便说一句,
git log --all --decorate --oneline --graph
(有人说“从狗那里得到帮助”)以这种方式显示了这个测试存储库(在我的例子中没有 origin/
分支):* c4a0671 (HEAD -> master) E
* a7b8ae4 D
* 3deea72 C
* b11828d B
* ffc29b5 (Demo2, Demo1) A
* 3309a8d initial
接下来,您查看 Demo1,移动
HEAD
:git checkout Demo1-Rebase-ABC
...--o--A <-- Demo1 (HEAD), Demo2
\
B--C--D--E <-- FeatureABC, origin/FeatureABC
并修改工作树,将修改后的文件添加到索引中,然后提交,以进行新的提交,我将称之为
F
,更新 HEAD
分支并因此分隔 Demo1
和 Demo2
.我现在将在这里使用我自己的命令及其输出:$ git checkout Demo1
Switched to branch 'Demo1'
$ echo demo1 > demo1.txt && git add demo1.txt && git commit -m F
[Demo1 89773b6] F
1 file changed, 1 insertion(+)
create mode 100644 demo1.txt
绘制图形变得有点困难;我将使用一行:
F <-- Demo1 (HEAD)
/
...--o--A <-- Demo2
\
B--C--D--E <-- FeatureABC, origin/FeatureABC
现在我们到您的第一个
git rebase
命令。我必须使用 master
, 当然:$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: F
这适用于当前分支(
HEAD
或 Demo1
)。它查找在 HEAD
上的提交不在 FeatureABC
( FeatureABC..
在 gitrevisions 语法中)。那是提交 F
.这些提交被放入可能复制的提交列表中——git rebase
将检查具有相同 git patch-id
的提交并跳过它们,尽管很明显这没有发生在这里。所以现在提交 F
复制到新提交 F'
, 具有不同的哈希 ID 和不同的基数: F [abandoned]
/
...--o--A <-- Demo2
\
B--C--D--E <-- FeatureABC, origin/FeatureABC
\
F' <-- Demo1 (HEAD)
(这是实际的
git log
输出,显示副本的新提交哈希。原始的,现在已放弃的 F
不会显示,除非我将 Demo1@{1}
添加到命令中,我在这里做了。原始是第二个F
显示,即较早的提交:$ git log --all --decorate --oneline --graph Demo1@{1}
* c1d0896 (HEAD -> Demo1) F
* c4a0671 (master) E
* a7b8ae4 D
* 3deea72 C
* b11828d B
| * 89773b6 F
|/
* ffc29b5 (Demo2) A
* 3309a8d initial
我更喜欢水平图,但这个图有更多信息,特别是缩写的哈希 ID。)
复制失败,我得再猜一次
现在我们尝试用
Demo2
重复这个,但它失败了。这是我的实际命令,剪切和粘贴。第一步工作正常:$ git checkout Demo2
Switched to branch 'Demo2'
$ echo demo2 > demo2.txt && git add demo2.txt && git commit -m G
[Demo2 ae30665] G
1 file changed, 1 insertion(+)
create mode 100644 demo2.txt
不再画原版
F
,这是新图。我把G
哪里F
曾经是,虽然我可以把它画成 ...--o--A--G
: G <-- Demo2 (HEAD)
/
...--o--A
\
B--C--D--E <-- FeatureABC, origin/FeatureABC
\
F <-- Demo1
但是,rebase 不起作用。我再次必须使用
master
而不是 FeatureABC
,但鉴于 git branch
在您的示例中的行为方式相同命令未设置上游(“跟踪”)名称:$ git rebase --onto master
There is no tracking information for the current branch.
Please specify which branch you want to rebase against.
See git-rebase(1) for details.
git rebase <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=<remote>/<branch> Demo2
原因
git rebase
失败,此错误消息是 --onto
has absorbed the argument as <newtarget>
, leaving us with no <upstream>
:If
<upstream>
is not specified, the upstream configured inbranch.<name>.remote
andbranch.<name>.merge
options will be used (see git-config(1) for details) and the--fork-point
option is assumed. If you are currently not on any branch or if the current branch does not have a configured upstream, the rebase will abort.
这里的粗体是我的,但我认为它也是关键。我假设您运行了
git rebase --onto <somename>
那没有失败。为了它没有失败,你的分支必须有一个上游集。那个上游可能是 origin/FeatureABC
或类似的,这意味着就 Git 而言,您正在运行:git rebase --onto FeatureABC --fork-point origin/FeatureABC
并不是:
git rebase --onto FeatureABC --no-fork-point origin/FeatureABC
一些 further reading in the (overly cryptic, in my opinion)
git rebase
documentation会出现这句话:If either
<upstream>
or--root
is given on the command line, then the default is--no-fork-point
, otherwise the default is--fork-point
.
换句话说:
git rebase FeatureABC
关闭
--fork-point
选项,如:git rebase --onto FeatureABC FeatureABC
但:
git rebase
或者:
git rebase --onto FeatureABC
离开
--fork-point
选项。什么
--fork-point
是关于--fork-point
的目标是专门删除曾经在您的上游但不再在您的上游的提交。见 Git rebase - commit select in fork-point mode举个例子。 The specific mechanism is complicated and relies on the upstream branch's reflog.由于我没有您的存储库或您的 reflog,因此我无法测试您的具体情况 - 但这是一个原因,并且可能是考虑到您问题中的提示的最可能的原因,即会影响 rebase 树结果的提交会掉线。由于具有相同的 patch ID 而丢弃的提交作为上游提交的是 [ 编辑 :] 经常 1 不会影响上次复制提交的最终树:它们只会导致 merge 冲突和/或迫使您使用 git rebase --skip
跳过它们,如果它们被包括在内。1写完这篇文章后,我想到有一个重要的异常(exception)(这可能与最初的问题无关,但我应该提到)。将一个功能或主题分支重新定位到更主线的分支上,当提交首先从功能中挑选出来进入主线,然后在主线中恢复时,会导致问题。考虑,例如:
...--o--*--P--Q--C'-R--S--X--T <-- mainline
\
A--B--C--D--E <-- topic
哪里
C'
是提交 C
的副本, 和 X
是提交的还原 C
不应该放入 mainline
然而。正在做:git checkout topic
git rebase mainline
将指示 Git 提交提交
A
通过 E
进入“要复制的候选人”名单,还要看P
通过 T
看看是否已经采用了。提交 C
被采用,为 C'
.如 C
和 C'
具有相同的补丁 ID——通常,它们会——Git 将丢弃 C
从列表中作为“已复制”。然而,C
已在提交 X
中明确还原.谁做rebase需要注意,小心恢复
C
如果需要和适当。这种特殊行为对于
git merge
来说不是问题(因为 merge 忽略中间提交),仅适用于 git rebase
.
关于git - 为什么 "rebase --onto ABC"与 "rebase ABC"不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42616979/