Push and Pull files with Git LFS

Learn the basic commands of the Git LFS and how to use it to manage large Unity and Unreal projects with lots of binary files.

Jochen Hunz
March 1, 2024
min read

Git LFS is an extension to Git that can handle binary files. If you push binary files without Git LFS, you will quickly hit the limits of your cloud storage providers. For example, GitLab has a limit of 10GB per repository and 100MB per file. When you use Git LFS, these limits don't exist.

Almost every Git client supports Git LFS, and if you install the command-line version of Git on Windows, Git LFS comes bundled with the installation.

Configure Git LFS

The easiest way to configure Git LFS is to download this .gitattributes file, which was configured to work with Unreal and Unity Engine, and place it in the root folder of your Git repository. Then use a desktop application like SourceTree, Fork, or Anchorpoint that supports Git LFS to push and pull files. That's it for most cases.

.gitattributes file for configuring Git LFS
Place the .gitattributes file in the root of your Git repository

This file tells Git which file extensions should be handled as LFS. In other words, which files should not be stored directly in the Git repository.

How Git LFS works technically

Technically, Git LFS takes care of where your binary files are stored on the remote server. Binaries will not be placed in the same location as the Git repository, but in a different location, in most cases an object storage.

Remember that Git is a decentralized version control system, and when you clone, it downloads the entire history. Without Git LFS, it would also download, say, 20 versions of a PSD file that you don't need.

How GIt LFS works, including the logo of Git and a psd file
Git LFS splits the working file (character.psd) into a small pointer file, that will be stored in the Git repository and the actual content, that will be stored on an object storage, which is infinitely scalable.

Instead, it downloads a tiny 1KB (or smaller) file called a "pointer file" for each version of the PSD file. This pointer file then knows where the original PSD is located on the Object Storage. So if you only need the latest version, it will only download the latest version of the PSD file.

For binaries, we can say that Git LFS makes Git behave like a centralized version control system.

Basic Git LFS commands

Once you have configured Git LFS, you can use the same Git commands as before. Git add, Git commit, Git pull, and Git push work exactly the same way. Here are a few commands that will give you more control over your Git project.

Git LFS track

This is more or less the same as adding a new line to your .gitattributes file. You are telling Git which files to handle via the Git LFS extension. The .gitattributes file follows the same syntax as the .gitignore file.

git lfs track "*.fbx"

Git LFS clone

Normally, a Git clone will also download all the files managed by Git LFS. The Git LFS clone command is therefore deprecated and not needed anymore.

Git LFS pull

Git LFS Pull allows you to pull files from your repository with certain performance optimizations. But now, Git pull has the same performance optimizations that Git LFS pull had before, so you actually don’t need it.

git lfs pull

Git LFS push

Normally a regular Git push will do the job. If for some reason files are missing from the repository, you can push them using a Git LFS push.

git lfs push origin main -all

The "--all" flag makes sure that everything that has been committed and tracked as LFS is also pushed.

Git LFS fetch

With Git LFS fetch you have additional control what you can download without applying it to your project folder. It’s similar to downloading a movie from a streaming service provider so that you can watch it offline later.

git lfs fetch origin main

File locking

Git LFS adds a file locking feature to Git.

*.fbx filter=lfs diff=lfs merge=lfs -text --lockable

To use it, you need to edit your .gitattributes file and add a "--lockable" parameter to your file types.

git lfs lock myFolder/character.psd

You can then use the “lock” command to make files read-only for other team members.

git lfs unlock myFolder/character.psd

To unlock a file, simply type:

git lfs unlock myFolder/character.psd --force

To force unlock a file, which was locked by somebody else, type:

Git LFS prune

git lfs prune

To clean up disk space used by files in the Git LFS cache, you can use Git LFS prune to clean up everything that is not your current version. This will keep a copy of the latest version in the Git LFS cache. If you want to avoid this, add the "--force" flag.

git lfs prune --force --verify-remote --verify-unreachable

To do that safely, add “--verify-remote” and “--verify-unreachable”, so that you don’t lose files.

Pointer files

Sometimes you may find that your actual working file (e.g. your character.psd) has become a 1KB pointer file. This can happen for several reasons. To fix this, just do a Git LFS pull as described above.

Showing pointer files instead of the main content can also be caused by not having Git LFS installed. So make sure you install Git LFS (or use a desktop GUI that supports it).

Migrate files, that have been already committed to Git LFS

In cases where you started working on a project without Git LFS and you encountered the issue of your repository slowing down or hit the limit by your hosting provider, then you can move over all the binary files to Git LFS. You have to use the “migrate” command for that.

First of all, make sure that Git LFS is installed and configured properly as mentioned above

Migrate the files to Git LFS

git lfs migrate import --include="*.psd" --everything

Replace "*.psd" with the patterns of the files you've tracked. The "--everything" option ensures all branches and tags are included.

Push your changes

git push --force

Be careful here, because you have to use a force push. Before you do that, inform your team that nobody should touch the repository while you are doing that transition

Then, everybody can pull the new changes