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

Ziz*_* Wu 5 git merge git-squash

初始场景:

A (master)
 \
 B - C  - D (development)
Run Code Online (Sandbox Code Playgroud)

合并后我想要什么 --squash:

A     -     E (master/development)
 \         /
 B - C - D 
Run Code Online (Sandbox Code Playgroud)

在分支上mastergit log将是

commit E
    Squashed commit of the following:
    commit D
    commit C
    commit B
commit A
Run Code Online (Sandbox Code Playgroud)

继续在分支上开发development

A     -     E (master)
 \         / \         
 B - C - D    F - G - H (development)
Run Code Online (Sandbox Code Playgroud)

再次与壁球合并:

A     -     E     -     I(master/development)
 \         / \         /
 B - C - D    F - G - H
Run Code Online (Sandbox Code Playgroud)

在分支上mastergit 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
Run Code Online (Sandbox Code Playgroud)

在分支上developmentgit log将是

Commit I
Commit H
Commit G
Commit F
Commit E
Commit D
Commit C
Commit B
Commit A
Run Code Online (Sandbox Code Playgroud)

我想与压缩的提交合并,master同时保持每个提交在development.

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

Sch*_*ern 5

您无法使用您显示的结构获得您想要的日志结果(git log --merges master会这样做)。将为您提供所需日志的结构打败了这一点。最后,这是一种弄巧成拙的 Git 工作方式。


我们的愿望是能够运行git log master并且只看到压缩的提交。这行不通。Git 不知道有些提交是为了master,有些是为了development。让我们看看建议的结构。

A     -     E     -     I [master] [development]
 \         / \         /
 B - C - D    F - G - H
Run Code Online (Sandbox Code Playgroud)

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

可以git log --merges master使用(或)获得您想要的内容,development以仅显示合并提交,但这将显示任何合并提交,甚至是作为development. 所以它实际上不起作用。

整个想法不必要地复杂,请继续阅读。


要获得您想要的日志结果,您必须像这样打破两个分支之间的关系。

A     -     E     -     I [master]
 \                   
 B - C - D - F - G - H [development]
Run Code Online (Sandbox Code Playgroud)

你可以以某种方式让它发挥作用,但没有意义。 git log master包含所有相同的日志消息,因此它与 一样长git log development,但它们会被粉碎在一起。您不能用来git log master进行代码考古(即“为什么这一行是这样写的”),因为所有更改都被粉碎到一个差异中,使得将一行更改与特定提交消息关联起来变得更加困难。master由于和的历史development是分离的,因此无法确保开发中的所有内容都成为 master,反之亦然(例如,master 的热修复)。

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
Run Code Online (Sandbox Code Playgroud)

E 和 K 是由 产生的正常合并提交git merge --no-ff。不存在development由特征分支处理的连续分支。功能分支是一次性的,合并后就会被删除。有关功能分支的信息保留在合并提交中,并git merge --no-ff保证保留分支结构。feature/tacos是一个用于尚未合并的 tacos 的功能分支。

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

最后,Git 历史是一个图表。如果你学会了如何使用该图,Git 的生活就会容易得多。如果你试图让 Git 历史线性化,就像一大堆煎饼一样,那么你就违背了 Git 的初衷,并为自己和其他人创造了额外的工作。