docs(lfs): document the sha the contents API expects for LFS files (#542)

Closes #243.

The `sha` of the contents API is compared against the ID of the blob the commit has at that path, and for a file tracked by Git LFS that blob is the pointer file. Sending the `lfs_oid` or a checksum of the file content fails with `sha does not match`, and nothing in the documentation said so.

Adds a section to the LFS page: use the `sha` from `GET /repos/{owner}/{repo}/contents/{filepath}`, not `lfs_oid`, and note that the API does turn the content into an LFS object by itself when `.gitattributes` tracks the path (`modifyFile()` stores the object and commits the pointer), so nothing else has to be done differently.

The swagger comments upstream are being fixed in https://github.com/go-gitea/gitea/pull/38915, which will reach `/api/next/` through the scheduled job and the released reference with 1.28. The documents of 1.22 – 1.27 are frozen, so the guide is the only place where readers of the current release can find it.

<!-- cloudflare-preview --> Preview: https://pr-542.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/542
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
This commit is contained in:
Lunny Xiao
2026-09-12 11:16:22 +00:00
committed by bircni
parent 24a7eb79e5
commit 9a6d0d90bf
+21
View File
@@ -41,3 +41,24 @@ client that causes SSH transfers to hang: https://github.com/git-lfs/git-lfs/pul
This can be worked around on all the client machines by setting the git config:
`git config --global lfs.ssh.automultiplex false`
:::
# Changing LFS files through the API
The [contents API](https://docs.gitea.com/api/operations/repo-change-files/)
works on LFS tracked files as well: send the file content as usual and Gitea
stores it as an LFS object and commits a pointer file, as long as the path is
matched by a `filter=lfs` rule in `.gitattributes`.
What is easy to get wrong is the `sha` of the file being changed, which
`PUT`/`DELETE /repos/{owner}/{repo}/contents/{filepath}` and
`POST /repos/{owner}/{repo}/contents` require for an existing file. Gitea
compares it with the ID of the blob the commit has at that path, and for an LFS
tracked file that blob is the **pointer file**, not the content:
- use the `sha` returned by
[`GET /repos/{owner}/{repo}/contents/{filepath}`](https://docs.gitea.com/api/operations/repo-get-contents/)
- do not use `lfs_oid` from the same response, which identifies the LFS object,
and do not use a checksum of the file itself
Sending anything else fails with `sha does not match`, even though the request
looks correct.