只显示作为我的一个提交的祖先的提交?

Show only commits that are ancestors of one of my commits?

我在一个大团队工作,所以有很多来自其他开发人员的功能分支,从 'master' 分支中萌芽。

我自己经常处理多个功能分支,所以我想要一种只列出 "my" 个分支的方法":

如何在命令行上执行此操作?

奖励:我经常使用 Git Extensions 来与 git 存储库进行交互。
它的默认视图显示整个 DAG。

但是,它允许用户通过直接为 git log 命令指定参数来过滤此视图,因此我希望命令行解决方案也可以在 GUI 世界中移植。

git log --pretty="%h %p" --author=<Name> --since="1 month ago"

每一行都有一个或多个提交。第一个是作者是你并且年龄小于 1 个月的提交,其余是它的parents。可以根据需要将额外的占位符和单词添加到格式字符串中。

可以得到git log来做这个,但是你必须分两部分做:

git log --author=... --since=1.month.ago --format=%H | git log --stdin

这是对这两部分的详细解释(在本例中由竖线 | 分隔)。

第一部分是提取您关心的所有 starting-point 提交,为此 git log — 或其管道姊妹命令 git rev-list — 需要通常的 --since and/or --until 对于 date-range-limiting 和 --author 到 select 提交,您是作者。使用 git rev-list 时,默认输出恰到好处:它是 selected 提交的哈希 ID 列表。恼人的是,虽然 git rev-list 因此更合适,但它不支持 --author,所以我们必须使用 git log--format=%H1 不过,为了消除歧义和简单起见,我将使用 git rev-list(并且没有 --format=%H 参数)来显示下面的大部分命令。

既然您已将 selected 提交作为起点哈希 ID,您只需 运行 git log 每个此类哈希 ID。毕竟,git log 所做的是:

  • 查找任何指定哈希 ID 的命令行参数。如果没有这样的参数,请使用 HEAD。这些是起始提交哈希 ID:将它们放入优先级队列中。默认优先级是较新的提交(较晚的提交者时间戳)排在队列的前面,较旧的在后面。

  • 现在队列已准备就绪,运行 一个循环:

    • 从队列中提取提交。
    • 显示它,除非由于其他参数(例如,文件路径名参数,这也会打开历史简化)而不显示它。
    • 将其父级放入队列,除非由于历史简化或 --first-parent.
    • 一些或全部最终不被放入队列


    这个循环 运行s 直到队列为空,或者提交显示限制计数(来自 -n <em>number</em> 或等效参数)运行s out.

请注意,如果您从单个提交哈希 ID 开始——例如由 HEAD 生成的哈希 ID——循环从队列中只有一个提交开始,它会删除并显示。如果该提交有一个父项,则该一个父项进入队列,现在队列的长度为 1,因此 Git 将那个父项从队列中取出,显示 it,并将 父级放入队列中——其长度再次为 1。这会重复直到队列变大(在合并时)或者你到达根提交,这就是为什么一个简单的 git log 的简单存储库有一些分支,但没有合并,只显示当前的提交分支 (HEAD).

不过,对于您的情况,该循环是您的第二部分:

display those plus all their ancestors, regardless of author.

第一部分——要放入优先级队列的提交哈希 ID 集——正是 git rev-list 打印的输出。

唯一棘手的部分在于将 git rev-list 打印的内容(selected 哈希 ID)连接到第二个 git log 命令中。如果您正在使用 Unix-like shell,例如 bash,您可以使用 命令替换:

git log $log_args $(git rev-list $rev_list_args)

This 运行s git rev-list(带任何参数)获取其输出,用空格替换换行符,2 然后 运行 s git log $log_args 附加参数由 git rev-list 的输出组成。

这个 command-substitution 技巧有一个小缺陷:一些系统有参数的最大数量。如果 git rev-list 打印的提交哈希 ID 过多,您会收到错误消息:参数列表太长。 要解决此问题,git log 允许您指定所有的起点作为输入git log,使用--stdin标志:

git rev-list $rev_list_args | git log $log_args --stdin

您可能希望在 $log_args 中包含 --decorate,这样 git log 将在显示时打印指向特定提交的任何分支或标记名称。 (请注意,log.decorate 控制是否隐含 --decorate,并且 log.decorate 已经默认为 auto 很长时间了,因此您可能不需要显式调用它,除非您通过管道传输 git log 输出或将其重定向到文件。)


1在非常旧的 Git 版本中,您必须拼写 arguemnt --pretty=format:%H.

从技术上讲,git log 是 Git 调用的 porcelain 命令,而 git rev-list 是 Git 调用的 管道命令。管道命令旨在生成对后续命令有用的简单输出。那是 git rev-list in a nutshell:它生成散列 ID,这些 ID 大多只对 Git 本身有用。瓷器命令旨在产生 human-usable 输出。 Porcelain 命令 倾向于服从用 git config 设置的用户配置指令:对于我们这里的目的,即仅打印哈希 ID,这实际上很糟糕。确实,git rev-list 应该占用 --author,但至少从 2019 年 11 月起,它并没有占用。

2Git 的关键部分不是 newlines-to-spaces 转换,而是 command-substituted 被拆分成单独的参数词。与其他人命令,但是,命令替换的细节变得很重要。