Get blob from commit?

I am trying to figure out how I can get a list of files and their old and new blobs for one commit.

Say you have a commit of 1, which changed 3 files. I would run the specified function and return 3 files along with my old blob and new blob (assuming they are not binary).

Would there be a single way to do this: get the commit and previous commit, resolve their trees, then diff on the trees to find out what is different, and then get a blob for every other file?

+4
source share
3 answers

Would there be a single way to do this: get the commit and previous commit, resolve their trees, then diff on the trees to find out what is different, and then get a blob for every other file?

Yes, this is the recommended way. "Old" and "new" entries are just concepts that make sense when comparing two Tree s.

Beware that the β€œold” and β€œnew” are not expressive qualifiers. As you can look at the diff header , the resulting different record status can be

  • GIT_DELTA_UNMODIFIED = 0, / ** no changes * /
  • GIT_DELTA_ADDED = 1, / ** record does not exist in the old version * /
  • GIT_DELTA_DELETED = 2, / ** record does not exist in the new version * /
  • GIT_DELTA_MODIFIED = 3, / ** record contents changed between old and new * /
  • GIT_DELTA_RENAMED = 4, / ** record has been renamed between old and new * /
  • GIT_DELTA_COPIED = 5, / ** the record was copied from another old record * /
  • GIT_DELTA_IGNORED = 6, / ** the entry is ignored in the workdir file * /
  • GIT_DELTA_UNTRACKED = 7, / ** record is not a tracked item in workdir * /
  • GIT_DELTA_TYPECHANGE = 8, / ** record type changed between old and new * /

The test libgit2 tests-clar / diff / tree file should give you an example of how to use this function.

Update:

A similar question (from you? ;-)) was raised in the libgit2 tray log. The answer from @arrbee is also based on using the git_diff_tree_to_tree() API .

+3
source

Extract SHA1 for previous and current versions

Consider the output of git show --raw v1.8.1^0 in your own git repository.

  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 

The last three lines indicate the files that were modified with this commit. The first SHA1 in the change line is the name of the object of the previous revision of the specified file, and the second is blob in the named commit. For example, GIT-VERSION-GEN in v1.8.1 hashes

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

and blob associated with its parent commit,

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

Note: documentation for git rev-parse explains

As a special rule, <rev>^0 means commit itself and is used when <rev> is the name of the tag object related to the commit object.

In this case, v1.8.1^0 means the commit, to which the v1.8.1 tag v1.8.1 .

Getting SHA1 for all blocks in commit

To get the object names for all the blocks associated with this commit, read the output of git ls-tree , which resembles

  $ 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
 ... 
0
source

Using only Git commands, you are not aware of the specific functions of libgit2 to access this information, but you can probably figure it out.

You can get a list of files from which files were modified in a specific commit using git show --stat COMMIT . Below is a list of changed file paths (plus information about how many lines have been changed). From there you can filter the material. You can also use pretty-formatting to remove even more content from the output.

Once you have the file path, you can get the blob file with git show COMMIT:PATH . You get the previous version of the file using git show COMMIT^:PATH .

-1
source

All Articles