如何以编程方式检测 master 中不正确(未重新定位)的合并气泡?
How to programmatically detect incorrect (not rebased) merge bubbles in master?
我们的开发流程指出,每个开发人员都应该首先将 his/her 主题 b运行ch 变基为 master,然后将其与 --no-ff
标志合并,以创建合并气泡。这会产生一个漂亮且易于遵循的历史图表。
然而,有时开发人员不小心通过 GitHub 用户界面而不是通过 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
|\
| * ...
|/
* ...
...
(我正在将提交 E
和 C
更改为 '
素数,因为它们会有不同的哈希值)
我们需要以编程方式获取此类损坏的合并提交的列表,例如 E
。
git rev-list --merges --format='%h %p' A..G | grep -v '^commit'
产生以下输出:
G E F
E C D
C A B
第一列表示合并提交,第二列是第一个父项(也是合并提交),第三个是第二个父项 - 来自主题 b运行ch 的提交。
但是,损坏的合并的父关系似乎没问题 - 当 运行 在固定的 Git 历史记录(第二张图)上时,命令给出相同的输出,所以我们无法识别它。
必须有另一种方法来检测项目中损坏的合并提交。请注意,要求 git
在历史记录中的每个提交上执行的解决方案不是首选,因为某些项目有 50k+ 提交,并且单个 git
执行需要超过 2 秒。
您的问题简化为一个简单的图形规则:
master
中的每个第一父项都应该是合并提交。 (即使对于“坏”图也是如此,但它可能值得检查——如果你允许修补程序在没有合并气泡的情况下进入 master,则应识别任何此类提交,然后不受其他规则的约束。请注意root 提交可能不会遵循此规则,并且可能存在一些截止点,早期提交不遵循 any 规则,您应该停止查找。)
每个这样的提交都会有一个 second-parent。该提交及其所有父项都应该是简单的(单亲)提交,直到它们也可以从导致此第二父项提交的合并的第一个父项访问到它们——这通过合并气泡本身进行跟踪——and(这是关键测试)与master
重新加入的提交应该是合并的另一个父级,它让你失望了合并气泡。
第二条规则为您识别提交 D
:D
的第一个也是唯一的父级是 A
,而它的父级应该是 C
。
所以,请阅读图表。您可以直接执行此操作(例如,在 GitPython 或其他软件中),或使用 git rev-list --topo-order --parents master
将图形读入文本,然后使用程序读取。
如,如果你能在一开始就防止意外合并,那是最好的方法,因为事后修复这些是一种历史重写形式,需要所有用户适应到重写的历史。
我们的开发流程指出,每个开发人员都应该首先将 his/her 主题 b运行ch 变基为 master,然后将其与 --no-ff
标志合并,以创建合并气泡。这会产生一个漂亮且易于遵循的历史图表。
然而,有时开发人员不小心通过 GitHub 用户界面而不是通过 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
|\
| * ...
|/
* ...
...
(我正在将提交 E
和 C
更改为 '
素数,因为它们会有不同的哈希值)
我们需要以编程方式获取此类损坏的合并提交的列表,例如 E
。
git rev-list --merges --format='%h %p' A..G | grep -v '^commit'
产生以下输出:
G E F
E C D
C A B
第一列表示合并提交,第二列是第一个父项(也是合并提交),第三个是第二个父项 - 来自主题 b运行ch 的提交。 但是,损坏的合并的父关系似乎没问题 - 当 运行 在固定的 Git 历史记录(第二张图)上时,命令给出相同的输出,所以我们无法识别它。
必须有另一种方法来检测项目中损坏的合并提交。请注意,要求 git
在历史记录中的每个提交上执行的解决方案不是首选,因为某些项目有 50k+ 提交,并且单个 git
执行需要超过 2 秒。
您的问题简化为一个简单的图形规则:
master
中的每个第一父项都应该是合并提交。 (即使对于“坏”图也是如此,但它可能值得检查——如果你允许修补程序在没有合并气泡的情况下进入 master,则应识别任何此类提交,然后不受其他规则的约束。请注意root 提交可能不会遵循此规则,并且可能存在一些截止点,早期提交不遵循 any 规则,您应该停止查找。)每个这样的提交都会有一个 second-parent。该提交及其所有父项都应该是简单的(单亲)提交,直到它们也可以从导致此第二父项提交的合并的第一个父项访问到它们——这通过合并气泡本身进行跟踪——and(这是关键测试)与
master
重新加入的提交应该是合并的另一个父级,它让你失望了合并气泡。
第二条规则为您识别提交 D
:D
的第一个也是唯一的父级是 A
,而它的父级应该是 C
。
所以,请阅读图表。您可以直接执行此操作(例如,在 GitPython 或其他软件中),或使用 git rev-list --topo-order --parents master
将图形读入文本,然后使用程序读取。
如