【问题标题】:Listing all commits given a tree hash id列出给定树哈希 id 的所有提交
【发布时间】:2018-06-19 16:33:07
【问题描述】:

如何列出所有具有给定树哈希 id 的 git 提交? (最顶层的树或子树对象)

我想从每个分支中寻找每个提交,甚至是悬空提交,所以这是在整个 git 数据库中的深度搜索。

示例 - 给定一个包含这些提交的数据库:

COMMIT: a1b2c3, tree abcd00
COMMIT: 9a9b9c, tree 090807 (this tree has a sub-tree abcd00)
COMMIT: aaccdd, tree 02ff00

寻找树对象abcd000 应该列出:

a1b2c3
9a9b9c

编辑:我试过这个命令,但它不适用于子树。顺便问一下,在非分离的 HEAD 上寻找最顶端的树可靠吗?

git  log --oneline --all --pretty="tree %T: commit %H" | grep ^"tree $mytreeid"

【问题讨论】:

  • 要搜索子树,您必须使用git ls-tree,通常使用-r(递归)。但是,树对象通常只是实现细节:有趣的搜索通常是对 blob 对象的搜索。 SO上有关于查找包含指定blob哈希的提交哈希的答案。

标签: git


【解决方案1】:

Git 有一个内置命令来检查给定分支是否包含特定的提交。

git branch --contains <commit>

为了列出包括远程分支在内的所有分支,而不仅仅是本地分支,您需要将-r 添加到命令中。


另一件事:如果您只需要跟踪特定的 文件 而不是提交,则可以使用:

# display list of commits which includes a given file
git log --<file path>

# if the file was also renamed in the past add the `--follow`
git log --follow -- <path>

【讨论】:

  • 在我的情况下,我既没有提交哈希也没有文件名,但是提交是我正在寻找的。我需要找到所有具有给定树哈希 id 的提交。
【解决方案2】:

我认为您可能在此处误用“分离的 HEAD”一词来指代悬空提交(我的答案基于该假设)。

首先,我们需要一个存储库中所有提交的列表,包括当前无法从任何分支、标签或其他引用访问的“悬空”提交。在某些时候,git cat-file 开发了使这变得非常容易的选项:

git cat-file --batch-check --batch-all-objects

如果您的git 版本没有这些选项,则有other ways to get a list of all objects

以上将产生如下输出:

2bd7a7d258cb8c0f529e267e72c37bfee2be3a92 tree 32
2d83b892c0922c9168d3c474e73da24301bc86bf tree 64
3eda82acd62f56b19d88a80650ed88428be8ac9b commit 231
42dae79fef2ede926a081821e6a7cf89387cd9f0 tree 66
5e9fac93b855f5cf5ed44969cf9cc53121195377 blob 29
b01735609620636d7b0179a940f7409a32041f87 commit 182

我们只对提交感兴趣,所以我们会通过 awk 过滤它:

$ git cat-file  --batch-check --batch-all-objects | awk '$2 == "commit" {print $1}'
3eda82acd62f56b19d88a80650ed88428be8ac9b
b01735609620636d7b0179a940f7409a32041f87

现在,对于每次提交,我们需要先提取顶层树 id:

git show --quiet --format='%T' <commit id>

然后递归列出该树中包含的所有树:

git ls-tree -r -t <tree id>

综合起来,我们得到:

#!/bin/sh

git cat-file  --batch-check --batch-all-objects |
    awk '$2 == "commit" {print $1}' |
    while read cid; do
        tree=$(git show --quiet --format='%T' $cid)
        echo $cid $tree
        git ls-tree -r -t $tree |
            awk -v cid=$cid '$2 == "tree" {print cid,$3}'
    done

这将为发现的每个树对象输出一行格式:

<commit id> <tree id>

所以您的问题的答案是将上述脚本的输出通过管道传输到grep &lt;tree id&gt;(或修改脚本以仅输出您想要的特定信息)。

【讨论】:

  • 很好的答案!您能否指出我在哪里可以获得将悬空提交与分离 HEAD 中的提交区分开来的解释?提前 Tnx。
  • 当然。 dangling commit 表示“任何引用都无法访问的提交”。当您签出特定的提交 ID 而不是命名引用时,您会得到一个分离的头(因此它更多地是指当前存储库的状态而不是对象)。
  • 所以,当在一个分离的 HEAD 中时,如果我们创建一个假设为 4 个新提交的链,我们就会有一个分离的 HEAD,其中有 4 个悬空提交和所有其他先前的提交,尽管在同一个分支中但分离HEAD 不是悬空提交(假设我们检查了标记分支中间的任意提交)。是这样吗?
  • 错误...是的。如果您在分离的头上创建提交,那么 git 将无法更新任何引用,因此一旦您更改到另一个分支,它们就会成为悬空提交(在您这样做之前它们仍然被 HEAD 引用) .
猜你喜欢
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 2012-08-26
  • 2016-12-11
  • 2013-09-11
  • 2018-06-21
  • 2023-03-27
  • 2018-10-19
相关资源
最近更新 更多