First things first, install git 1.8.2 or newer and then install git-lfs
Create a new repo
git init . echo Hello World > README.md git add README.md git commit -m "Initial commit"
Let's create some more files
ls > foo.txt ls > bar.txt
And add them to git
git add foo.txt bar.txt
You should already have git-lfs installed. To ensure that git-lfs is setup correctly in your git configuration files use the git lfs install command:
git lfs install
Now let's add some large files to be tracked by git-lfs:
dd if=/dev/urandom of=cat.bin bs=1048576 count=1 dd if=/dev/urandom of=dog.bin bs=1048576 count=1
Now we are going ensure that git-lfs is tracking the large *.bin files we just created. Tracking means that in subsequent commits, these files will now be LFS files.
Note: This does NOT mean that versions of the files in previous commits will be converted. That involves a process commonly known as "rewriting history" and is described in the migration section.
We do this by setting a track pattern, using the git lfs track command.
git lfs track '*.bin'
This tells git-lfs to track all files matching the *.bin pattern. The quotes around the *.bin are there to prevent the shell from expanding *.bin, else you would end up only tracking cat.bin dog.bin, and no other bin in the future.
To see a list of all patterns currently being tracked by git-lfs, run git lfs track with no arguments
Listing tracked paths *.bin (.gitattributes)
To see the list of files being tracked by git-lfs, run git lfs ls-files. You will see that this list is currently empty. This is because technically the file isn't an lfs object until after you commit it.
Next, you need to add .gitattributes to your git repository. git lfs track stores the tracked files patterns in .gitattributes. This way when the repo is cloned, the tracked file patterns are preserved.
git add .gitattributes
We can also add the *.bin files now that they are tracked via git-lfs.
git add "*.bin"
Now git status should look like this.
On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: .gitattributes new file: bar.txt new file: cat.bin new file: dog.bin new file: foo.txt
Finally, commit the new files
git commit -m "Add files"
Now, when you run git lfs ls-files, you will see the list of tracked files
f05131d24d * cat.bin 7db207c488 * dog.bin
Adding git-lfs to a pre-existing repo
Let's create pretend repo to understand how converting to git-lfs works
git init . touch README.md git add README.md git commit -m "initial" git tag one echo hi > plain.txt ls > foo.bin git add plain.txt foo.bin git commit -m "Add some files" git tag two echo bye > plain.txt ls > bar.bin ls > foo.bin git add plain.txt foo.bin bar.bin git commit -m "Update and add another file" git tag three echo bye >> plain.txt ls > foo.bin git add plain.txt foo.bin git commit -m "Update some more" git tag four
Now lets decide we want *.bin files to be turned into lfs objects.
git lfs track '*.bin' git add .gitattributes git commit -m "Track .bin files" git tag not_working
Just tracking files does NOT convert them to lfs. They are part of history already, the only way to convert old files is to rewrite history (see the section about migrating existing data).
Next we can try converting the latest version of history only to LFS. Since *.bin are currently tracked, we just need to add the files back after removing them. We will remove it from git without deleting the file (aka remove cache), and then add it back
git rm --cached *.bin git add *.bin git commit -m "Convert last commit to LFS"
Now, git lfs ls-files shows:
4665a5ea42 * bar.bin 4665a5ea42 * foo.bin
We can also see that the foo.bin is an lfs file by git show HEAD:foo.bin
version https://git-lfs.github.com/spec/v1 oid sha256:4665a5ea423c2713d436b5ee50593a9640e0018c1550b5a0002f74190d6caea8 size 36
But when we look at the previous histories, we see that they are still not LFS tracked. git show not_working:foo.bin
bar.bin foo.bin plain.txt README.md
It's important to understand that tracking an LFS file does not remove it from a previous version of history. If you create a repo without LFS before, and put hundreds of MB in there, after all these steps, the old version still has all the large files in git, not in LFS.
Migrating existing repository data to LFS
Sometimes files end up committed within your repository when they should have been committed with LFS. This can be accidental, or can come up when converting an existing Git repository to use Git LFS. To make this possible, Git LFS ships with a git lfs migrate command that allows for such migrations:
Using git lfs migrate
Install Git LFS v2.2.1 (or later)
Rewrite e.g. all *.mp4 video files on the current branch that are not present on a remote:
git lfs migrate import --include="*.mp4"
Alternatively, rewrite all *.mp4 video files on a given branch(es) regardless of whether they are present on a remote (may require a force-push):
git lfs migrate import --include="*.mp4" --include-ref=refs/heads/master --include-ref=refs/heads/my-feature
Push the converted repository as a new repository:
Cleaning up the .git directory after migrating
The above successfully converts pre-existing git objects to lfs objects. However, the regular objects still persist in the .git directory. These will be cleaned up eventually by git, but to clean them up right away, run:
git reflog expire --expire-unreachable=now --all git gc --prune=now