1

我们的开发流程规定每个开发人员都应该先将他/她的主题分支变基为 master,然后将其与--no-ff标志合并,以创建合并气泡。这会产生一个漂亮且易于遵循的历史图表。但是,有时开发人员会不小心通过 GitHub 用户界面而不是通过 Git CLI 合并他们的拉取请求,Git CLI 在实际合并之前不会变基,从而导致以下“混乱”的历史图表:

*   G
|\
| * F
|/
*   E Merge pull request #123 from feature-three
|\
| * D
* |   C
|\ \
| |/
|/|
| * B
|/
*   A
|\
| * ...
|/
*   ...
...

如果遵循该过程,我们将看到以下历史图表:

*   G
|\
| * F
|/
*   E' Merge branch 'feature-three'
|\
| * D
|/
*   C'
|\
| * B
|/
*   A
|\
| * ...
|/
*   ...
...

(我正在更改提交EC进行'初始化,因为它们会有不同的哈希值)

我们需要以编程方式获取此类损坏的合并提交的列表,例如E.

git rev-list --merges --format='%h %p' A..G | grep -v '^commit'产生以下输出:

G E F
E C D
C A B

第一列代表合并提交,第二列是第一个父级(也是合并提交),第三列是第二个父级 - 来自主题分支的提交。但是,损坏的合并的父关系似乎没问题 - 该命令在固定的 Git 历史记录(第二张图)上运行时给出相同的输出,因此我们无法识别它。

必须有另一种方法来检测项目中损坏的合并提交。请注意,不需要git在历史记录中的每个提交上执行的解决方案,因为某些项目有 50k+ 提交,并且单次git执行需要超过 2 秒。

4

1 回答 1

0

您的问题简化为一个简单的图形规则:

  • 每个第一父级都master应该是一个合并提交。(即使对于“坏”图也是如此,但它可能值得检查——如果您允许修补程序在没有合并气泡的情况下进入 master,则应识别任何此类提交,然后不受其他规则的约束。请注意,根提交可能不会遵循此规则,并且可能存在一些截止点,早期的提交不遵循任何规则,您应该停止查找。)

  • 每个这样的提交都会有第二个-parent。该提交及其所有父级应该是简单的(单父级)提交,直到它们也可以从导致该第二父级提交的合并的第一个父级访问——这将通过合并气泡本身进行追踪——<em>并且(这是关键测试)重新加入的提交master应该是合并的另一个父级,它使您在合并气泡的这一侧下降。

第二条规则D为您识别提交:D的第一个也是唯一的父级是A,而它的父级应该是C

所以,只需阅读图表。您可以直接执行此操作(例如,在 GitPython 或其他方式中),或者使用git rev-list --topo-order --parents master将图形读入文本,然后使用程序读取。

正如Nitsan Avni 在评论中建议的那样,如果您可以首先防止意外合并,那是最好的方法,因为事后修复这些是历史重写的一种形式,这需要所有用户适应重写的历史.

于 2020-07-06T17:49:51.433 回答