【问题标题】:Determine commits introduced to branch by merge commit in git?确定通过git中的合并提交引入分支的提交?
【发布时间】:2018-03-12 06:43:11
【问题描述】:

我正在尝试确定由于使用合并 ID 进行合并而引入父分支的提交。

【问题讨论】:

    标签: git merge git-merge git-log git-rev-list


    【解决方案1】:

    命令git log <id>~1..<id> 将列出所有合并的提交,以及合并提交本身。

    【讨论】:

    • 这是进行任何真正合并的方法。如果要排除合并本身,请使用id^1..id^2
    【解决方案2】:

    TL;DR

    使用max630's answer,只要它是真正的合并。要排除合并本身,请使用它的轻微变体:M^1..M^2

    您在这里要求的是找到由于合并而变得可达的提交。这个可达性的想法是一个图论概念。因此,如果你画出合并的结果,答案就更清楚了。

    找到合并基地

    假设“合并前”图表如下所示,其中* 是合并基础提交,LR 是左侧和右侧提示提交:

    ...--*--...--L   <-- mainline
          \
           o--...--R   <-- sidebranch
    

    那么“合并后”的图是这样的:

    ...--*--...--L---M   <-- mainline
          \         /
           o--...--R   <-- sidebranch
    

    现在很明显,新引入的提交是 :-) 沿着底行的提交,即那些可从(并包括)R 到达的提交,但不包括合并基础提交。我们从M 的第二个父级(即R)开始到达它们,然后沿着从R 到其父级的反向连接,到另一个父级,依此类推。这些通向底部的o 节点,该节点连接回提交*

    如果你有一个像sidebranch 这样指向R 的名字,你只需要找到合并基:

    mb=$(git merge-base $all mainline^1 sidebranch)
    

    它使用“提交的第一父”语法来识别提交L 和提交M^1 后缀。如果您不再拥有名称 sidebranch,则可以使用“提交的第二个父级”语法来识别提交 R

    mb=$(git merge-base $all mainline^1 mainline^2)
    

    很遗憾,这不是唯一可能的输入图。典型的“合并前”图表如下所示:

    ...--*   <-- mainline
          \
           o--...--R   <-- sidebranch
    

    在没有--no-ff 的情况下运行git merge 将执行“快进”操作,这实际上不是合并:您最终会得到一个线性图并且没有合并提交:

    ...--*--o--...--R   <-- mainline, sidebranch
    

    在这里,除非您仍然有主线分支的 reflog 条目,否则实际上不可能找到提交 *。如果您确实有 reflog 条目,这很简单:它是mainline@{<em>number</em>},使用适当的number。 (找到合适的 number 是查看 reflog 以查找来自快进的更新。如果您刚刚进行了合并,它只是 1 并且也是 @ 987654352@.)

    mb=$(git rev-parse mainline@{1})   # for instance
    

    我将$all 放在上面查找合并基的示例命令中的原因是,当您有多个合并基时,还有第三种可能性:

    ...--o--*---o--...--L
             \ /
              X
             / \
    ...--o--*---o--...--R
    

    在这里,您将要排除所有合并基础。如有必要,将$all 替换为--all

    现在您拥有所需的一切

    现在您知道了合并基础,如果合并是真正的合并,则使用 git merge-base 找到它们,通过合并可以访问的提交只是那些可以从 R 本身访问的提交,但不是来自合并基地:

    git rev-list sidebranch --not $mb
    

    如果您想检查提交而不是简单地枚举提交,请使用 git log 而不是 git rev-list

    简化这个

    以上所有内容都旨在找到合并基并排除它们,以便我们获得提交 R 及其可访问的祖先,而无需从 L 获得任何可访问的提交。但是我们不必开始这个排除特别从合并基础。我们可以从L 本身开始。

    要命名L,我们只需要命名mainline的前一个值或合并M的第一个父级。 M的第一个parent是M^1M~1,所以只要知道M的hash ID,就可以加上后缀说“排除这些”。

    甚至还有一个简写语法。而不是:

    git rev-list M^2 --not M^1
    

    或略短:

    git rev-list M^2 ^M^1
    

    我们可以使用两点语法:

    git rev-list M^1..M^2
    

    这是我们在顶部所拥有的。

    请注意,所有这些都假定“真正的合并”:如果合并是快进,则必须改用 reflog。

    【讨论】:

    • 感谢您的详细解释。在快进合并的情况下如何计算??
    • 这就是中间的东西(不是很好放置)进来的地方:你必须使用 reflog。如果要找到信息,那就是找到它的地方。请注意,reflog 条目最终会过期,并且 reflog 不会传输到存储库的克隆。
    【解决方案3】:

    您可以签出分支并使用 git log 查看分支中的提交和提交 ID。 git log -n10 --oneline 将为您提供该分支中前 10 次提交的历史记录。

    【讨论】:

      猜你喜欢
      • 2012-08-31
      • 2012-03-02
      • 2014-01-22
      • 1970-01-01
      • 2018-05-10
      • 1970-01-01
      • 2017-01-24
      • 2021-06-26
      • 1970-01-01
      相关资源
      最近更新 更多