为什么git rebase没有';我不想打壁球吗?

为什么git rebase没有';我不想打壁球吗?,git,Git,我正准备对我正在处理的分支发起一个请求。在github上,我看到我比master提前了5次提交,所以我想将我的提交压缩成一次。我运行git日志以查看以前的提交是什么: git log --oneline 4363273 Updated Order_Entry with bulk UPDATE command e7e0c64 Updated Order Entry module and Orders Schema 2cff23e Merge branch 'order_schema' 104b2

我正准备对我正在处理的分支发起一个请求。在github上,我看到我比master提前了5次提交,所以我想将我的提交压缩成一次。我运行git日志以查看以前的提交是什么:

git log --oneline

4363273 Updated Order_Entry with bulk UPDATE command
e7e0c64 Updated Order Entry module and Orders Schema
2cff23e Merge branch 'order_schema'
104b2ce Orders Schema
f7d57cf Order Entry updated to handle and log responses from LC
afa1b7b Merge pull request #18 from project/bugfix/mockvenue
4b2c8d8 Return correct string in mock venue API
现在我想我想挤压上面列出的前5个提交(4363273-f7d57cf)。于是我就跑:

git rebase -i HEAD~5

4363273 Updated Order_Entry with bulk UPDATE command
pick 44768b2 Add script to run simulation on a strategy
pick f82ec8d Implement mock venue
pick f7d57cf Order Entry updated to handle and log responses from LC
pick 4b2c8d8 Return correct string in mock venue API
pick 104b2ce Orders Schema
pick 4363273 Updated Order_Entry with bulk UPDATE command
为什么运行git rebase后显示的提交列表与运行git log时的前5个提交不匹配。特别是,为什么e7e0c64和2cff23e出现在git日志中而不是git rebase中

* 4363273 Updated Order_Entry with bulk UPDATE command
*   e7e0c64 Updated Order Entry module and Orders Schema
|\
| *   2cff23e Merge branch 'order_schema'
| |\
| | * 104b2ce Orders Schema
| * |   afa1b7b Merge pull request #18 from project/bugfix/mockvenue
| |\ \
| | |/
| |/|
| | * 4b2c8d8 Return correct string in mock venue API
| |/
* | f7d57cf Order Entry updated to handle and log responses from LC
|/
*   8ed2260 Merge pull request #17 from project/mockvenue

您的图表显示了大量合并。这是问题的根源。这里值得注意的是,
HEAD~5
的意思是“在
之后向后退五步--first parent


让我们先介绍一下背景知识。一般来说,您不能对合并重新设置基础,并且重新设置基础通常不会尝试(它通常只是丢弃它们)。使用
git-rebase-p
将尝试保留合并,并且通常会成功,但是交互使用非常困难(因为编辑脚本没有合并的表示)

一旦我们了解了rebase的工作原理,我们就可以看到更多。假设我们有这样一个提交图:

          B - C - D   <-- other-branch
        /
... - A
        \
          E - F - G   <-- your-branch
          B - C - D   <-- other-branch
        /           \
... - A               E' - F' - G'   <-- your-branch
        \
          E - F - G   [reflog only]
如果我们尝试对合并提交执行相同的操作,我们会遇到问题。合并有两个(或多个)父级,在没有人工帮助的情况下无法进行cherry pick:您必须告诉git cherry pick要区分的父级是哪个

git-rebase-p所做的是重做合并,而不是尝试一次挑选。rebase文档有这样一个示例,在这个示例中,您可以将
A
重设为
Q

                  X
                   \
                A---M---B
               /
       ---o---O---P---Q
它们不显示结果,但应该是这样的(理想情况下,原始
A--M--B
序列灰显):

请注意,新提交
M'
必须是
a'
和(未更改的)提交
X
之间的合并。如果合并是一个正常的(非“邪恶”)合并,但显然有点棘手,至少是这样


让我们回到您的特定情况,在这里,
git log--graph
给出了下面的文本(我只是稍微修改了一下)。从侧面看有点困难(上面的其他图表在左边有前置提交,在右边有后续提交,而
git log--graph
输出在下面有前置提交,在上面有后续提交),但我将快速尝试一下,为每个提交添加单字母代码:

H   * 4363273 Updated Order_Entry with bulk UPDATE command
G   *   e7e0c64 Updated Order Entry module and Orders Schema
    |\
F   | *   2cff23e Merge branch 'order_schema'
    | |\
E   | | * 104b2ce Orders Schema
D   | * |   afa1b7b Merge pull request #18 from project/bugfix/mockvenue
    | |\ \
    | | |/
    | |/|
C   | | * 4b2c8d8 Return correct string in mock venue API
    | |/
B   * | f7d57cf Order Entry updated to handle and log responses from LC
    |/
A   *   8ed2260 Merge pull request #17 from project/mockvenue
现在,将
A
作为最左边的提交,将
H
作为最右边的提交:

    C---D
   /___/ \
  //__--E-F
 ///       \
A-----B-----G--H
直系(第一亲)祖先从
H
G
,然后到
B
,再到
A
。这意味着
HEAD~5
是一个我们甚至看不到的提交(在
a
的左边两个),并且
git-rebase-i HEAD~5
应该列出除合并之外的所有提交(
D
F
G
)。这将是五个提交:
A
B
C
E
,和
H
。但是根据它的日志消息,
A
也是一个合并。我们在这里缺少信息,无法绘制完整的图形(因为紧凑形式中有很多线,所以也可以)

无论如何,事实上,这就是正在发生的事情。
rebase
命令通过列出从tip commit(
HEAD
,也就是commit
H
)中可到达的每个提交(第一次排除的提交(
HEAD~5
,在
a
左侧的两个提交步骤,因此我们看不到它),来查找对cherry pick的提交。然后,它抛出合并提交,并将挑选每个剩余的提交来构建一个新的线性分支


这是否有意义,以及您应该选择哪些提交,都不是任何其他人可以回答的问题。

git log
按日期排序(默认情况下),但是
git-rebase
必须(因此确实)使用拓扑顺序。如果将
--graph
添加到
git日志--oneline
,会发生什么?(使用
--graph
显示提交图,并强制
git log
进行拓扑排序。)(您还可以添加
--decoration
,它将显示分支名称等,尽管使用
--all
比不使用它时更有趣。)@torek我发布了该图。我正在查看它,但仍然不明白为什么在运行rebase命令时e7e0c64和2cff23e没有出现。哇。谢谢你的解释。真的让我明白了一些。我原以为我理解rebase,但显然还有很多。所以在我按字母顺序排列的图表中,当我运行rebase时,提交A、D、F和G不会出现,因为它们都是合并提交?是的(很抱歉延迟响应,我周末外出旅行)。这是一个多么好的答案啊。解释得很好。非常感谢你的帮助。
    C---D
   /___/ \
  //__--E-F
 ///       \
A-----B-----G--H