Git与--squash合并,同时保留每次提交的日志

时间:2015-10-17 20:30:25

标签: git merge git-squash

初始方案:

A (master)
 \
 B - C  - D (development)

合并后我想要的东西--squash:

A     -     E (master/development)
 \         /
 B - C - D 

在分支master上,git log将是

commit E
    Squashed commit of the following:
    commit D
    commit C
    commit B
commit A

继续开发分支development

A     -     E (master)
 \         / \         
 B - C - D    F - G - H (development)

再次与壁球合并:

A     -     E     -     I(master/development)
 \         / \         /
 B - C - D    F - G - H

在分支master上,git log将是

commit I
    Squashed commit of the following:
    commit H
    commit G
    commit F
commit E
    Squashed commit of the following:
    commit D
    commit C
    commit B
commit A

在分支development上,git log将是

Commit I
Commit H
Commit G
Commit F
Commit E
Commit D
Commit C
Commit B
Commit A

我想与master上压缩的提交合并,同时保留development上的每个提交。

我不知道如何实现它。我的问题是,我不知道如何在第一次合并中D指向E,而I将包含B,C,D,E,F,G,H而不是F,G,H } 只要。

2 个答案:

答案 0 :(得分:2)

您无法使用所显示的结构获得所需的日志结果(git log --merges master将执行此操作)。将为您提供所需日志的结构将失败。而且,最终,这是与Git合作的一种弄巧成拙的方式。

希望能够运行git log master并且只能看到被压缩的提交。这不会奏效。 Git并不知道某些提交适用于master,有些提交适用于development。让我们看一下建议的结构。

A     -     E     -     I [master] [development]
 \         / \         /
 B - C - D    F - G - H

此时,masterdevelopment指向同一个提交。就Git历史而言,它们是相同的。分支只不过是指向提交的标签。 承诺不记得他们承诺的分支git log mastergit log development将生成相同的日志,显示从A到I的所有提交.E和I压缩的提交日志将是多余的。

可以通过git log --merges master(或development)获得你想要的东西,只显示合并提交,但这将显示任何合并提交,甚至是development的一部分。所以它并没有真正发挥作用。

这个想法不必要地复杂化,继续阅读。

要获得所需的日志结果,您可以打破这两个分支之间的关系。

A     -     E     -     I [master]
 \                   
 B - C - D - F - G - H [development]

你可以以某种方式开展工作,但没有意义。 git log master包含所有相同的日志消息,因此它与git log development一样长,但它们会被粉碎在一起。你不能使用git log master进行代码考古(即。"为什么这条线以这种方式编写")因为这些变化都被拼凑成一个差异,这使得更难以关联具有特定提交消息的更改行。由于masterdevelopment的历史记录已取消关联,因此无法确保开发中的所有内容都成为主数据库,反之亦然(例如,主要修补程序)。

git log master提供的信息少于git log development,而 更难以理解masterdevelopment没有任何关联,并且失去了保留合并历史记录的所有好处。维持这种复杂的设置毫无意义。

相反,使用git merge --no-ff合并功能分支(不是一个连续的"开发"分支)并保留分支历史记录以方便考古。

              G - J [feature/tacos]
             /
A     -     E     -     K [master]
 \         / \         /
 B - C - D    F - H - I

E和K是由git merge --no-ff生成的正常合并提交。没有连续的development分支,由功能分支处理。功能分支是一次性使用,一旦合并就删除。有关功能分支的信息将保留在合并提交中,git merge --no-ff可保证分支结构得以保留。 feature/tacos是一个功能分支,用于处理尚未合并的玉米饼。

git log --graph --decorate master将显示master的完整历史记录,其中合并提交显示功能何时结束,以及说明分支历史记录的行。诸如GitX之类的GUI Git历史记录工具是另一种以图形形式读取历史记录的方法。

最后,Git历史是一个图表。如果你学习如何使用Git图表生活会更容易。如果你试着让Git历史变得线性,就像一大堆煎饼一样,你就会打败Git并为自己和其他所有人创造额外的工作。

答案 1 :(得分:0)

好吧,不可能完全你要求的东西,就像你合并分支一样,你会在提交日志中看到来自两个分支的提交。您可能想要的是这样的:

A      -     E (master)
 \         
 B - C - D (development)

你只需从development分支中挑选提交,压缩它们并在master之上应用。

最简单的方法就是这样:

git checkout development && git rebase -i master HEAD

然后用squash替换除第一个之外的所有操作。因此,您将得到一个分离的头部,指向压缩的提交,应用于master之上。您只需将master重置为此提交即可。

我想,提交消息并不是你想要的,因为它将重新提交所有提交的消息,而不是它们的哈希值,但是你将能够使用{{1来挂钩生成提交消息选项。

一切都有点过于手动,但您可以编写所有脚本并创建别名。我相信,这是您使用--exec本身最接近的,而不是用某种更高级别的编程语言重写所有内容。