【问题标题】:git log revision range gives incorrect range of commitsgit log revision range 给出了不正确的提交范围
【发布时间】:2014-08-05 05:22:31
【问题描述】:

我正在尝试使用git log 的参数列出分支上给定范围内的所有提交。出于某种原因,它似乎没有给我正确的结果(或者我可能理解错误的命令?)。

这是我正在做的事情的步骤:

  1. 克隆仓库

    git clone https://github.com/openstack/nova.git

  2. 执行git log,这是最后 9 次提交:

    d5bde44 Merge "Make metadata password routines use Instance object"
    6cbc9ee Merge "Fix object change detection"
    39b7875 Merge "Fix object leak in nova.tests.objects.test_fields.TestObject"
    94d1034 Merge "maint: correct docstring parameter description"
    6407f17 Merge "Fix live_migration method's docstring"
    7406661 Merge "Fix infinitely reschedule instance due to miss retry info"
    9d8a34f Merge "Remove unused code from test_compute_cells"
    429cd4b Fix object change detection
    01381b8 Fix object leak in nova.tests.objects.test_fields.TestObject
    ...
    
  3. 假设我想获得从01381b8 开始的所有提交。我发出git log 01381b8..HEAD 并看到以下输出:

    d5bde44 Merge "Make metadata password routines use Instance object"
    6cbc9ee Merge "Fix object change detection"
    39b7875 Merge "Fix object leak in nova.tests.objects.test_fields.TestObject"
    94d1034 Merge "maint: correct docstring parameter description"
    6407f17 Merge "Fix live_migration method's docstring"
    7406661 Merge "Fix infinitely reschedule instance due to miss retry info"
    9d8a34f Merge "Remove unused code from test_compute_cells"
    429cd4b Fix object change detection
    2214bc0 Remove unused code from test_compute_cells
    9639b55 Fix infinitely reschedule instance due to miss retry info
    a5184d3 Fix live_migration method's docstring
    76729a3 maint: correct docstring parameter description
    28224a6 Make metadata password routines use Instance object
    

哇!当我预期 8 时,我实际上在该输出中得到了 13 个提交。这里发生了什么?修订范围是否是在给定提交后获取显示提交的正确机制?或者这是一个错误?

【问题讨论】:

  • 可能不是错误。当您执行git log --oneline --graph 时,无论有无修订范围,您会得到什么样的输出?

标签: git version-control git-branch dvcs git-log


【解决方案1】:

这里的问题在于“之后”的模糊概念。

提交与其说是“之前”和“之后”,不如说是“嵌入到图表中”。在这种情况下,由于存储库是可克隆的,我克隆了它。显然它相当活跃:

$ git log --oneline -9
77bad25 Merge "Remove deprecated config option names: Juno Edition"
d4d712a Merge "Deprecate instance_get_by_uuid() from conductor"
d5bde44 Merge "Make metadata password routines use Instance object"
6cbc9ee Merge "Fix object change detection"
39b7875 Merge "Fix object leak in nova.tests.objects.test_fields.TestObject"
94d1034 Merge "maint: correct docstring parameter description"
6407f17 Merge "Fix live_migration method's docstring"
7406661 Merge "Fix infinitely reschedule instance due to miss retry info"
9d8a34f Merge "Remove unused code from test_compute_cells"

这比你的 last-9 输出更新。不过,更有趣的是,如果在记录时添加了--graph(我会将数字增加到 10),这些看起来会如何:

$ git log --oneline --graph -n 10

*   77bad25 Merge "Remove deprecated config option names: Juno Edition"
|\  
| * d0a02fa Remove deprecated config option names: Juno Edition
* |   d4d712a Merge "Deprecate instance_get_by_uuid() from conductor"
|\ \  
| * | 1d340cc Deprecate instance_get_by_uuid() from conductor
* | |   d5bde44 Merge "Make metadata password routines use Instance object"
|\ \ \  
| |/ /  
| * | 28224a6 Make metadata password routines use Instance object
* | |   6cbc9ee Merge "Fix object change detection"
|\ \ \  
| * | | 429cd4b Fix object change detection
* | | |   39b7875 Merge "Fix object leak in nova.tests.objects.test_fields.TestO
|\ \ \ \  
| |/ / /  
| * | | 01381b8 Fix object leak in nova.tests.objects.test_fields.TestObject

(我们得到一组不同的“最顶层”提交,因为--graph 修改了遍历,这就是我进行 10 次提交的原因)。

要了解这里发生了什么,您需要从git loggit rev-list。像许多 git 命令一样,git log 使用 git rev-list 选择要显示的修订。 (一些 git 命令实际上运行 git rev-list 而其他人共享它的源代码,但无论哪种方式它的工作原理都是一样的。)

git 修订符号x..y^x y 的简写(或y ^x——它们的含义相同)。无论您是写像masterorigin/stable/havana 这样的名称,还是像HEAD 这样的间接名称,或者是原始提交ID,还是像77bad25 这样的缩短的原始提交ID,xy部分被解析为底层的 git 对象(在我们的例子中应该是一个提交)。可以使用git rev-parse观察解析步骤:

$ git rev-parse master
77bad252096f7a4a8174340f0f2a3baf1fd52195
$ git rev-parse HEAD
77bad252096f7a4a8174340f0f2a3baf1fd52195
$ git rev-parse origin/stable/havana
0bf0bb4b5df64f7266c903a986d0b90a1f223822

git rev-list 对此所做的是从该提交向后工作以找到其父提交,然后从这些提交到其父提交,依此类推。结果是祖先集。

master 的祖先在这一点上没有特别的顺序:

  • master 本身:77bad25...
  • master 的第一任父母,git rev-parse master^1d4d712a...
  • master的第二个父母,git rev-parse master^2d0a02fa...
  • master的第一个父母的第一个父母,git rev-parse master^1^1d5bde44...
  • master的第一个父母的第二个父母,git rev-parse master^1^21d340cc...

当然还有更多,返回许多提交:

$ git rev-list master | wc -l
   27918

所以git rev-list master 选择所有 27 万个提交,git log master 会显示所有提交(按某种顺序,根据通过 git log 传递给 git rev-list 的其他选项修改顺序)。

要排除其中一些,您可以告诉git rev-list 从某个特定修订开始——例如01381b8——并找到它的所有祖先(包括01381b8 本身):

$ git rev-list 01381b8 | wc -l
   27901

此时,这比从master 开始并向后工作(并且第二个列表中没有不在第一个列表中的提交)所发现的提交减少了 17 个。所以如果你告诉git rev-list 给你“所有从master 开始的提交,减去从01381b8 开始的所有提交”,你应该得到17 个提交:

$ git rev-list master ^01381b8 | wc -l
      17

这就是我们所看到的。 (实际的列表并没有那么有趣,但您可以使用git rev-list master ^01381b8 或等效的git rev-list 01381b8..master 查看它。)

这些提交是 git log 将向您展示的提交,给定相同的修订范围。

您可以花几天时间研究 git rev-list 文档,但仍然遗漏了一些项目(例如,--graph 告诉您它“启用父级重写”和“暗示 --topo-order”,直到我刚才检查,我都忘记了关于父级重写部分。幸运的是,这无论如何都不适用于这里,只是需要--date-order 强制图形版本按日期而不是拓扑排序。)

【讨论】:

    【解决方案2】:

    使用以下命令,

    git log --graph --pretty=format:'%Cblue%h%Creset -%C(red)%d%Creset %s %Cgreen(%cr) %C(粗蓝色)%Creset' --abbrev-commit

    它会在一行中以丰富多彩的方式为您提供提交日志,其中包含分支名称、作者详细信息、图表、日期。

    试试这个!!真是太棒了。

    【讨论】:

    • 我可以知道给-1的原因吗:(
    • 不是我的反对意见,但也许你的回答被反对了,因为它并没有真正回答问题,而是对 toreks 帖子的评论。
    • @Lekensteyn:感谢您的更新!根据我对这个问题的理解,正确获取日志是这个问题的主要目的。我的回答真的会增加提问的意图。
    • @trinth:我希望我能满足您提出问题的主要意图。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 2021-04-29
    • 2016-09-16
    • 2020-12-18
    • 1970-01-01
    • 2018-03-11
    相关资源
    最近更新 更多