Published 2025-01-06.
Last modified 2025-01-18.
Time to read: 8 minutes.
git
collection.
I have published 8 articles about the Git large file system (LFS). They are meant to be read in order.
- Git Large File System Overview
- Git LFS Scripts
- Git LFS Client Installation
- Git LFS Server URLs
- Git-ls-files, Wildmatch Patterns and Permutation Scripts
- Git LFS Tracking, Migration and Un-Migration
- Git LFS Client Configuration & Commands
- Git LFS SSH Authentication
- Working With Git LFS
- Evaluation Procedure For Git LFS Servers
- Git LFS server tests:
6 articles are still in process.
Instructions for typing along are given for Ubuntu and WSL/Ubuntu. If you have a Mac, most of this information should be helpful.
This Article Probably Contains Errors
This article is incomplete and may contain errors. It has been published to allow collaboration with fact-checkers. Not all of these scenarios might make sense to attempt to review. Do not rely on this information yet.
Null Servers
Of all the available Git LFS server choices, the option to do without a Git LFS server is the simplest to set up. In fact, you can do away with the Git server also and use a bare Git repository instead. You will lose the file locking feature, but few people use it.
A null Git LFS server could be set up for an individual or organization if a local area network is already set up and at least one machine is always available as a server. I have written this article with that assumption in mind.
For a null Git LFS server, all that is required is a network-accessible directory structure to store large files.
No client-side Git LFS filters or hooks are required
Use Cases
Doing without a Git LFS server has the following common use cases:
- File size overwhelms available bandwidth.
- Extremely sensitive documents, copies of which must not leave the building.
- Simplest possible Git LFS setup.
The following scenarios are complete examples of different ways of setting up null Git LFS servers.
- A locally accessible bare Git repository and a separate locally accessible directory for large files.
- A remote Git repository, such as GitHub, with a locally accessible directory for large files.
Restrictions & Requirements
- Only one concurrent user with write access.
- A computer is dedicated to acting as a server.
My Setup
I am the only person who has write access to my files.
I have an Ubuntu server in my apartment called
gojira
that is a media store, runs Plex,
and is a terrific programming environment.
This machine is normally never turned off.
It acts as a Samba server, runs an nginx web server, etc.
I used gojira
as a Git LFS server-side test platform.
Gojira
has a dedicated UPS and is mirrored to a backup machine called
bambam
.
I also have a laptop for working while traveling, and another laptop for performing on-location computer music. Both of these laptops need Git LFS, although the types of information stored on each are different.
I also have a desktop computer
(bear
)
that I wrote most of the website on.
Bear
needs to access everything that all the other machines have access to.
My user ID on all machines is mslinn
.
Bare Git Repositories
Bare Git Repositories discusses bare Git repositories and
introduces the new_bare_repo
script that we will use shortly.
It is possible to employ Git LFS with a bare Git repository, so long as the bare Git repository is accessible via a supported protocol. The script makes the empty bare repository that we will need for each test scenario.
Scenarios Considered
The following scenarios were considered for this evaluation.
Git Server | Scenario | Git LFS Protocol | Use Cases |
---|---|---|---|
None (bare repo) | 1 | local |
Not functional.
|
2 | SSH |
| |
GitHub | 3 | local |
|
4 | SSH |
| |
5 | http
|
|
Scenario 1: Locally Accessible Bare Git Repository
Git Server | Scenario | Git LFS Protocol | Use Cases |
---|---|---|---|
None (bare repo) | 1 | local |
Not functional.
|
I am still working on this scenario.
The bare repository for this test was created on Ubuntu server gojira
in ~/eval_repos/repo1.git/
.
A new directory called ~/eval_repos/repo1.lfs
was created to hold Git LFS data.
The git
protocol is unavailable in this scenario because there is no Git server.
mslinn@gojira ~ $ mkdir -p ~/eval_repos && cd ~/eval_repos
mslinn@gojira eval_repos $ mkdir repo1.lfs
mslinn@gojira eval_repos $ new_bare_repo repo1.git Initialized empty shared Git repository in /home/mslinn/eval_repos/repo1.git/ The new repository contains the following subdirectory tree . ├── hooks ├── info ├── objects │ ├── info │ └── pack └── refs ├── heads └── tags 9 directories All done! The bare repository was created in '/home/mslinn/eval_repos/repo1.git'.
My desktop computer bear
will contain a similar tree of test repositories,
mirroring the server-side organization.
Instead of being rooted in my home directory, the tree is rooted at $work
.
mslinn@bear ~ $ mkdir -p $work/eval_repos && cd $work/eval_repos
My home directory on gojira
is mounted on my desktop computer bear
at /mnt/gojira_mslinn
.
Thus, the path to the bare Git repository on gojira
from the desktop computer is
/mnt/
.
Let’s make sure the bare Git repository is on the server gojira
in the expected directory:
mslinn@bear eval_repos $ ls /mnt/gojira_mslinn/eval_repos/repo1.git HEAD* config* description* hooks/ info/ objects/ refs/
Let’s also ensure that the directory for the null Git LFS repository is
also where we expect it to be.
This directory will be used as the value of lfs.url
in a moment.
mslinn@bear eval_repos $ ls -l /mnt/gojira_mslinn/eval_repos/repo1.lfs total 0
Now we can clone the bare Git repository.
mslinn@bear eval_repos $ git clone /mnt/gojira_mslinn/eval_repos/repo1.git Cloning into 'repo1'... warning: You appear to have cloned an empty repository. done. mslinn@bear eval_repos $ cd repo1
mslinn@bear repo1 $
This is the first opportunity to establish lfs.url
.
If we forget to do this, the tracked large files will end up in the Git repository,
instead of the Git LFS repository.
mslinn@bear repo1 $ git config -f .lfsconfig lfs.url \ /mnt/gojira_mslinn/eval_repos/repo1.lfs
mslinn@bear repo1 $ cat .lfsconfig [lfs] url = /mnt/gojira_mslinn/eval_repos/repo1.lfs
Now let’s populate the repository with the first set of test data,
stored in the git_lfs_test_data/v1/
directory.
mslinn@bear repo1 $ rsync -at --progress "$work/git/git_lfs_test_data/v1/" ./
sending incremental file list ./ 200MB.zip 209,715,200 100% 357.09MB/s 0:00:00 (xfr#1, to-chk=9/11) BigBuckBunny_640x360.m4v 121,283,919 100% 133.41MB/s 0:00:00 (xfr#2, to-chk=8/11) big_buck_bunny_480p_h264.mov 106,491,904 100% 89.56MB/s 0:00:01 (xfr#3, to-chk=7/11) big_buck_bunny_480p_stereo.avi 156,506,028 100% 281.61MB/s 0:00:00 (xfr#4, to-chk=6/11) big_buck_bunny_480p_stereo.ogg 166,825,767 100% 165.73MB/s 0:00:00 (xfr#5, to-chk=5/11) big_buck_bunny_720p_h264.mov 416,751,190 100% 199.02MB/s 0:00:01 (xfr#6, to-chk=4/11) big_buck_bunny_720p_stereo.avi 284,437,944 100% 157.80MB/s 0:00:01 (xfr#7, to-chk=3/11) big_buck_bunny_720p_stereo.ogg 196,898,674 100% 154.80MB/s 0:00:01 (xfr#8, to-chk=2/11) enwik9.zip 322,592,222 100% 305.21MB/s 0:00:01 (xfr#9, to-chk=1/11) rdf-files.tar.zip 160,912,831 100% 372.47MB/s 0:00:00 (xfr#10, to-chk=0/11)
Let’s see what we have in this repository now:
mslinn@bear repo1 $ git status On branch master No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) 200MB.zip BigBuckBunny_640x360.m4v README.md big_buck_bunny_480p_h264.mov big_buck_bunny_480p_stereo.avi big_buck_bunny_480p_stereo.ogg big_buck_bunny_720p_h264.mov big_buck_bunny_720p_stereo.avi big_buck_bunny_720p_stereo.ogg enwik9.zip rdf-files.tar.zip
Git LFS must be informed of the patterns to track.
mslinn@bear repo1 $ track -ce avi m4v mov ogg pdf zip Tracking "*.avi" Tracking "*.AVI" Tracking "**/*.avi" Tracking "**/*.AVI" Tracking "*.m4v" Tracking "*.M4V" Tracking "**/*.m4v" Tracking "**/*.M4V" Tracking "*.mov" Tracking "*.MOV" Tracking "**/*.mov" Tracking "**/*.MOV" Tracking "*.ogg" Tracking "*.OGG" Tracking "**/*.ogg" Tracking "**/*.OGG" Tracking "*.pdf" Tracking "*.PDF" Tracking "**/*.pdf" Tracking "**/*.PDF" Tracking "*.zip" Tracking "*.ZIP" Tracking "**/*.zip" Tracking "**/*.ZIP"
.gitattributes
was created in the current directory by the previous command.
It looks like this:
*.avi filter=lfs diff=lfs merge=lfs -text *.AVI filter=lfs diff=lfs merge=lfs -text **/*.avi filter=lfs diff=lfs merge=lfs -text **/*.AVI filter=lfs diff=lfs merge=lfs -text **/*.M4V filter=lfs diff=lfs merge=lfs -text *.m4v filter=lfs diff=lfs merge=lfs -text *.M4V filter=lfs diff=lfs merge=lfs -text **/*.m4v filter=lfs diff=lfs merge=lfs -text *.mov filter=lfs diff=lfs merge=lfs -text *.MOV filter=lfs diff=lfs merge=lfs -text **/*.mov filter=lfs diff=lfs merge=lfs -text **/*.MOV filter=lfs diff=lfs merge=lfs -text *.ogg filter=lfs diff=lfs merge=lfs -text *.OGG filter=lfs diff=lfs merge=lfs -text **/*.ogg filter=lfs diff=lfs merge=lfs -text **/*.OGG filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.ZIP filter=lfs diff=lfs merge=lfs -text **/*.zip filter=lfs diff=lfs merge=lfs -text **/*.ZIP filter=lfs diff=lfs merge=lfs -text
It took about 11 seconds to add all files to the next commit. This is two orders of magnitude faster than the same operation would have taken with Plain Old Git.
mslinn@bear repo1 $ time git add -A real 0m11.336s user 0m3.542s sys 0m2.984s
Commits are almost instant, no need to time them.
mslinn@bear repo1 $ git commit -m - [master (root-commit) 4ced4f2] - 12 files changed, 51 insertions(+) create mode 100644 .gitattributes create mode 100644 200MB.zip create mode 100644 BigBuckBunny_640x360.m4v create mode 100644 README.md create mode 100644 big_buck_bunny_480p_h264.mov create mode 100644 big_buck_bunny_480p_stereo.avi create mode 100644 big_buck_bunny_480p_stereo.ogg create mode 100644 big_buck_bunny_720p_h264.mov create mode 100644 big_buck_bunny_720p_stereo.avi create mode 100644 big_buck_bunny_720p_stereo.ogg create mode 100644 enwik9.zip create mode 100644 rdf-files.tar.zip
This is where Git LFS really shows its value. Committing more 2GB at once is not possible with Plain Old Git, because pack sizes cannot exceed 2GB.
mslinn@bear repo1 $ time git push -u origin master Uploading LFS objects: 100% (10/10), 0 B | 0 B/s, done. Enumerating objects: 14, done. Counting objects: 100% (14/14), done. Delta compression using up to 24 threads Compressing objects: 100% (13/13), done. Writing objects: 100% (14/14), 1.91 KiB | 97.00 KiB/s, done. Total 14 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To /mnt/gojira_mslinn/git_eval_repos/repo1.git * [new branch] master -> master branch 'master' set up to track 'origin/master'. real 0m43.957s user 0m0.336s sys 0m0.839s
As you can see, one of the files being pushed is 200 MB. This is twice the 100 MB file size restriction that online vendors have for Plain Old Git. In total, this Git push was 2 GB; however, it only took 34 seconds.
Exercise the Git LFS Repository
I moved to my Windows WSL laptop, called camille
.
It already had Git LFS installed.
The steps for the remainder of this evaluation are:
-
Copied my
gojira_credentials
file (which was created in Mounting Shared Directories on WSL & Ubuntu) to my home directory oncamille
. -
Created the
/mnt/gojira_mslinn
mount point. -
Made an entry to define the
/mnt/gojira_mslinn
mount point in/etc/fstab
as before for mounting the shared directory ongojira
containing the Git repository. - Mounted the shared directory tree
/mnt/gojira_mslinn
- Cloned containing the Gif LFS repository
- Make a change to a small file and a large file
- Commit and push
- Return to the desktop and pull the changes.
mslinn@camille ~ $ scp gojira:gojira_credentials ~/
mslinn@camille ~ $ sudo mkdir /mnt/gojira_mslinn
mslinn@camille ~ $ echo \ "//gojira/mslinn /mnt/gojira_mslinn drvfs credentials=/home/mslinn/gojira_credentials,defaults,gid=1000,uid=1000" | \ sudo tee -a /etc/fstab > /dev/null
mslinn@camille ~ $ sudo systemctl daemon-reload
mslinn@camille ~ $ sudo mount /mnt/gojira_mslinn
mslinn@camille ~ $ mkdir $work/git_lfs && cd $work/git_lfs
mslinn@camille git_lfs $ time git clone /mnt/gojira_mslinn/eval_repos/repo1.git Cloning into 'repo1'... done. Filtering content: 100% (10/10), 1.99 GiB | 32.30 MiB/s, done. real 1m10.895s user 0m2.397s sys 0m4.482s
The git clone
command behaved differently than usual.
This message appeared within a second:
Cloning into 'repo1'... done.
But the computer continued to churn away for 70 seconds more while it downloaded Git LFS content, until that concluded with:
Filtering content: 100% (10/10), 1.99 GiB | 32.30 MiB/s, done.
Now let’s verify that all the large objects are stored in Git LFS. An asterisk (*) after the OID indicates a full object, while a minus (-) indicates an LFS pointer.
mslinn@camille git_lfs $ cd repo1
mslinn@camille repo1 $ git lfs ls-files -s d14b731506 * 200MB.zip (210 MB) 738e2f9998 * BigBuckBunny_640x360.m4v (121 MB) 98959d8b27 * big_buck_bunny_480p_h264.mov (106 MB) 4fc75fa403 * big_buck_bunny_480p_stereo.avi (156 MB) 9b9867582c * big_buck_bunny_480p_stereo.ogg (167 MB) 45c8bafeb9 * big_buck_bunny_720p_h264.mov (417 MB) 919e19d85c * big_buck_bunny_720p_stereo.avi (284 MB) 785b09a585 * big_buck_bunny_720p_stereo.ogg (197 MB) 99cdb5ac84 * enwik9.zip (323 MB) c5608dae76 * rdf-files.tar.zip (161 MB)
None of the large files are shown as being stored in Git LFS. This is because null servers cannot provide a callback, so the Git client is not notified when a large file should be handled as Git LFS content.
Scenario 2: Remote Git Repository With Locally Accessible Large Files
Git Server | Scenario | Git LFS Protocol | Use Cases |
---|---|---|---|
2 | SSH |
|
There are several equivalent syntaxes for specifying a Git URL for SSH. They provide identical results. Use the one that pleases you most. I tend to use the shortest URL possible.
Clone The Bare Repository On a Client Machine
A copy of the empty bare repository was placed in $HOME/repo2
on server gojira
.
The following uses
brace expansion
as a shorthand expression.
mslinn@gojira ~ cp -a bare_repo{,1}
Clones of bare Git repositories are normal Git repositories.
Back on my desktop computer called bear
, I performed the following on WSL/Ubuntu:
-
Cloned the bare repository
repo2
on the server calledgojira
to a new directory on my desktop computerbear
, into a new directory under the$work
directory.Shellmslinn@bear ~ $ mkdir $work/git_lfs && cd $work/git_lfs
mslinn@bear git_lfs $ git clone gojira:repo2 Cloning into 'repo2'... warning: You appear to have cloned an empty repository.
mslinn@bear git_lfs $ cd repo2
mslinn@bear repo2 $ -
No hooks are required because there is no Git server and no Git LFS server in this scenario,
so there will be no callbacks.
I included the
git lfs install
command because of the copy/paste habit that so many people have. These instructions should work even if you use these instructions with a non-null Git LFS server, provided that a suitable URL is used.Shellmslinn@bear repo2 $ git lfs install # No-op Updated Git hooks. Git LFS initialized.
Let's see what the local copy of the bare Git repository looks like at this point:
mslinn@bear repo2 $ git config remote.origin.url gojira:repo2
mslinn@bear repo2 $ ls # No files at present
mslinn@bear repo2 $ tree -ad . └── .git ├── branches ├── hooks ├── info ├── objects │ ├── info │ └── pack └── refs ├── heads └── tags
13 directories
Set Up Tracking
All large files need to be tracked.
The patterns you provide via the git lfs track
command specify the filename patterns to be tracked.
Because media filenames might be in UPPERCASE or lowercase,
the patterns for media files are specified in lowercase and UPPERCASE using the
wp
script.
It is best to set up Git LFS tracking before adding large files to the Git repository.
The large files downloaded by
git_lfs_test_data
will be copied into this Git repository in the next section.
mslinn@bear repo2 $ track -ce avi m4v mov ogg zip Tracking "*.avi" Tracking "*.AVI" Tracking "**/*.avi" Tracking "**/*.AVI" Tracking "*.m4v" Tracking "*.M4V" Tracking "**/*.m4v" Tracking "**/*.M4V" Tracking "*.mov" Tracking "*.MOV" Tracking "**/*.mov" Tracking "**/*.MOV" Tracking "*.ogg" Tracking "*.OGG" Tracking "**/*.ogg" Tracking "**/*.OGG" Tracking "*.zip" Tracking "*.ZIP" Tracking "**/*.zip" Tracking "**/*.ZIP"
The git lfs track
command created .gitattributes
and stored the wildcard patterns into it.
*.ZIP filter=lfs diff=lfs merge=lfs -text **/*.zip filter=lfs diff=lfs merge=lfs -text *.MOV filter=lfs diff=lfs merge=lfs -text *.ogg filter=lfs diff=lfs merge=lfs -text **/*.ogg filter=lfs diff=lfs merge=lfs -text **/*.OGG filter=lfs diff=lfs merge=lfs -text *.avi filter=lfs diff=lfs merge=lfs -text *.mov filter=lfs diff=lfs merge=lfs -text **/*.mov filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text **/*.ZIP filter=lfs diff=lfs merge=lfs -text *.AVI filter=lfs diff=lfs merge=lfs -text **/*.AVI filter=lfs diff=lfs merge=lfs -text *.M4V filter=lfs diff=lfs merge=lfs -text **/*.m4v filter=lfs diff=lfs merge=lfs -text *.OGG filter=lfs diff=lfs merge=lfs -text **/*.avi filter=lfs diff=lfs merge=lfs -text *.m4v filter=lfs diff=lfs merge=lfs -text **/*.M4V filter=lfs diff=lfs merge=lfs -text **/*.MOV filter=lfs diff=lfs merge=lfs -text
The git lfs track
command also created the .git/lfs
directory.
mslinn@bear repo2 $ tree -ad . └── .git ├── branches ├── hooks ├── info ├── lfs │ └── tmp ├── objects │ ├── info │ └── pack └── refs ├── heads └── tags
13 directories
Add Content
It is time to add content to the Git repository:
- Create a normal file.
-
Copy the large files from the
git_lfs_test_data
script into the local copy of therepo2
Git repository.
mslinn@bear repo2 $ echo 'Hello world' > normal_file.txt
mslinn@bear repo2 $ time scp gojira:/work/git/git_lfs_test_data/* . 200MB.zip 100% 200MB 114.2MB/s 00:01 BigBuckBunny_640x360.m4v 100% 116MB 111.5MB/s 00:01 big_buck_bunny_480p_h264.mov 100% 102MB 111.4MB/s 00:00 big_buck_bunny_480p_stereo.avi 100% 149MB 113.2MB/s 00:01 big_buck_bunny_480p_stereo.ogg 100% 159MB 118.9MB/s 00:01 big_buck_bunny_720p_h264.mov 100% 397MB 115.0MB/s 00:03 big_buck_bunny_720p_stereo.avi 100% 271MB 111.8MB/s 00:02 big_buck_bunny_720p_stereo.ogg 100% 188MB 113.9MB/s 00:01 enwik9.zip 100% 308MB 115.1MB/s 00:02 rdf-files.tar.zip 100% 153MB 114.9MB/s 00:01 real 0m18.208s user 0m2.456s sys 0m2.433s
I previously mentioned that the
git add
command is slow when working with large files.
However, when large files are added to Git LFS,
the process only takes as long as necessary to place a copy of the large files in .git/lfs/objects
.
mslinn@bear repo2 $ time git add -A real 0m11.237s user 0m3.315s sys 0m2.793s
As we know, gitadd
takes snapshots of normal files and saves them in the staging area
(.git/index
).
This repository only has one normal file (normal_file.txt
), so the Git index
is small right now:
$ du -h .git/index 4.0K .git/index
The large tracked files that were just added should have been snapshotted and saved to .git/lfs/objects
.
The last line of the following output is highlighted,
and shows that the total amount of data staged is 2 GB,
which, as you may recall, is the total amount of bunny videos that were downloaded.
mslinn@bear repo2 $ du -h .git/lfs/objects 398M .git/lfs/objects/45/c8 398M .git/lfs/objects/45 150M .git/lfs/objects/4f/c7 150M .git/lfs/objects/4f 116M .git/lfs/objects/73/8e 116M .git/lfs/objects/73 188M .git/lfs/objects/78/5b 188M .git/lfs/objects/78 272M .git/lfs/objects/91/9e 272M .git/lfs/objects/91 102M .git/lfs/objects/98/95 102M .git/lfs/objects/98 308M .git/lfs/objects/99/cd 308M .git/lfs/objects/99 160M .git/lfs/objects/9b/98 160M .git/lfs/objects/9b 154M .git/lfs/objects/c5/60 154M .git/lfs/objects/c5 200M .git/lfs/objects/d1/4b 200M .git/lfs/objects/d1 2.0G .git/lfs/objects
We can even view the videos stored in the Git LFS staging area!
mslinn@bear repo2 $ vlc .git/lfs/objects/45/c8/45c8bafeb9a53df7f491198d2e71529701bcf1cd51805782089fac1d32869f9b
Commit
Now the files need to be committed; this command executes quickly.
mslinn@bear repo2 $ time git commit -m 'Added a normal file and large files' [master (root-commit) 7d0fe8c] Added a normal file and large files 12 files changed, 51 insertions(+) create mode 100644 .gitattributes create mode 100644 200MB.zip create mode 100644 BigBuckBunny_640x360.m4v create mode 100644 big_buck_bunny_480p_h264.mov create mode 100644 big_buck_bunny_480p_stereo.avi create mode 100644 big_buck_bunny_480p_stereo.ogg create mode 100644 big_buck_bunny_720p_h264.mov create mode 100644 big_buck_bunny_720p_stereo.avi create mode 100644 big_buck_bunny_720p_stereo.ogg create mode 100644 enwik9.zip create mode 100644 normal_file.txt create mode 100644 rdf-files.tar.zip real 0m0.327s user 0m0.016s sys 0m0.027s
Push Changes To The Bare Repository
The files are ready to be pushed to the bare repository.
Only normal_file.txt
will be handled normally,
while the others will be handled as large files.
mslinn@bear repo2 $ time git push -u origin master Locking support detected on remote "origin". Consider enabling it with: $ git config lfs.https://gojira/home/mslinn/repo2.git/info/lfs.locksverify true Uploading LFS objects: 100% (10/10), 2.1 GB | 115 MB/s, done. Enumerating objects: 14, done. Counting objects: 100% (14/14), done. Delta compression using up to 24 threads Compressing objects: 100% (13/13), done. Writing objects: 100% (14/14), 1.93 KiB | 123.00 KiB/s, done. Total 14 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To ssh://gojira/home/mslinn/repo2 * [new branch] master -> master branch 'master' set up to track 'origin/master'. real 0m19.457s user 0m3.541s sys 0m3.557s
That happened quickly!
I do not believe the Locking support detected
message since http
is not being used.
If you type the git config
command as suggested, the warning goes away, which is fine,
but nothing changes unless http
is used.
The above pushed LFS objects to gojira:/home/mslinn/repo2/.git/lfs/objects
.
We can see the same IDs for the large files
in both copies of the repository.
mslinn@bear repo2 $ tree .git/lfs/ .git/lfs/ .git/lfs/ ├── cache │ └── locks │ └── refs │ └── heads │ └── master │ └── verifiable ├── objects │ ├── 45 │ │ └── c8 │ │ └── 45c8bafeb9a53df7f491198d2e71529701bcf1cd51805782089fac1d32869f9b │ ├── 4f │ │ └── c7 │ │ └── 4fc75fa403994e7c313da139d93a5aebdbda27cc951616aa4e480db6877c9850 │ ├── 73 │ │ └── 8e │ │ └── 738e2f999860553d056dd79c952f58f63cbb73892a57c72342ce9e5330d9d2d7 │ ├── 78 │ │ └── 5b │ │ └── 785b09a585be55f81326a3fcef2cdeeb7ebbc33932b6305fd84209928df67f28 │ ├── 91 │ │ └── 9e │ │ └── 919e19d85c51e8f07074f9e51127c103280d7623c2b6696f2621b4fca6850e76 │ ├── 98 │ │ └── 95 │ │ └── 98959d8b270c6c35c9e2c906559a47c49a0e1491c8c1d6e5576164f3549aeea6 │ ├── 99 │ │ └── cd │ │ └── 99cdb5ac84392252d3f0912ccedd195bc95bd80cbef3b0cdf2eee4ad9a3b7a51 │ ├── 9b │ │ └── 98 │ │ └── 9b9867582cc9cf88b03f8a2065c4f86ec17e650e65c369e1ea4d0d37e5df5da6 │ ├── c5 │ │ └── 60 │ │ └── c5608dae76ef836dfe8af2651d3869a2db0c3a9015ac43fb8d17f72499d17c58 │ └── d1 │ └── 4b │ └── d14b73150642f30d2342e6620fa537ea273a58b8b751fc5af8f4aabe809f8fc4 └── tmp 28 directories, 11 files
The same files exist in the .git/lfs/objects
directory on the server.
mslinn@bear repo2 $ ssh gojira tree repo2/.git/lfs/objects repo2/.git/lfs/objects ├── 45 │ └── c8 │ └── 45c8bafeb9a53df7f491198d2e71529701bcf1cd51805782089fac1d32869f9b ├── 4f │ └── c7 │ └── 4fc75fa403994e7c313da139d93a5aebdbda27cc951616aa4e480db6877c9850 ├── 73 │ └── 8e │ └── 738e2f999860553d056dd79c952f58f63cbb73892a57c72342ce9e5330d9d2d7 ├── 78 │ └── 5b │ └── 785b09a585be55f81326a3fcef2cdeeb7ebbc33932b6305fd84209928df67f28 ├── 91 │ └── 9e │ └── 919e19d85c51e8f07074f9e51127c103280d7623c2b6696f2621b4fca6850e76 ├── 98 │ └── 95 │ └── 98959d8b270c6c35c9e2c906559a47c49a0e1491c8c1d6e5576164f3549aeea6 ├── 99 │ └── cd │ └── 99cdb5ac84392252d3f0912ccedd195bc95bd80cbef3b0cdf2eee4ad9a3b7a51 ├── 9b │ └── 98 │ └── 9b9867582cc9cf88b03f8a2065c4f86ec17e650e65c369e1ea4d0d37e5df5da6 ├── c5 │ └── 60 │ └── c5608dae76ef836dfe8af2651d3869a2db0c3a9015ac43fb8d17f72499d17c58 └── d1 └── 4b └── d14b73150642f30d2342e6620fa537ea273a58b8b751fc5af8f4aabe809f8fc4
21 directories, 10 files
Clone The Bare Repository Again
Scenario 3: GitHub With Locally Accessible Large Files
Git Server | Scenario | Git LFS Protocol | Use Cases |
---|---|---|---|
GitHub | 3 | local |
|
Scenario 4: GitHub With Remotely Accessible Large Files Over SSH
Git Server | Scenario | Git LFS Protocol | Use Cases |
---|---|---|---|
4 | SSH |
|
I have had good results with Git LFS over SSH when SSH keys have been deployed throughout the network. Without SSH keys, an authentication mechanism would be required.
Git Server | Scenario | Git LFS Protocol | Use Cases |
---|---|---|---|
5 | http
|
|
I have published 8 articles about the Git large file system (LFS). They are meant to be read in order.
- Git Large File System Overview
- Git LFS Scripts
- Git LFS Client Installation
- Git LFS Server URLs
- Git-ls-files, Wildmatch Patterns and Permutation Scripts
- Git LFS Tracking, Migration and Un-Migration
- Git LFS Client Configuration & Commands
- Git LFS SSH Authentication
- Working With Git LFS
- Evaluation Procedure For Git LFS Servers
- Git LFS server tests:
6 articles are still in process.
Instructions for typing along are given for Ubuntu and WSL/Ubuntu. If you have a Mac, most of this information should be helpful.