Removing Git LFS From A Project
How to remove Git LFS from your project's history
Git Large File Storage (LFS) is an extension to Git that separates large, frequently changing, binary files and saves them in a separate storage location outside of the normal Git project. LFS replaces these binary files with smaller text files, called pointers, that hold information about the original file and how to download them. These pointers look something like this:
version https://git-lfs.github.com/spec/v1
oid sha256:d7cbc07ce9b78a89764c0ac5e9c8e1b9dbdeb42c30d8396cba8f75aace5ba225
size 145930
Git-LFS uses git hooks to transparently replace and create these pointers whenever we make a commit and saves the binary data outside of Git until the next push where it will sync with your LFS server. When everything is working correctly, we should never see these pointer files.
When we say "remove LFS from a project" we really mean removing the hooks from our project, which, if not done correctly, will leave these pointer files all throughout our project's history with no way to download the actual files they pointed to, preventing us from ever building an older release of our project again.
To successfully uninstall LFS, we'll need to rewrite the project's history, replacing all the LFS pointer files with the actual file they pointed to, adding them back into our project's history. In the end, the project will look as if LFS was never installed in the project at all.
Step: 0 - Make A Backup
Before we begin, rewriting history is remarkably dangerous, with many opportunities to silently break something you'll only find out about after it's too late. Make a backup before you start and save it until you're absolutely sure the project's history is correct.
git clone --mirror $URL backup && cd backup
git lfs fetch --all
Replacing $URL
with the location of the project, these two commands
will:
- Create a bare copy of the project and navigate into it.
- Download all the files in LFS from the remote LFS server.
This will give you a complete backup of the project, including branches and other refs like tags and notes, as well as download all the files from LFS, ensuring any screw-ups with the next step are recoverable.
Step: 1 - Rewrite History
In the working copy of our project, filter-branch
can easily replace
all the LFS pointer files for us. However this step will also change all the
names of the commits (git objects) in your project, so references to specific
commits like Fixed in a4749f3
will break. If you have a lot of these
types of commits you might want to use more advanced tools like filter-repo.
git filter-branch -f --prune-empty --tree-filter '
[ -f .gitattributes ] && git rm -f .gitattributes
find . -type f | while read FILE; do
if head -2 "$FILE" | grep -q "^oid sha256:"; then
POINTER=$(cat "$FILE")
echo -n "$POINTER" | git lfs smudge > "$FILE"
git add "$FILE"
fi
done' --tag-name-filter cat -- --all
This uses git filter-branch --tree-filter
to go through each commit for
every branch, and use find
and grep
to list every LFS pointer
file so we can use git lfs smudge
to replace the pointers with the LFS
data, before committing the changes and moving to the next commit in the history.
Step: 2 - Remove Hooks & Filters
If this is the only project that uses LFS, you can remove the --local
option from the following command to also remove the filters from your global
Git config file ~/.gitconfig
git lfs uninstall --local
Once the pointer files have been replaced, we can remove the hooks and filters LFS used to read the pointer files every time we fetched, pushed or committed changes to the project, with this simple built-in LFS command.
Step: 3 - Remove the LFS cache
rm -r .git/lfs
Finally, if this is your working copy of the project, you can save some disk space by removing the LFS cache folder inside the git directory of your project.