How to convert a file tracked by git to git-lfs?

Lars Bilke picture Lars Bilke · Nov 9, 2017 · Viewed 12.1k times · Source

How do I convert a single file (e.g. a png) which is already committed as a regular object to git-lfs?

I do not want to migrate the whole repo and I also do not want to rewrite the history of the repo.

Answer

Edward Thomson picture Edward Thomson · Nov 9, 2017

git lfs track will begin tracking a new file or an existing file that is already checked in to your repository. When you run git lfs track and then commit that change, it will update the file, replacing it with the LFS pointer contents.

Here I have a repository with a PNG checked in "normally" (without using LFS):

C:\Temp\LFS>dir
 Volume in drive C is Windows
 Volume Serial Number is A442-238A

 Directory of C:\Temp\LFS

11/09/2017  11:12 AM    <DIR>          .
11/09/2017  11:12 AM    <DIR>          ..
10/20/2017  01:22 PM            48,517 VSTS.png
               1 File(s)         48,517 bytes
               2 Dir(s)  284,988,436,480 bytes free

C:\Temp\LFS>git status
On branch master
nothing to commit, working tree clean

I don't need to make any changes to the PNG, I can simply git lfs track it:

C:\Temp\LFS>git lfs track VSTS.png
Tracking "VSTS.png"    

And git-lfs has done everything it needs to - it's set up the tracking information in the .gitattributes, and now git knows that VSTS.png is modified:

C:\Temp\LFS>git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   VSTS.png

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitattributes

no changes added to commit (use "git add" and/or "git commit -a")

Now if we git add the file, it will add the LFS object to the repository, and we can commit the changes. What will actually be done is that git-lfs will enqueue that file for LFS storage, and replace the file in the repository with a pointer file, telling LFS where to find the actual blob, which we can see if we inspect the contents of the repository's stage:

C:\Temp\LFS>git add VSTS.png

C:\Temp\LFS>git cat-file blob :0:VSTS.png
version https://git-lfs.github.com/spec/v1
oid sha256:6075cd5130bdbe29a037cba93dc22158d1443b22b2ffb6acb0d1d541838f26b9
size 48517

(That's the actual LFS metadata, instead of the PNG file.)

Now when you commit and push these changes, the file will be in LFS. This is not retroactive however - you are not rewriting the repository's history, so previous versions of the PNG will still be in the repository directly (not in LFS) and will still be taking up space.

If you did want to rewrite the history, I would recommend using the BFG Repo Cleaner.