从提交中获取blob?

时间:2013-01-13 21:17:53

标签: c git libgit2

我试图找出如何为单个提交获取文件列表及其各自的新旧blobs

假设您提交1更改了3个文件。我会运行所述函数并返回3个文件以及它们的旧blob和新blob(假设它们不是二进制文件)。

执行此操作的唯一方法是获取提交和先前提交,解析其树,然后在树上执行diff以找出不同的内容,然后为每个不同的文件获取blob?

3 个答案:

答案 0 :(得分:3)

  

执行此操作的唯一方法是获取提交和先前提交,解析其树,然后在树上执行diff以找出不同的内容,然后为每个不同的文件获取blob?

是的,这是推荐的方法。 “旧”“新”条目只是在比较两个Tree时有意义的概念。

请注意“old”“new”不是那些富有表现力的限定符。如你可以查看 diff header ,条目的差异状态可能是

  • GIT_DELTA_UNMODIFIED = 0,/ **无变化* /
  • GIT_DELTA_ADDED = 1,旧版本中不存在/ **条目* /
  • GIT_DELTA_DELETED = 2,新版本中不存在/ **条目* /
  • GIT_DELTA_MODIFIED = 3,/ **条目内容在新旧之间发生了变化* /
  • GIT_DELTA_RENAMED = 4,/ **条目在旧版和新版之间重命名* /
  • GIT_DELTA_COPIED = 5,/ **条目是从另一个旧条目中复制的* /
  • GIT_DELTA_IGNORED = 6,/ **条目在workdir中被忽略的项目* /
  • GIT_DELTA_UNTRACKED = 7,/ **条目是workdir * /
  • 中未跟踪的项目
  • GIT_DELTA_TYPECHANGE = 8,/ **旧版和新版之间的条目类型更改* /

libgit2 tests-clar/diff/tree 测试文件应该会为您提供此功能的一些示例用法。

更新

在libgit2问题跟踪器中引发了 similar question (来自你?;-))。 @arrbee的答案也依赖于git_diff_tree_to_tree() API

答案 1 :(得分:0)

为先前和当前版本提取SHA1

考虑git自己的存储库中git show --raw v1.8.1^0的输出。

commit 5d417842efeafb6e109db7574196901c4e95d273
Author: Junio C Hamano 
Date:   Mon Dec 31 14:24:22 2012 -0800

    Git 1.8.1

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:100644 100644 fec1a06... d6f9555... M  Documentation/RelNotes/1.8.1.txt
:100644 100644 b0e8f02... 7a3f03b... M  Documentation/git.txt
:100755 100755 b2dffc8... 72e37c9... M  GIT-VERSION-GEN

最后三行表示随该提交而更改的文件。更改行上的第一个SHA1是给定文件的先前版本的对象名称,第二个是命名提交中的blob。例如,GIT-VERSION-GEN中的v1.8.1哈希

$ git show v1.8.1^0:GIT-VERSION-GEN | git hash-object --stdin
72e37c9bfe3e897635f8c211569d9e6f5658a980

与其父提交相关联的blob是

$ git show v1.8.1^0~:GIT-VERSION-GEN | git hash-object --stdin
b2dffc839f306123d544e8f536ee31a7574f1139

注意:git rev-parse的文档说明了

  

作为一项特殊规则,<rev>^0表示提交本身,并在<rev>是引用提交对象的标记对象的对象名时使用。

在这种情况下,v1.8.1^0表示对v1.8.1标记所引用的提交。

为提交中的所有blob提取SHA1

要获取与给定提交关联的所有blob的对象名称,请阅读git ls-tree的输出,其类似于

$ git ls-tree -r v1.8.1^0
100644 blob 5e98806c6cc246acef5f539ae191710a0c06ad3f    .gitattributes
100644 blob f702415c12c5a4a66180f7ffd697347e5343ac4a    .gitignore
100644 blob c7e86183001a00ad2105765708b5b59852ef6640    .mailmap
100644 blob 536e55524db72bd2acf175208aef4f3dfc148d42    COPYING
100644 blob ddb030137d54ef3fb0ee01d973ec5cee4bb2b2b3    Documentation/.gitattributes
100644 blob d62aebd848b2a44f977ad4d7c4b75b6ff72b2163    Documentation/.gitignore
100644 blob 69f7e9b76c3f9b87b7951fb0df6a9720edadeb3e    Documentation/CodingGuidelines
100644 blob e53d333e5c08515af1e21d81c7daa365b12609a1    Documentation/Makefile
100644 blob fea3f9935b7794ce86f04d22c9d68fb9d537167d    Documentation/RelNotes/1.5.0.1.txt
100644 blob b061e50ff05b5e13211bb315e240974e898de32c    Documentation/RelNotes/1.5.0.2.txt
...

答案 2 :(得分:-1)

仅使用Git命令,不知道用于访问此信息的特定libgit2函数,但您可以解决这个问题。

您可以使用git show --stat COMMIT获取特定提交中哪些文件已更改的文件列表。底部是已更改的文件路径列表(加上详细信息更改了多少行)。你可以从那里过滤掉那些东西。您可以进一步使用漂亮格式从输出中删除更多内容。

获得文件路径后,可以使用git show COMMIT:PATH获取文件blob。您可以使用git show COMMIT^:PATH获取该文件的先前版本。