使用git 2.11,git rebase文档说:
当前分支重置为< upstream>或< newbase>如果 - 选项已提供。这与git reset具有完全相同的效果 - 硬(或)。 ORIG_HEAD设置为在重置之前指向分支的顶端。
我理解,好像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
首先,倒带头重播你的工作 ...应用:创建文件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
当前分支没有跟踪信息。请 指定要反对的分支。请参阅git-rebase(1) 的信息。
git rebase <branch>
如果您希望为此分支设置跟踪信息,则可以执行此操作 用:
git branch --set-upstream-to=origin/<branch> Demo2-Rebase-onto-ABC
我误解了警告信息。当使用--onto时,认为git在默认值中混淆了。所以我只想&#34;帮助&#34;通过告诉git当前分支我想要改变
git rebase --onto FeatureABC Demo2-Rebase-onto-ABC
首先,倒带头重播你的作品......
git log --oneline -3
表示分支Demo2-Rebase-onto-ABC
变得相同而不是FeatureABC
。最后一次提交&#34;创建文件Demo2_Onto_BogusFile.txt&#34;已消失,文件./Demo2_Onto_BogusFile.txt
已删除。
问题:git rebase --onto FeatureABC Demo2-Rebase-onto-ABC
没有应用Demo2-Rebase-onto-ABC
分支上的新提交的原因是什么?
答案 0 :(得分:5)
它们不一样,--fork-point
选项也会使这变得复杂。我认为这可能是你的一点点,虽然它不可能确定,只是你所描述的,因为你提出的步骤之一只会产生错误。
要了解实际发生的情况,绘制(部分)提交图非常有用,特别注意标记,因为您使用的多个名称都指向单个提交。
假设当前分支为
FeatureABC
,它与远程分支完全同步。
因此我们有这样的东西 - 但之类的东西并不是很好; 你拥有存储库,所以你应该绘制图形;我必须猜测:
...--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
(&#34;得到A DOG&#34的帮助;正如有人说的那样)以这种方式显示此测试存储库(在我的情况下没有origin/
分支):< / p>
* 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
分开1}}和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
上的提交(gitrevisions语法中的FeatureABC..
)。那个提交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
命令没有设置上游(&#34;跟踪&# 34;)名称:
$ 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>
:
如果未指定
<upstream>
,将使用branch.<name>.remote
和branch.<name>.merge
选项中配置的上游(有关详细信息,请参阅git-config(1))和{{1假设选项。如果您当前不在任何分支上,或者当前分支没有配置上游,则rebase将中止。
这里的粗体字是我的,但我认为它也是关键。我假设您运行了--fork-point
没有失败。因为它没有失败,你的分支必须有一个上游集。上游可能是 git rebase --onto <somename>
或类似的,这意味着就Git而言,你正在运行:
origin/FeatureABC
和不:
git rebase --onto FeatureABC --fork-point origin/FeatureABC
有些further reading in the (overly cryptic, in my opinion) git rebase
documentation会出现这句话:
如果在命令行上给出了
git rebase --onto FeatureABC --no-fork-point origin/FeatureABC
或<upstream>
,那么 默认值为--root
,否则默认值为--no-fork-point
。
换句话说:
--fork-point
关闭 git rebase FeatureABC
选项,如下所示:
--fork-point
但:
git rebase --onto FeatureABC FeatureABC
或:
git rebase
将git rebase --onto FeatureABC
选项留在。
--fork-point
是什么 --fork-point
的目标是专门 drop 提交,曾经一度在您的上游,但不再在您的上游。有关示例,请参阅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 将不影响最后复制的提交的最后一个树:它们只会导致合并冲突和/或强制您使用--fork-point
跳过它们,如果它们被包含在内。
1 在写完之后我发现有一个重要的例外(这可能与原始问题无关,但我应该提及)。将功能或主题分支重新分配到更多主线分支上,当首次将功能 out 提取到主线中,然后在主线中还原时,将导致问题。考虑一下,例如:
git rebase --skip
其中...--o--*--P--Q--C'-R--S--X--T <-- mainline
\
A--B--C--D--E <-- topic
是提交C'
的副本,而C
是提交X
的还原,尚未放入C
。这样做的:
mainline
将指示Git将git checkout topic
git rebase mainline
通过A
提交到&#34;候选人中以复制&#34;列表,但也请查看E
到P
以查看是否已采用任何内容。提交T
已,为C
。如果C'
和C
通常具有相同的修补程序ID,则将 -Git将从列表中删除C'
,因为&#34;已经复制&#34 ;。但是,C
中C
已在提交X
中明确还原。
如果需要并且适当的话,任何人都需要注意,并仔细恢复C
。
这种特殊行为不 git merge
的问题(因为合并忽略了中间提交),只有git rebase
。