How to save all git versions of a file to disk?

Viewed 239

Having a file.py which has three versions in git with three unique commit hashes.

So how can I programmatically restore all of the versions into specific files, such as:

0_<git_hash>_file.py
1_<git_hash>_file.py
2_<git_hash>_file.py

Solution does not have to be Python, but looking into the Python git package currently.

3 Answers
n=0
git log --pretty= --diff-filter=d --raw -- $file | 
while read m1 m2 h1 h2 rest; do
        eval git show $h2 > $((n++))_${h2}.$file
done

or

n=0
git log --pretty=%h --diff-filter=d -- $file |
while read; do
        eval git show $REPLY:$file > $((n++))_$REPLY.$file
done

depending on whether you want the blob's or the commit's hash in the resulting file name.

You can get a specified version of a file without checking out the corresponding commit using git show. For example:

git show git_hash:./file.py

will print the contents of file.py as of the specified commit to standard output. (Presumably the Git Python interface, which I haven't used, provides similar functionality.) The leading ./ avoids path resolution problems in some cases (I don't remember the details).

I've written a Perl script that does this kind of thing for several different version control systems (most of which I no longer use): https://github.com/Keith-S-Thompson/get-versions (no warranties).

As requested, here's an example of running get-versions on a copy of its own repo:

$ ls -l
total 56
-rw-r--r-- 1 kst kst 18092 Aug  9  2015 COPYING
-rw-r--r-- 1 kst kst  6234 Apr 16  2018 README.md
-rw-r--r-- 1 kst kst   940 Apr 25  2018 TODO.md
-rwxr-xr-x 1 kst kst 20977 Apr 16  2018 get-versions
$ get-versions -pad 3 -last 3 get-versions 
$ ls -l
total 128
-rw-r--r-- 1 kst kst 18092 Aug  9  2015 COPYING
-rw-r--r-- 1 kst kst  6234 Apr 16  2018 README.md
-rw-r--r-- 1 kst kst   940 Apr 25  2018 TODO.md
-rwxr-xr-x 1 kst kst 20977 Apr 16  2018 get-versions
-r--r--r-- 1 kst kst 20752 Mar  2 10:54 get-versions,012
-r--r--r-- 1 kst kst 20766 Mar  2 10:54 get-versions,013
-r--r--r-- 1 kst kst 20977 Mar  2 10:54 get-versions,014
$ 

get-versions -help prints an entirely too verbose usage message. (Adding a man page is on my TODO list, as is preserving execute permissions.)

Use git rev-list to get the list of commits, and git show to output the file:

i=0; git rev-list --abbrev-commit HEAD | 
while read sha; do
    git show $sha:./file.py > $((i++))_${sha}_file.py
done

This version might avoid problems with i++ being executed in a subshell and not affecting the parent:

i=0; git rev-list --abbrev-commit HEAD |
while read sha; do
    git show $sha:./file.py > ${i}_${sha}_file.py
    ((i++))
done
Related