Git的文档的muchderision主题...有很好的理由:
git的变基[-i | --interactive] [选项] [--exec <CMD>] [--onto <newbase>] [<上游> [<分支>]]
此处该参数被标记upstream
,和有帮助的( ?)从命令输出参考git branch --set-upstream-to
和origin/<branch>
,这意味着您的本地分支必须有一个像origin/my-feature
这样的远程分支才能工作。但事实并非如此。
git rebase
做什么是副本一系列提交,每个拷贝发生,如果你想在一个特定的运行git cherry-pick
提交。通过复制每提交一个线性提交图中的提交,您将获得复制开发分支的效果。 我认为,这使得以图表形式更有意义。例如,假设你有这样的顺序:
... <- o <- A <- B <-- master
\
C <- D <- E <-- my-feature
其中每个字母代表一些特定的承诺,其中一个大丑40个字符的SHA-1的数和提交历史my-feature
与commit-连接起来master
的历史记录在提交o
。如果您在master
上创建了新分支my-feature
,然后又回到分支master
,进行了两次提交,然后转至my-feature
并进行了三次提交(每次提交的实际顺序)无所谓:我只需要你在master
上做了两个,现在我把他们作为现在作为第一个A
和第二个B
,并且在my-feature
上有三个。现在
,因为它与发展情况,你可能会决定它将使基础上,master
当前提示,即更有意义C
-through- E
,有C
的父提交是B
。
一个非常手动的方法来实现这一目标是:
$ git checkout master
$ git checkout -b new-my-feature
$ git cherry-pick <id of commit C>
$ git cherry-pick <id of commit D>
$ git cherry-pick <id of commit E>
这使得一个新的分支,new-my-feature
,并复制三个提交,这个结果:
C' - D' - E' <-- new-my-feature
/
... o - A - B <-- master
\
C - D - E <-- my-feature
的方式混帐构造新的提交C'
将比较树 - 关联的源快照 - 对于C
与其父提交o
的树,将相同的更改应用于t ree for B
,然后重新使用提交消息C
进行新的提交。换句话说,提交C'
是C
的“副本”。 D'
与D
相同,E'
与E
相同。
在任何情况下,如果你把这个第三图像,然后删除my-feature
分支标签,并重新命名new-my-feature
到my-feature
,你得到的是:
C' - D' - E' <-- my-feature
/
... o - A - B <-- master
原来的三所老my-feature
提交的“丢失“(他们通过”reflog“条目保存30天,但这些条目通常不可见,以免混淆视图)。
git rebase
所做的是自动执行此过程:它找到要复制的提交序列,将序列复制到其他提交中,然后移动分支标签。
你可以指定的是,所有没有非常好记录的选项都是分支名称 - 默认为当前分支 - 通常在某种程度上,间接地指向停止复制的点。 “目标”提交,重定位为--onto <newbase>
,默认为您给出的参数(如果有的话),请拨打<upstream>
。
这种工作方式依赖于理解其他相当重要的东西,这会影响双点符号。
让我们回到原来的图形,我们再次做任何樱桃采摘和分支标签移动的,也就是说,之前我们变基之前有:
... - o - A - B <-- master
\
C - D - E <-- my-feature
现在让我们来问git的是什么版本在master..my-feature
:
$ git rev-list master..my-feature
e59f6c2d348d465e3147b11098126d3965686098
8413a79e67177d026d2d8e1ac66451b80bb25d62
1f9e0a53489aaca7859722e037a47e93858cbc42
(我做这些,但事实上这种设置,你会真正得到只有三个SHA-1)。
我认为一个很好的方式来解释这是在颜色填充/突出显示(当然,我不能在这里的文字做这个,所以你必须想像它)。
想象一下,您从my-feature
的提示开始,即提交E
。将此提交涂成绿色:这是“要使用”。然后,按照其父指针返回提交D
。将此提交也刷为绿色。跟着那个到C
并且涂绿色;跟着那个到o
并且绘制那个绿色,然后继续到整个图形中的o
的父母。
然后,从master
的提示开始,即提交B
。将此提交涂成红色:“停止”。然后,按照其父母提交A
,并将其涂成红色。按照o
,用红色油漆在绿色涂料上涂漆:“停止”。一路跟随o
的父母,用红漆覆盖他们所有的绿色涂料。
(如果你愿意,你可以做红的第1,那么绿,只要你不覆盖任何红配绿。)
结果,将提交该git rev-list
应该列出,正是那些(仍然)是绿色的提交,这只是我们想要改变的三个提交。即使我们从B
,master
的提示开始了“红色列表”,情况也是如此。
所有这一切的简短版本是,为了重组,我们想要的 - 至少现在 - 是git rebase
将master
视为“上游”。 rebase的“上游”参数提供了“红色颜料”参数,master..my-feature
修订说明符的左半部分和--onto
参数:我们想要复制提交,以便它们在master
的提示最后提交后出现。
实际上,您可以使用git branch --set-upstream-to
将master
(在您自己的私人存储库中)设置为my-feature
的“上游”。上游不一定是像origin/branch
这样的远程跟踪分支。您自己的本地分支机构在此处可以正常工(但是请记住,如果您开始共享此分支 - 将其推送到远程git存储库(如origin
),那么您可能希望在此时开始使用远程跟踪分支作为“上游”,以提醒自己要分享,并获得了较为典型的变基流去。你可以做一个新的git branch --set-upstream-to
在任何时候改变“上游”。)
单词“分支”的另一个git文档问题的例子。它至少有两种不同的含义。在作为该脚注段落的一部分的图表中,master
是一个“分支”(我喜欢称其为“分支标签”或“分支名称”)。同样,my-feature
是一个分支。在这种情况下,这两种标签分别简单地标注一个特定的提交 - B
和E
。但是,每个提交都有其自己的父提交指针:B
指向A
,E
指向D
,依此类推。遵循这些父指向箭头产生的提交链也是一个“分支”。
在其确切点停止调用此类链“分支”取决于你的观点:my-feature
可能会停止在提交o
,而master
可能会继续回通过o
。 Git在这里并没有太多的帮助,尽管没有总是正确的答案:它确实取决于你想包含的内容。
有做这一个稍微更简单的方法,因为不是一个承诺作为参数git cherry-pick
可以采取更多:
$ git cherry-pick <id> <id> <id>
例如,或者:
$ git cherry-pick my-feature~3..my-feature
它使用在the gitrevisions documentation中描述的说明符可以让git找到这三个ID。
像'HEAD〜1'(在最后一次提交之前提交)这样的表达式也应该有效。如果有足够的提交,它可能会更容易复制并粘贴来自日志的散列,而不是计算您想要改变的提交数量。 – CoDEmanX