为什么这个git rebase认为存在';没什么可做的?
在本例中,git认为不需要重新设置基础,但显然需要 下面是一个创建迷你测试git存储库的快速脚本为什么这个git rebase认为存在';没什么可做的?,git,Git,在本例中,git认为不需要重新设置基础,但显然需要 下面是一个创建迷你测试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 c
#!/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'
运行此操作后,以下是每个分支中的文件
的外观
master | lineA | lineB | lineC
------------------------------
a A a a
b b B b
c c c C
现在,让我们将所有分支合并到master中,然后将文件中的每个字母大写
$ git checkout master
$ git merge lineA
好的
什么?不,主人换了
$ git checkout master
$ cat file
A
b
c
$ git checkout lineB
$ cat file
a
B
c
在我看来,branch lineB需要重新设置基础,以合并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
在这里,合并应该是冲突的,但git正在悄悄地对它们进行抨击。我不知道这是否相关,但似乎很奇怪。第一个命令的结果
在脚本之后,我们有(缩写行分支名称…):
这些命令:
$ git checkout master
$ git merge lineA
$ git checkout lineB
$ git rebase master
结果是一个快进合并,它只是移动master
指向与lineA
相同的提交
给予:
master
lA lB lC
↓ ↓ ↓
first----A----B----C
无需再基地工作
所以这一系列命令:
$ git checkout master
$ git merge lineA
$ git checkout lineB
$ git rebase master
正在说将lineB
分支移动到master
的顶部
…但它已位于主控
的顶部
master
必须在其历史记录中有一些lineB
没有的提交才能使rebase命令有任何工作要做
无合并冲突
当Git创建合并提交时,它会考虑要进行合并的父级的历史记录。在这种情况下,两个分支都指向公共提交链上的提交。Git可以看到A
commit在B
commit之前,后者在C
commit之前。因此Git认为后一个提交是在前一个提交的基础上添加的,因此它们并不冲突
相反,如果您有如下历史记录:
master
↓
---A
/
| lB
| ↓
first----B
然后Git将它们视为并行的开发线。在这种情况下,将lB
合并到master
或反之亦然会发生冲突。这是因为B
不是历史中A
之上的添加,因此Git需要用户输入以了解哪些更改需要保留。我认为您的混淆点又回来了。当你执行死刑的时候
git commit -am 'first'
git checkout -b lineA
您确实创建了一个名为lineA
的新分支,但分支点是您刚才所做的提交(“first
”)。正如Git所说,first
是这两个分支历史的一部分,在脚本中,它也是这两个分支中最近的提交。带有一些选项的Git日志显示两个分支名称都指向第一个提交,在本例中为提交id 58b7dcf:
git log --graph --oneline --decorate
* 58b7dcf (HEAD, master, lineA) first
继续:
echo -e "A\nb\nc" > file
git commit -am 'A'
git log --graph --oneline --decorate
* ed40ed2 (HEAD, lineA) A
* 58b7dcf (master) first
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'
git log --graph --oneline --decorate
* 4033067 (HEAD, lineC) C
* f742aed (lineB) B
* ed40ed2 (lineA) A
* 58b7dcf (master) first
git checkout master
git merge lineA
Updating 58b7dcf..ed40ed2
Fast-forward
log命令显示commitA
(ed40ed2)现在是lineA
上的最新提交,其父提交是first
,它仍然是主机上的最新提交。如果此时要将lineA
合并回master
,这将是一个快速的(琐碎的)合并,因为master
没有提交,因为lineA
从它分支出来。同样,将lineA
重定基址到master
上除了报告之外,什么也做不了
Current branch lineA is up to date.
因为分支master
(主分支的尖端)上最近的提交仍然是分支lineA
历史的一部分。继续:
echo -e "A\nb\nc" > file
git commit -am 'A'
git log --graph --oneline --decorate
* ed40ed2 (HEAD, lineA) A
* 58b7dcf (master) first
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'
git log --graph --oneline --decorate
* 4033067 (HEAD, lineC) C
* f742aed (lineB) B
* ed40ed2 (lineA) A
* 58b7dcf (master) first
git checkout master
git merge lineA
Updating 58b7dcf..ed40ed2
Fast-forward
每个新分支都是在前一个分支的最新提交的基础上构建的,没有并行开发。继续:
echo -e "A\nb\nc" > file
git commit -am 'A'
git log --graph --oneline --decorate
* ed40ed2 (HEAD, lineA) A
* 58b7dcf (master) first
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'
git log --graph --oneline --decorate
* 4033067 (HEAD, lineC) C
* f742aed (lineB) B
* ed40ed2 (lineA) A
* 58b7dcf (master) first
git checkout master
git merge lineA
Updating 58b7dcf..ed40ed2
Fast-forward
请注意,这是一个快进合并,所以它所做的只是将master
移动到ed40ed2:
git log --graph --oneline --decorate
* ed40ed2 (HEAD, master, lineA) A
* 58b7dcf first
最后:
git checkout lineB
git rebase master
Current branch lineB is up to date.
git log --graph --oneline --decorate
* f742aed (HEAD, lineB) B
* ed40ed2 (master, lineA) A
* 58b7dcf first
你写道:
什么?不,主人换了
$ git checkout master
$ cat file
A
b
c
$ git checkout lineB
$ cat file
a
B
c
是的,master
已更改,但不会影响lineB
或lineC
的历史记录master
很快就提交了ed40ed2,它已经是lineB
的父级。确切地说,它是f742aed的父级,这是我为commitB
获得的commit id
对于习惯于其他版本控制系统的人来说,混淆之处在于Git为提交记录而不是分支名称记录了一个树状的数据结构(技术上是DAG)。树枝是短暂的;它们只是标签,就像可移动的版本标签。提交之间的父子关系是您在git log--graph
和其他可视化工具中看到的关系。我也这么认为。使用git扩展查看您的分支树形状。对我来说,您创建的所有分支都源于master,所以git以它的方式告诉您不需要重基。此时,您只需合并