Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个git rebase认为存在';没什么可做的?_Git - Fatal编程技术网

为什么这个git rebase认为存在';没什么可做的?

为什么这个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

在本例中,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 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命令显示commit
A
(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的父级,这是我为commit
B
获得的commit id


对于习惯于其他版本控制系统的人来说,混淆之处在于Git为提交记录而不是分支名称记录了一个树状的数据结构(技术上是DAG)。树枝是短暂的;它们只是标签,就像可移动的版本标签。提交之间的父子关系是您在
git log--graph
和其他可视化工具中看到的关系。

我也这么认为。使用git扩展查看您的分支树形状。对我来说,您创建的所有分支都源于master,所以git以它的方式告诉您不需要重基。此时,您只需合并