Git在特定情况下表现异常,我能够重现此问题。我有两个分支,分别是master和Feature,它们指向同一提交。当我将母版重置为父提交并尝试在母版之上重新设置功能时,功能分支也指向父提交,尽管我希望变基不执行任何操作。我不确定为什么会这样。
复制步骤:
运行以下命令以重现初始状态:
deepakgupta @ git init
Initialized empty Git repository in /tmp/hello/.git/
deepakgupta (master)@ touch hello
deepakgupta (master)@ git add hello
deepakgupta (master)@ git commit -m "First commit"
[master (root-commit) 1750f9c] First commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 hello
deepakgupta (master)@ touch world
deepakgupta (master)@ git add world
deepakgupta (master)@ git commit -m "Second commit"
[master 7411ad0] Second commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 world
deepakgupta (master)@ git branch feature
此时,这是git log
的样子:
commit 7411ad0984841b28dca630d54c3b079ebd01c7e9 (HEAD -> master, feature)
Author: Deepak Gupta <[email protected]>
Date: Tue Apr 7 13:58:09 2020 +0530
Second commit
commit 1750f9c5ba95f53742005657e9cee41390165dc7
Author: Deepak Gupta <[email protected]>
Date: Tue Apr 7 13:57:54 2020 +0530
First commit
现在尝试:
git reset --hard HEAD^
git checkout feature
git branch --set-upstream-to master
现在是git日志,现在看起来:
commit 7411ad0984841b28dca630d54c3b079ebd01c7e9 (HEAD -> feature)
Author: Deepak Gupta <[email protected]>
Date: Tue Apr 7 13:58:09 2020 +0530
Second commit
commit 1750f9c5ba95f53742005657e9cee41390165dc7 (master)
Author: Deepak Gupta <[email protected]>
Date: Tue Apr 7 13:57:54 2020 +0530
First commit
当我尝试git rebase
时会发生什么?我觉得状态应该保持不变。但它变为:
commit 1750f9c5ba95f53742005657e9cee41390165dc7 (HEAD -> feature, master)
Author: Deepak Gupta <[email protected]>
Date: Tue Apr 7 13:57:54 2020 +0530
First commit
(END)
有人可以解释这种行为吗?
此问题-或功能,如Git人士更喜欢提及的-是由于Git的叉点模式所致。 The git rebase
documentation描述如下:
如果未指定
git rebase
,将使用在upstream
和branch.name.remote
选项中配置的上游(详细信息请参见branch.name.merge
)并且假定为git-config[1]选项。如果您当前不在任何分支上,或者当前分支上没有配置上游,则重新定位将中止。
(格式(尤其是粗体部分是我的)。下一段提供了这个神秘的摘要:
由当前分支中的所有提交所做的更改但不包含在
--fork-point
中的所有更改都保存到一个临时区域。这与upstream
显示的提交集相同;如果git log <upstream>..HEAD
处于活动状态,则按git log 'fork_point'..HEAD
(请参见下面有关--fork-point
的说明);如果指定了--fork-point
选项,则按git log HEAD
。
(此描述省略了一些重要的项目:特别是默认情况下,也将丢弃等同于补丁ID的合并和提交。但这两个都不影响您的特定情况。)
分叉点描述在页面的中间。它提到:
[
--root
是fork_point
命令的结果(请参见git merge-base --fork-point <upstream> <branch>
)。如果git-merge-base[1]最终为空,则fork_point
将用作后备。
[upstream
是upstream
,而master
是当前分支,branch
:
feature
((使用我在复制示例时制作的存储库中的哈希ID):
$ git merge-base --fork-point master feature
af07c3c48ff0d499400ac539aa9c665a8dddcd6f
因此,鉴于此合并基础,$ git log --decorate --oneline
af07c3c (HEAD -> feature) Second commit
dbf1741 (master) First commit
承诺将复制的提交将是rebase
显示的提交:
git log af07c3c48ff0d499400ac539aa9c665a8dddcd6f..HEAD
未列出任何提交,因此未复制任何提交。
要禁用叉点模式,请运行:
$ git log af07c3c48ff0d499400ac539aa9c665a8dddcd6f..HEAD
$
或:
git rebase --no-fork-point
即使当前分支git rebase master
的上游是feature
,默认情况下,显式master
禁用叉点模式。强制Git在使用显式分支名称时使用派生点模式-您是否希望这样做?在这种情况下,您大概不想要它-您也可以运行:
git rebase master
完全不带参数,您会得到git rebase --fork-point master
的效果。