splash image

February 8, 2022

What is git LFS?

Git large file storage or LFS is a way to store binaries outside your git repo, but still work with them as if they were part of the repo.

It works by replacing the actual file with a small text file which contains a pointer to the real thing. Every problem in computer science can be solved by another level of indirection.

$ cat screenshot.png 
version https://git-lfs.github.com/spec/v1
oid sha256:8ded39c045d36d4f745e46525b5c8b6a29baceb89006a3e85148ce66db9c187d
size 280654

For a brief introduction to LFS see https://git-lfs.github.com/ or watch this video.

Installation

Installation requires 2 steps.

  1. Place git-lfs on the path.
    I pulled the latest binary for macOS arm64 from GitHub releases.

  2. Configure git to use LFS with git lfs install.

Both of these steps are included in the install.sh script, in the GitHub release.

Why is the binary called 'git-lfs'?

A git extension is a binary prefixed git-.

Running git lfs invokes git-lfs, which gives you a nice summary of the available commands.

To get started with Git LFS, the following commands can be used.

 1. Setup Git LFS on your system. You only have to do this once per
    repository per machine:

        git lfs install

 2. Choose the type of files you want to track, for examples all ISO
    images, with git lfs track:

        git lfs track "*.iso"

 3. The above stores this information in gitattributes(5) files, so
    that file need to be added to the repository:

        git add .gitattributes

 4. Commit, push and work with the files normally:

        git add file.iso
        git commit -m "Add disk image"
        git push

What does 'git lfs install' do?

The command git lfs install configures a git filter, which calls git-lfs to convert between pointer files and the actual blobs. This filter configuration lives in your git config (e.g. at ~/.gitconfig) and applies to all your repos.

[filter "lfs"]
	clean = git-lfs clean -- %f
	smudge = git-lfs smudge -- %f
	process = git-lfs filter-process
	required = true

If you prefer not to run these hooks all the time, you can uninstall them with git lfs uninstall after finishing your work on an LFS git repo.

How is a repo configured to use LFS?

The command git lfs track '*.png' adds the following line to the .gitattributes file in the repo.

*.png filter=lfs diff=lfs merge=lfs -text

This associates git-lfs with .png files. Once the association is made, you can work with those files normally, and git-lfs will handle the LFS interactions with GitHub automatically, in the background.

Example repo

This repo lives at github.com/jldec/lfs-test

$ git init
Initialized empty Git repository in /Users/jldec/lfs-test/.git/

$ git lfs track '*.png'
Tracking "*.png"

$ git lfs track
Listing tracked patterns
    *.png (.gitattributes)
Listing excluded patterns

$ git add -A
$ git commit -m 'initial commit'
[main (root-commit) c25b950] initial commit
 2 files changed, 4 insertions(+)
 create mode 100644 .gitattributes
 create mode 100644 screenshot.png

$ git lfs ls-files
ba2a8c5285 * screenshot.png

$ git remote add origin git@github.com:jldec/lfs-test.git
$ git push -u origin main
Uploading LFS objects: 100% (1/1), 146 KB | 0 B/s, done.
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 408 bytes | 408.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:jldec/lfs-test.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   screenshot.png

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

$ git commit -a -m 'update lfs file screenshot.png'
[main e695f5f] update lfs file screenshot.png
 1 file changed, 2 insertions(+), 2 deletions(-)

$ git push
Uploading LFS objects: 100% (1/1), 281 KB | 121 KB/s, done.
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 405 bytes | 405.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:jldec/lfs-test.git
   c25b950..e695f5f  main -> main

To leave a comment
please visit dev.to/jldec

debug

user: anonymous

{
  "path": "/blog/what-is-git-lfs",
  "attrs": {
    "title": "What is git LFS?",
    "splash": {
      "image": "/images/station-clouds.jpg"
    },
    "date": "2022-02-08",
    "layout": "BlogPostLayout",
    "excerpt": "Git large file storage or LFS is a way to store binaries outside your git repo, but still work with them as if they were part of the repo."
  },
  "md": "# What is git LFS?\n\nGit large file storage or LFS is a way to store binaries outside your git repo, but still work with them as if they were part of the repo.\n\nIt works by replacing the actual file with a small text file which contains a pointer to the real thing. Every problem in computer science can be solved by another level of indirection.\n\n```sh\n$ cat screenshot.png \nversion https://git-lfs.github.com/spec/v1\noid sha256:8ded39c045d36d4f745e46525b5c8b6a29baceb89006a3e85148ce66db9c187d\nsize 280654\n```\n\nFor a brief introduction to LFS see https://git-lfs.github.com/ or watch this [video](https://www.youtube.com/watch?v=uLR1RNqJ1Mw).\n\n## Installation\nInstallation requires 2 steps.\n\n1. Place `git-lfs` on the path.  \n   I pulled the latest binary for macOS arm64 from [GitHub releases](https://github.com/git-lfs/git-lfs/releases).\n\n2. Configure git to use LFS with `git lfs install`.\n\nBoth of these steps are included in the `install.sh` script, in the GitHub release.\n\n## Why is the binary called 'git-lfs'?\nA git extension is a binary prefixed `git-`.\n\nRunning `git lfs` invokes `git-lfs`, which gives you a nice summary of the available commands.\n\n```\nTo get started with Git LFS, the following commands can be used.\n\n 1. Setup Git LFS on your system. You only have to do this once per\n    repository per machine:\n\n        git lfs install\n\n 2. Choose the type of files you want to track, for examples all ISO\n    images, with git lfs track:\n\n        git lfs track \"*.iso\"\n\n 3. The above stores this information in gitattributes(5) files, so\n    that file need to be added to the repository:\n\n        git add .gitattributes\n\n 4. Commit, push and work with the files normally:\n\n        git add file.iso\n        git commit -m \"Add disk image\"\n        git push\n```\n\n## What does 'git lfs install' do?\nThe command `git lfs install` configures a git filter, which calls git-lfs to convert between pointer files and the actual blobs.\nThis filter configuration lives in your git config (e.g. at `~/.gitconfig`) and applies to all your repos.\n\n```.gitconfig\n[filter \"lfs\"]\n\tclean = git-lfs clean -- %f\n\tsmudge = git-lfs smudge -- %f\n\tprocess = git-lfs filter-process\n\trequired = true\n```\n\nIf you prefer not to run these hooks all the time, you can uninstall them with `git lfs uninstall` after finishing your work on an LFS git repo.\n\n## How is a repo configured to use LFS?\nThe command `git lfs track '*.png'` adds the following line to the `.gitattributes` file in the repo.\n\n```.gitattributes\n*.png filter=lfs diff=lfs merge=lfs -text\n```\n\nThis associates git-lfs with `.png` files.\nOnce the association is made, you can work with those files normally, and git-lfs will handle the LFS interactions with GitHub automatically, in the background.\n\n## Example repo\nThis repo lives at [github.com/jldec/lfs-test](https://github.com/jldec/lfs-test)\n\n```sh\n$ git init\nInitialized empty Git repository in /Users/jldec/lfs-test/.git/\n\n$ git lfs track '*.png'\nTracking \"*.png\"\n\n$ git lfs track\nListing tracked patterns\n    *.png (.gitattributes)\nListing excluded patterns\n\n$ git add -A\n$ git commit -m 'initial commit'\n[main (root-commit) c25b950] initial commit\n 2 files changed, 4 insertions(+)\n create mode 100644 .gitattributes\n create mode 100644 screenshot.png\n\n$ git lfs ls-files\nba2a8c5285 * screenshot.png\n\n$ git remote add origin git@github.com:jldec/lfs-test.git\n$ git push -u origin main\nUploading LFS objects: 100% (1/1), 146 KB | 0 B/s, done.\nEnumerating objects: 4, done.\nCounting objects: 100% (4/4), done.\nDelta compression using up to 8 threads\nCompressing objects: 100% (3/3), done.\nWriting objects: 100% (4/4), 408 bytes | 408.00 KiB/s, done.\nTotal 4 (delta 0), reused 0 (delta 0), pack-reused 0\nTo github.com:jldec/lfs-test.git\n * [new branch]      main -> main\nBranch 'main' set up to track remote branch 'main' from 'origin'.\n\n$ git status\nOn branch main\nYour branch is up to date with 'origin/main'.\n\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git restore <file>...\" to discard changes in working directory)\n        modified:   screenshot.png\n\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\n\n$ git commit -a -m 'update lfs file screenshot.png'\n[main e695f5f] update lfs file screenshot.png\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n$ git push\nUploading LFS objects: 100% (1/1), 281 KB | 121 KB/s, done.\nEnumerating objects: 5, done.\nCounting objects: 100% (5/5), done.\nDelta compression using up to 8 threads\nCompressing objects: 100% (3/3), done.\nWriting objects: 100% (3/3), 405 bytes | 405.00 KiB/s, done.\nTotal 3 (delta 0), reused 0 (delta 0), pack-reused 0\nTo github.com:jldec/lfs-test.git\n   c25b950..e695f5f  main -> main\n```\n\n_To leave a comment  \nplease visit [dev.to/jldec](https://dev.to/jldec/what-is-git-lfs-28db)_\n\n\n",
  "html": "<h1>What is git LFS?</h1>\n<p>Git large file storage or LFS is a way to store binaries outside your git repo, but still work with them as if they were part of the repo.</p>\n<p>It works by replacing the actual file with a small text file which contains a pointer to the real thing. Every problem in computer science can be solved by another level of indirection.</p>\n<pre><code class=\"language-sh\">$ cat screenshot.png \nversion https://git-lfs.github.com/spec/v1\noid sha256:8ded39c045d36d4f745e46525b5c8b6a29baceb89006a3e85148ce66db9c187d\nsize 280654\n</code></pre>\n<p>For a brief introduction to LFS see <a href=\"https://git-lfs.github.com/\">https://git-lfs.github.com/</a> or watch this <a href=\"https://www.youtube.com/watch?v=uLR1RNqJ1Mw\">video</a>.</p>\n<h2>Installation</h2>\n<p>Installation requires 2 steps.</p>\n<ol>\n<li>\n<p>Place <code>git-lfs</code> on the path.<br>\nI pulled the latest binary for macOS arm64 from <a href=\"https://github.com/git-lfs/git-lfs/releases\">GitHub releases</a>.</p>\n</li>\n<li>\n<p>Configure git to use LFS with <code>git lfs install</code>.</p>\n</li>\n</ol>\n<p>Both of these steps are included in the <code>install.sh</code> script, in the GitHub release.</p>\n<h2>Why is the binary called 'git-lfs'?</h2>\n<p>A git extension is a binary prefixed <code>git-</code>.</p>\n<p>Running <code>git lfs</code> invokes <code>git-lfs</code>, which gives you a nice summary of the available commands.</p>\n<pre><code>To get started with Git LFS, the following commands can be used.\n\n 1. Setup Git LFS on your system. You only have to do this once per\n    repository per machine:\n\n        git lfs install\n\n 2. Choose the type of files you want to track, for examples all ISO\n    images, with git lfs track:\n\n        git lfs track &quot;*.iso&quot;\n\n 3. The above stores this information in gitattributes(5) files, so\n    that file need to be added to the repository:\n\n        git add .gitattributes\n\n 4. Commit, push and work with the files normally:\n\n        git add file.iso\n        git commit -m &quot;Add disk image&quot;\n        git push\n</code></pre>\n<h2>What does 'git lfs install' do?</h2>\n<p>The command <code>git lfs install</code> configures a git filter, which calls git-lfs to convert between pointer files and the actual blobs.\nThis filter configuration lives in your git config (e.g. at <code>~/.gitconfig</code>) and applies to all your repos.</p>\n<pre><code class=\"language-.gitconfig\">[filter &quot;lfs&quot;]\n\tclean = git-lfs clean -- %f\n\tsmudge = git-lfs smudge -- %f\n\tprocess = git-lfs filter-process\n\trequired = true\n</code></pre>\n<p>If you prefer not to run these hooks all the time, you can uninstall them with <code>git lfs uninstall</code> after finishing your work on an LFS git repo.</p>\n<h2>How is a repo configured to use LFS?</h2>\n<p>The command <code>git lfs track '*.png'</code> adds the following line to the <code>.gitattributes</code> file in the repo.</p>\n<pre><code class=\"language-.gitattributes\">*.png filter=lfs diff=lfs merge=lfs -text\n</code></pre>\n<p>This associates git-lfs with <code>.png</code> files.\nOnce the association is made, you can work with those files normally, and git-lfs will handle the LFS interactions with GitHub automatically, in the background.</p>\n<h2>Example repo</h2>\n<p>This repo lives at <a href=\"https://github.com/jldec/lfs-test\">github.com/jldec/lfs-test</a></p>\n<pre><code class=\"language-sh\">$ git init\nInitialized empty Git repository in /Users/jldec/lfs-test/.git/\n\n$ git lfs track '*.png'\nTracking &quot;*.png&quot;\n\n$ git lfs track\nListing tracked patterns\n    *.png (.gitattributes)\nListing excluded patterns\n\n$ git add -A\n$ git commit -m 'initial commit'\n[main (root-commit) c25b950] initial commit\n 2 files changed, 4 insertions(+)\n create mode 100644 .gitattributes\n create mode 100644 screenshot.png\n\n$ git lfs ls-files\nba2a8c5285 * screenshot.png\n\n$ git remote add origin git@github.com:jldec/lfs-test.git\n$ git push -u origin main\nUploading LFS objects: 100% (1/1), 146 KB | 0 B/s, done.\nEnumerating objects: 4, done.\nCounting objects: 100% (4/4), done.\nDelta compression using up to 8 threads\nCompressing objects: 100% (3/3), done.\nWriting objects: 100% (4/4), 408 bytes | 408.00 KiB/s, done.\nTotal 4 (delta 0), reused 0 (delta 0), pack-reused 0\nTo github.com:jldec/lfs-test.git\n * [new branch]      main -&gt; main\nBranch 'main' set up to track remote branch 'main' from 'origin'.\n\n$ git status\nOn branch main\nYour branch is up to date with 'origin/main'.\n\nChanges not staged for commit:\n  (use &quot;git add &lt;file&gt;...&quot; to update what will be committed)\n  (use &quot;git restore &lt;file&gt;...&quot; to discard changes in working directory)\n        modified:   screenshot.png\n\nno changes added to commit (use &quot;git add&quot; and/or &quot;git commit -a&quot;)\n\n$ git commit -a -m 'update lfs file screenshot.png'\n[main e695f5f] update lfs file screenshot.png\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n$ git push\nUploading LFS objects: 100% (1/1), 281 KB | 121 KB/s, done.\nEnumerating objects: 5, done.\nCounting objects: 100% (5/5), done.\nDelta compression using up to 8 threads\nCompressing objects: 100% (3/3), done.\nWriting objects: 100% (3/3), 405 bytes | 405.00 KiB/s, done.\nTotal 3 (delta 0), reused 0 (delta 0), pack-reused 0\nTo github.com:jldec/lfs-test.git\n   c25b950..e695f5f  main -&gt; main\n</code></pre>\n<p><em>To leave a comment<br>\nplease visit <a href=\"https://dev.to/jldec/what-is-git-lfs-28db\">dev.to/jldec</a></em></p>\n"
}