git-lfs is a weird one
I quite like using git for managing le content, but I also quite like not having a
repository get megabytes bigger every time I add a screenshot, so I thought today would be a good day to try
out
git-lfs, which basically stores large files out of band and just versions the metadata and a
reference to them.
First of all, I wanted a directory to just chuck things in - let's call it ./blobs. This requires
a .gitattributes file in the
repository root that looks like this:
blobs/** filter=lfs diff=lfs merge=lfs -text
As I often do with git, since it doesn't have any interest in committing an empty directory, I
added a README.md file to the directory. No amount of fucking around would make git-lfs not try to add the README.md as an LFS file (and it's not just me).
[attr]not-lfs !filter !diff !merge text
blobs/** filter=lfs diff=lfs merge=lfs -text
blobs/README.md not-lfs
not
blobs/** filter=lfs diff=lfs merge=lfs -text
blobs/README.md -filter -diff -merge -text
Eventually I gave up and just added blobs/README.md first, then added the .gitattributes file after, and that seems to work.
While it didn't seem to stop screwing around with the file to begin with, adding this to .gitattributes does seem to mostly work, and removing it manages to trigger
this
issue in magit:
blobs/README.md -filter -diff -merge -text
So, I'm not really sure. Perhaps I'm just misunderstanding how it's meant to work.
Anyway, I had my README.md as a text file and added a couple of binary files. Now for the easiest
part, time to push the repository! Let's do that:
Pushing to ssh://my.forgejo.example/user/repo.git
Uploading LFS objects: 50% (1/2), 173 KB | 3.3 KB/s, done.
LFS: Client error &{%!!(string=https) %!!(string=) %!!(*url.Userinfo=<nil>) %!!(string=my.forgejo.example) %!!(string=/user/repo.git/info/lfs/objects/3287493847ab1231231235452431221/412341234) %!!(string=) %!!(bool=false) %!!(bool=false) %!!(string=) %!!(string=) %!!(string=)}s(MISSING) from HTTP 413
Well, that's unexpected. Especially unexpected is getting an HTTP
error from a ssh push. I had been fucking around a lot with LFS
by this point so spent a while looking at paths and permissions on the server to see if I'd collided
something, but then I searched a lot for "HTTP 413 git-lfs" and got annoyed at all the results just being
people misconfiguring the max body size limit for their frontend HTTP proxy rather than explaining my special
SSH problem. Eventually it occurred to me that having an HTTP error might actually indicated an HTTP problem,
so I read one of the nginx articles and it was about files above 5MB causing problems, and
noticed that precisely one out of two files copied OK, then I had a look at ./blobs directory:
❯ ls -l blobs/
-rw-r--r-- 1 rob staff 130 May 3 14:19 some-small-file
-rw-r--r-- 1 rob staff 114 May 3 14:00 README.md
-rw-r--r-- 1 rob staff 5103114 May 3 14:19 some-file-above-5MB
Anyway, I added client_max_body_size 3000m; to the proxy configuration in nginx and then it
worked, voila.
Eventually I found the rather surprising fact that git-lfs
historically only used ssh for authentication, doing the actual data transfer via HTTP. There's a proposal to not do that
and an out-of-tree implementation.
gitea actually has a configuration option to do it all over ssh, which is disabled by default due to a now-fixed bug in git-lfs (and
another one).
forgejo hasn't ported that code yet since it has bad test coverage, which is a bit unfortunate.
Anyway! Now it mostly works.