After using Git LFS on and off for over two years, even going through one major version change, I’ve decided git LFS is not for me, at this stage. Here’s how I took an existing repo using Git LFS, and removed it to return to a vanilla Git repo.
Briefly, Git LFS is a way for Git to manage large binary files such as large textures/audio/video, typically found in content development pipelines. Git itself isn’t really meant to manage large binary assets, and most git server implementations (like GitHub) reject files above a size limit. I’ve blogged about Git LFS before, almost a year ago, when I determined it was the least-bad of my options.
Why I decided don’t need Git LFS
– Onboarding engineers is harder
– Sometimes it breaks in surprising, unrecoverable ways that require re-downloading the repo. Usually something goes wrong with the smudge filter.
– Installation and managing versions is unreliable (see previous blog post)
– Accidentally running a normal git operation on a git-lfs repo without git-lfs installed can break the repo unrecoverably (locally). This can happen if you accidentally use the wrong shell. I have done this several times.
– I’m only using it for a handful of almost-never changing files: big textures for prototyping assets, audio and video. I can instead gitignore these and sync via Dropbox.
– I’m paying extra for it (one Github “data pack” @ $5/month)
How I broke up with Git LFS:
1) I copied my git-lfs repo folder locally, and then pushed it to a new repo on Github while experimenting.
2) I compressed files that could be compressed further.
Turns out I had a great deal of *.tga files in my Unity repo. Both TGA and PNG are lossless formats. Some time back in the day, game engines preferred TGA; something about alpha depth, but to Unity and other modern engines they are indistinguishable.
I wanted to bulk convert all the tga to png, while maintaining Unity’s .meta files references. Turns out this is pretty easy, thanks to this Stack Overflow response to me here.
3) I excised lfs files from my git history.
To remove lfs from a repo, I couldn’t just do it in the modern day, I had to be a revisionist historian; these files never existed ;) Unfortunately, this means that if I rewind my repo to before the lfs removal commits (which I tagged), some references will be broken. But, at least the history will be there for diagnosis.
git-filter-branch
is the traditional way to remove unwanted files from your git history. However, it can be slow, and bfg-repo-cleaner is a shockingly feature-packed alternative
I used this command:
bfg --delete-files *.tga *.TGA *.tif --protect-blobs-from master
4) I uninstalled git-lfs from the repo, I think.
I couldn’t find any documentation that gave me a clear answer on a clean uninstall of git-lfs, so here’s some things I did, some of which may be unnecessary.
I ran this command in the repo:
git lfs uninstall
I deleted some lines with lfs in them from .git/config
I deleted the .gitattributes
file, which contained the listing of all the files I used with lfs.
However, once I did all this, the folder .git/lfs
exists still with 2.5 G in it. I know that git does lazy, occasional garbage collection, so it’s possible that this hadn’t been triggered yet. I just removed the folder.
5) I gradually pushed my new repo in parts.
After bfg, nearly all my git repo history had diverged from the remote on Github. I had to force push the new repo (this is a dark-aligned force power, btw). This didn’t work initially, with the error “The remote end hung up unexpectedly”
Some answers suggested I increased my buffer size, with:
git config http.postBuffer 524288000
This did not resolve the problem at first.
This post suggested I push the repo history in parts.
It’s unfortunate this process is so manual. My repo had 477 commits, from looking up my rev list with:
git rev-list --all --count
However, HEAD~477 isn’t an accessible commit, probably due to merged branches in my history.
Apparently this is my first commit accessible this way:
git push -u origin HEAD~305:refs/head/master --force
I finished the push with
git push -u origin HEAD~105:master
git push master
6) I tested that git-lfs via cloning without git-lfs.
.git/lfs folder was present, but empty, when I cloned again. Suspicious, but it seemed gone.
7) I resolved billing issues with GitHub support.
After deleting the original git-lfs repo, it took a couple hours for my lfs data usage to disappear. The usage even then didn’t go to zero – turns out there was another repo I forgot about still using lfs and had to contact GitHub support to find out. Unfortunately this usage bar doesn’t tell us which repos are using the quota.