列出给定树形哈希id的所有提交

时间:2018-01-10 13:28:36

标签: git

如何列出具有给定树哈希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"

2 个答案:

答案 0 :(得分: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 <tree id>(或修改脚本以仅输出您想要的特定信息)。

答案 1 :(得分:0)

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>