在这个例子中,git 认为它不需要 rebase,但它显然需要。
这是一个创建迷你测试 git 存储库的快速脚本
#!/bin/bash
rm -rf testgit
mkdir testgit
cd testgit
git init
echo -e "a\nb\nc" > file
git add file
git commit -am 'first'
git checkout -b lineA
echo -e "A\nb\nc" > file
git commit -am 'A'
git checkout -b lineB
echo -e "a\nB\nc" > file
git commit -am 'B'
git checkout -b lineC
echo -e "a\nb\nC" > file
git commit -am 'C'
运行后,这是每个分支中的 file
的样子
master | lineA | lineB | lineC
------------------------------
a A a a
b b B b
c c c C
现在让我们将所有分支 merge 到 master 中,之后 file
中的每个字母都应该大写
$ git checkout master
$ git merge lineA
好的。
$ git checkout lineB
$ git rebase master
Current branch lineB is up to date.
什么?不,主人换了。
$ git checkout master
$ cat file
A
b
c
$ git checkout lineB
$ cat file
a
B
c
在我看来,分支 lineB 需要 rebase 以 merge 通过 merge lineA 对 master 所做的更改。
为什么 git 认为不需要这样做?
此外,如果你这样做
$ git checkout master
$ git merge lineA
Already up-to-date.
$ git merge lineB
...
1 file changed, 2 insertions(+), 2 deletions(-)
$ cat file
a
B
c
$ git merge lineC
...
1 file changed, 2 insertions(+), 2 deletions(-)
$ cat file
a
b
C
这里的 merge 应该是冲突的,但是 git 正在悄悄地破坏它们。我不知道这是否相关,但看起来很奇怪。
最佳答案
第一条命令的结果
在我们的脚本之后(缩写行分支名称...):
master lA lB lC
↓ ↓ ↓ ↓
first----A----B----C
这些命令:
$ git checkout master
$ git merge lineA
导致快进 merge ,它只是将 master
移动到与 lineA
相同的提交。
给予:
master
lA lB lC
↓ ↓ ↓
first----A----B----C
Rebase 没有工作
所以这个命令序列:
$ git checkout lineB
$ git rebase master
是说将 lineB
分支移动到 master
之上。
...但它已经在 master
之上。
master
必须在其历史记录中有一些 lineB
没有的提交,rebase 命令才能执行任何工作。
没有 merge 冲突
当 Git 创建 merge 提交时,它会考虑将要 merge 的父项的历史记录。在这种情况下,两个分支都指向公共(public)提交链上的提交。 Git 可以看到 A
提交在 B
提交之前,而 B
提交在 C
提交之前。因此,Git 认为较晚的提交是在较早的提交之上添加的,因此它们不会冲突。
如果你有这样的历史:
master
↓
---A
/
| lB
| ↓
first----B
那么 Git 会将它们视为平行的开发线。在那种情况下,将 lB
merge 到 master
中,反之亦然会发生冲突。这是因为 B
不是历史上 A
之上的添加,因此 Git 需要用户输入以了解要保留哪些更改。
关于git - 为什么这个 git rebase 认为无事可做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40613102/