Dealing with old LFS bloat filling up your Git cloud storage

For anyone who has made a large game with Adventure Game Studio using Git as the source control, the problem of the sprite file is surely the bane of your life. For older versions of AGS, all sprites were stored together in one immense inseparable blob of a sprite file (acsprset.spr), which can easily end up too large to store in regular Git storage (Github has a 100mb limit).

The standard solution to this is LFS (Large File Storage) which is plugin for Git that allows it to track large binary files. But this is a poor solution. acsprset.spr can be more than 1GB for higher resolution games, resulting in very bloated LFS storage. Unlike regular Git source control, where only the differenc from the previous state is comitted, every LFS commit adds the full size of any changed file to LFS. Cloud Git storage like Bitbucket or Github charges for every GB of LFS storage used per month. At this time (2026) Bitbucket charges $10 per month for every 100GB of LFS storage used, and Github charges $0.07 per GB per month.

A new feature added in AGS 3.6 is a menu option “Restore all sprites from sources” which allows the acsprset.spr file to be recreated from individual sprite files, allowing it to be safely added to .gitignore, and indiviual sprites tracked in LFS or as regular Git files, as appropriate for your project. Older versions of AGS did not have this feature, and the full acsprset.spr file must be committed every time it changes in order to remain consistent with the code.

This has left a team I’m on facing a $100 a month bill for 2 excessively large Git repositories on Bitbucket. I resolved to stop the money leakage by removing old LFS file versions. The main issue is that I did not want to lose the non-LFS Git history. Git history is very valuable in tracking down bugs, because you can follow the development of a source file over time. Sadly, removing the LFS history would mean that old commits would no longer be able to compile. This means that a “retrospective” in the future about how the graphics evolved over time will not be possible with older LFS files trashed. But I don’t think that $80 a month over decades is worth possible future nostalgia.

Here’s the technique I used to strip the LFS files without damaging the source history. It took a large repository from 727MB/442GB LFS to 1.42GB repo, 3.548GB LFS.

The idea is to remove the very large problematic sprite files from the repository entirely, and put all the other LFS files (.ogg files etc) in regular git storage. This makes the repository larger, but reduces the bloating in the LFS system.

CAUTION: Be very sure not to use this technique on any repository you have not backed up and confirmed the back up is good (compiles and runs). It’s very easy to corrupt a repository using these dangerous techniques.

  • Back up all branches of the original repository. Store them as zips. Upload them to Dropbox or Google Drive or somewhere that isn’t your local machine.
  • Install git-filter-repo from https://github.com/newren/git-filter-repo (git-filter-repo is a command line tool for rewriting git history)
  • Clone a mirror copy. A mirror is different than a regular clone, because it contains all the information needed to create a complete new version of the repository elsewhere.
git clone --mirror git@bitbucket.org:your/repo.git mirror_repo

(where repo.git is the original repo and mirror_repo is the directory you want it in)

  • Remove all files ending in .spr –
    If you are using this for something other than AGS, you will substitute whatever file type you want removed for *.spr
git filter-repo --path-glob '*.spr' --invert-paths
  • Re-add the origin (to fetch the other LFS files)
git remote add origin git@bitbucket.org:your/repo.git
  • Fetch the LFS files (except .spr, which we have removed entirely) [Note: if there’s enough space on your hard drive this will fetch literally everything, and if you want to back up the mirror, you can, but you will need a spare removable hard drive]
git lfs fetch --all
  • Put all the other LFS files into regular git storage
git lfs migrate export --include="*" --everything
  • check that there are no lfs files left
git lfs ls-files --all
  • Set the origin to a brand new completely empty repository.
git remote set-url origin git@bitbucket.org:your/brandnewrepo.git
  • make sure the origin is pointing to your new empty repo (don’t want to overwrite the old one)
git remote -v

PUSH!

git push --mirror
  • Download the newly created repo,
  • Edit the .gitattributes file so that only *.spr are added to LFS
  • Re-add the acsprset.spr file (the correct one for each branch, using your backups), add it to lfs, commit, push.
  • Download a fresh copy of your new repo and confirm that all branches compile and run.
  • Delete the old, bloated repository when you are sure that the new one works.

This snippet gives you the total size of all LFS in a repository, so you can check results:

git lfs ls-files --all --debug | awk -F: '$1~/size/{t+=$2}END{printf "Total is: %.2f GB\n", t/1024/1024/1024}'