Another title for this question could be 'How to checkout multiple versions of a Git-LFS managed file?'
I would like to inspect several versions of a file stored in Git-LFS. I would therefore like to several versions of this file side-by-side in my working directory. Something like this is what I have in mind:
git show v1:./myfile.ipynb > myfile-v1.ipynb
git show v2:./myfile.ipynb > myfile-v2.ipynb
This does not work as desired: the file is managed by Git-LFS, so to git show
its contents at each version looks like
version https://git-lfs.github.com/spec/v1
oid sha256:62aafe00ec8b61a37dd729e7d3a723382...
size 20439
I am interested in the file's 'true', Git-LFS-managed contents, rather than the pointer file that LFS stores in Git's own tree.
How can I create untracked, custom-named files that each contain a specific version of a file tracked by Git-LFS? This does not need to be a single command, I am resigned to Git needing multi-step scripts for single-concept actions.
Piping an lfs pointer into git lfs smudge
will yield you what you want. For example:
git cat-file blob <blob-sha> | git lfs smudge
Or if you have a commit-ish (a commit hash, branch name, just HEAD
, etc.) and a file name:
git cat-file blob <commit-ish>:path/to/my-large-file.name | git lfs smudge
You could redirect the output into a file.
Update: @Markonius' answer is the proper way to do it.
Here is a script that does this based on experimenting with an LFS repository. I didn't look at the LFS protocol in details, so there might be quirks unaccounted for, but it worked for my simple case.
git-lfs-cat-file
The relevant details are:
LFS files are stored in the index with the following structure:
version https://git-lfs.github.com/spec/v1
oid sha256:abcdeffffffffffffff
size nnnnnnnn
Actual LFS object will then be under .git/lfs/objects/ab/cd/abcdeffffffffffffff
.
When last I was working with LFS, there were conversations on the project page about better integration - such as by writing diff and/or merge tools that could be plugged in via .gitattributes
. These didn't seem to be considered high priority, since the main intended use case of LFS is to protect large binary files (but certainly I've come across multiple cases where either I had a large text file, or the only reasonable way to set up LFS tracking rules cast a wide enough net to catch some smaller text files). I'm not sure if there's been any progress on those tools, as I haven't looked at the project page in a while.
Absent those things, there's not a particularly "slick" way to do what you're asking. You can set up two work trees and check out different versions. You can check out one version, rename it, and then check out the other.