从Github网站或API中获取分支合并列表是否可能?

59
在我们的工作流程中,没有直接提交到主分支(master branch)的操作。主分支只接受来自拉取请求(Pull Requests)的合并操作。
可以将每个合并操作视为添加到主分支的新功能。
因此,我想以列表形式获取合并到主分支的内容,作为一种可视化的方式,以展示添加到产品中的功能块随时间而变化。
Git或Github API是否提供此查询,还是我需要解析原始提交记录?
3个回答

89

我使用以下脚本:

git log main --first-parent --merges \
        --pretty=format:"%h %<(10,trunc)%aN %C(white)%<(15)%ar%Creset %C(red bold)%<(15)%D%Creset %s"

解释每个参数:

  • main: 你的主分支名称。可省略,此时将使用当前分支。
  • --first-parent: 跳过合并分支的提交记录。这将删除某些人将master合并到其分支中的条目。
  • --merges: 仅显示“合并提交”(有多个父提交的提交记录)。如果要查看直接提交到主分支的提交,请省略此参数。
  • --pretty-format: 应用以下格式:
    • %h: 提交的短哈希值;
    • %<(10,trunc)%aN: 作者姓名,截断至10个字符;
    • %<(15)%ar: 相对提交时间,填充至15个字符;
    • %<(15)%D: 标签名称,同样填充至15个字符;
    • %s: 提交信息的第一行。

结果非常令人满意:

terminal image of the command output


5
请注意:这并不与Github有任何关联,而是Git本身内部的功能,这非常好。 - Jim Aho
我想将内容直接输出到文本文件并查看完整的历史记录,因此我使用以下命令:git log --first-parent master
--pretty=format:"%h, %<(10,trunc)%aN, %ai, %s, %<(50,trunc)%b"
- Bryan
能否将合并请求的编号添加到此列表中? - Viesturs
1
小修正,我不认为--first-parent需要参数。你示例中的“master”只是传递给日志的分支。 - Scott
1
你是对的,@Scott。我已经更新了答案,并且澄清了--merges的用法。 - Fábio Batista

17

通过git log命令,Git提供了一些过滤渲染提交的开关,
其中一个适合您的请求:

  • --merges 仅打印合并提交。这与 --min-parents=2 完全相同。

下面显示的是从LibGit2Sharp项目的 vNext 分支可达的合并提交(即具有多个父级的提交)

$ git log vNext --merges --oneline
090b2de Merge pull request #348 from jamill/credential_callback_fix
0332c35 Merge pull request #260 from ben/great-renaming
3191c1b Merge pull request #239 from ben/libgit2-upgrade-81eecc3
1d544e8 Merge branch 'vNext'
238d259 Merge remote-tracking branch 'origin/master'

更新

可以通过 GitHub API 获取相同的输出,但可能会更加复杂。

这需要检索分支上的所有提交,分页浏览所有结果(以检索所有提交元数据),同时过滤掉仅公开一个父节点的提交。

作为起点,以下URL显示了vNext分支的最新30次提交。


8
如果您想关注合并提交,这些提交是由于合并拉取请求而产生的,您可以考虑使用新的Git 2.27(2020年第二季度)git log --show-pulls选项。
"git log"已学习"--show-pulls",有助于路径规范限制历史视图;除了引入真正更改的提交外,还显示从侧面分支中获取整个更改的合并提交,这通常会被省略。

请看提交8d049e1(2020年4月10日),作者是Derrick Stolee (derrickstolee)
(由Junio C Hamano -- gitster --合并于提交9af3a7c,2020年4月22日)

revision: --show-pulls添加了有用的合并信息

签名作者:Derrick Stolee

"git log --<path>"或"git rev-list --<path>"的默认文件历史简化侧重于提供最小的一组提交,这些提交首次贡献了更改。
修订遍历通过仅访问合并提交的第一个TREESAME父提交(如果存在),极大地限制了遍历提交的集合。这意味着不会遍历提交图中的某些部分,这可能会带来性能上的好处,但也可能会“隐藏”添加更改但被合并解决方案忽略的提交。

(TREESAME:路径规范在相应树之间没有明显的区别;“在树之间相同”)

The --full-history option modifies this by walking all commits and reporting a merge commit as "interesting" if it has any parent that is not TREESAME.
This tends to be an over-representation of important commits, especially in an environment where most merge commits are created by pull request completion.

Suppose we have a commit A and we create a commit B on top that changes our file.
When we merge the pull request, we create a merge commit M.
If no one else changed the file in the first-parent history between M and A, then M will not be TREESAME to its first parent, but will be TREESAME to B. Thus, the simplified history will be "B". However, M will appear in the --full-history mode.

However, suppose that a number of topics T1, T2, ..., Tn were created based on commits C1, C2, ..., Cn between A and M as follows:

A----C1----C2--- ... ---Cn----M------P1---P2--- ... ---Pn
 \     \     \            \  /      /    /            /
  \     \__.. \            \/ ..__T1    /           Tn
   \           \__..       /\     ..__T2           /
    \_____________________B  \____________________/

If the commits T1, T2, ... Tn did not change the file, then all of P1 through Pn will be TREESAME to their first parent, but not TREESAME to their second.
This means that all of those merge commits appear in the --full-history view, with edges that immediately collapse into the lower history without introducing interesting single-parent commits.

The --simplify-merges option was introduced to remove these extra merge commits.
By noticing that the rewritten parents are reachable from their first parents, those edges can be simplified away.
Finally, the commits now look like single-parent commits that are TREESAME to their "only" parent. Thus, they are removed and this issue does not cause issues anymore.

However, this also ends up removing the commit M from the history view!
Even worse, the --simplify-merges option requires walking the entire history before returning a single result.

Many Git users are using Git alongside a Git service that provides code storage alongside a code review tool commonly called "Pull Requests" or "Merge Requests" against a target branch.

When these requests are accepted and merged, they typically create a merge commit whose first parent is the previous branch tip and the second parent is the tip of the topic branch used for the request.
This presents a valuable order to the parents, but also makes that merge commit slightly special. Users may want to see not only which commits changed a file, but which pull requests merged those commits into their branch.
In the previous example, this would mean the users want to see the merge commit "M" in addition to the single- parent commit "C".

Users are even more likely to want these merge commits when they use pull requests to merge into a feature branch before merging that feature branch into their trunk.

In some sense, users are asking for the "first" merge commit to bring in the change to their branch. As long as the parent order is consistent, this can be handled with the following rule:

"Include a merge commit if it is not TREESAME to its first parent, but is TREESAME to a later parent."

These merges look like the merge commits that would result from running "git pull <topic>" on a main branch.
Thus, the option to show these commits is called "--show-pulls".
This has the added benefit of showing the commits created by closing a pull request or merge request on any of the Git hosting and code review platforms.

To test these options, extend the standard test example to include a merge commit that is not TREESAME to its first parent. It is surprising that that option was not already in the example, as it is instructive.

In particular, this extension demonstrates a common issue with file history simplification. When a user resolves a merge conflict using "-Xours" or otherwise ignoring one side of the conflict, they create a TREESAME edge that probably should not be TREESAME.
This leads users to become frustrated and complain that "my change disappeared!"

In my experience, showing them history with --full-history and --simplify-merges quickly reveals the problematic merge.
As mentioned, this option is expensive to compute.

The --show-pulls option might show the merge commit (usually titled "resolving conflicts") more quickly.
Of course, this depends on the user having the correct parent order, which is backwards when using "git pull master" from a topic branch.

There are some special considerations when combining the --show-pulls option with --simplify-merges.
This requires adding a new PULL_MERGE object flag to store the information from the initial TREESAME comparisons. This helps avoid dropping those commits in later filters. This is covered by a test, including how the parents can be simplified. Since "struct object" has already ruined its 32-bit alignment by using 33 bits across parsed, type, and flags member, let's not make it worse.

PULL_MERGE用于revision.c,其值为1u<<15,与commit-graph.c中的REACHABLE相同。
仅在写入提交图形文件时使用REACHABLE标志,并且使用--show-pulls进行修订遍历不会在同一进程中发生。将来必须注意确保这种情况仍然存在。

更新Documentation/rev-list-options.txt,详细说明此选项的重要细节。这需要更新历史简化部分中的示例,以演示TREESAME第二个父级存在的一些问题。

在此处查看完整示例


2
谢谢!“ --merges” 对我没有用,但这个方法可行! - zenoh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接