37

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.

Lars Bilke
  • 4,940
  • 6
  • 45
  • 63
  • Not sure I understand: if you [`git lfs track`](https://github.com/git-lfs/git-lfs/wiki/Tutorial) the file, it will now be tracked by `git-lfs` and subsequent commits will not include the entirety of the file. But this does not affect previous commits, which you _cannot_ do without rewriting the history. – Edward Thomson Nov 09 '17 at 10:48
  • So I have to make a modification to the already tracked file and then a subsequent commit will switch the file to be tracked by git-lfs? – Lars Bilke Nov 09 '17 at 11:06
  • Nope! `git lfs track` works fine on existing files and will do the conversion. Thanks for the clarification, I'll add an answer. – Edward Thomson Nov 09 '17 at 11:11

1 Answers1

49

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.

Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
  • 3
    Thanks a lot! It works but one additional thing I did to get the intended behavior is to discard the changes to `.gitattributes` at the end. I already track `*.png` and don't need an additional tracking entry for e.g. `VSTS.png` in `.gitattributes`. – Lars Bilke Nov 09 '17 at 13:11
  • What if the file changes constantly, does it get saved many times or only the differnces like any other file in the repo? – Daahrien Aug 07 '20 at 12:51
  • 1
    @Lestat The lfs text stub gets updated with the file sha and size each time the file changes, so it's like any other file in the repo. The file itself will have to be uploaded each time though, but the historical changes won't contribute to the repo size when you clone it down. – Edward Spencer Sep 30 '21 at 10:07
  • 1
    What about the other way around. Convert file form LFS to regular? – Royi Feb 08 '22 at 13:19