我已准备好在我正在处理的分支机构上发起拉取请求。在github上,我看到我提前完成了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 log中而不是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
答案 0 :(得分:15)
您的图表显示了大量合并。这是问题的根源。值得注意的是,HEAD~5
表示“--first-parent
之后的五步”。
首先介绍一下背景知识。一般来说,你不能改变合并,并且rebase通常不会尝试(它通常只是丢弃它们)。使用git rebase -p
将尝试保留合并,并且通常会成功,但是交互式使用非常困难(因为编辑脚本没有合并表示)。
一旦我们了解了rebase如何运作,我们就能看到更多。假设我们有这样的提交图:
B - C - D <-- other-branch
/
... - A
\
E - F - G <-- your-branch
Rebase会进行一系列提交,并将其转换为更改集/修补程序。也就是说,如果您提交的E
,F
和G
提交了A
,则git必须生成从A
到E
的差异},然后从E
到F
,最后从F
到G
。这些代表“如何从基本提交转换”(当前为A
)“到提示,作为一系列修改。”
然后,rebase转向新的基本提交,在本例中为commit D
,并按顺序应用这些补丁。从适用于A
的{{1}}到E
的更改会产生新的提交D
。应用于E'
的从E
到F
的更改会产生新的提交E'
。最终更改为F'
。
更改提交到修补程序(通过将其与其父项进行比较)然后应用修补程序实际上是G'
。换句话说,git cherry-pick
只是一系列挑选操作,将提交rebase
,E
和F
提取到从G
延伸的新分支上。新的提交图如下所示:
D
如果我们尝试使用合并提交执行相同的操作,则会遇到问题。合并有两个(或更多)父母,如果没有人工帮助,就不能挑选出来:你必须告诉 B - C - D <-- other-branch
/ \
... - A E' - F' - G' <-- your-branch
\
E - F - G [reflog only]
哪个父母是不同的父母。
git cherry-pick
做的是重做合并,而不是尝试樱桃挑选。 rebase文档中有一个示例,您可以在其中将git rebase -p
重新绑定到A
:
Q
他们没有显示结果,但它应该看起来像这样(理想情况下,原始的 X
\
A---M---B
/
---o---O---P---Q
序列是灰色的):
A--M--B
请注意,新提交 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
direct (first-parent)祖先行从 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
也是一个合并。我们在这里缺少信息,无法绘制完整的图表(因为紧凑的表单中有一行 lot ),所以也是如此。
无论如何,这实际上是发生了什么。 A
命令通过列出从 可从 到达的提示提交(rebase
)提交的每个提交来查找提交以进行挑选的提交第一个被排除的提交(HEAD
,提交H
左侧的两个步骤,所以我们看不到它。然后抛出合并提交,并将挑选每个剩余的提交以构建一个新的线性分支。
这是否有意义,以及哪些提交你应该挑选,不是任何其他人都可以为你回答。