git lfs track writes a pattern into .gitattributes with filter=lfs diff=lfs merge=lfs -text. From then on, git add runs the clean filter, which moves each matching file into .git/lfs/objects and stages a pointer; checkout runs the smudge filter, which swaps the pointer for the content (15).
git lfs track "public/covers/*.png"
# Copy the six color-corrected covers into public/covers/
git add .gitattributes .lfsconfig .husky public/covers
git commit -qm "Store the cover images in Git LFS"
git lfs ls-files
git cat-file -p HEAD:public/covers/1.png
git push -q
grep -c "PUT" ../lfs/logTracking "public/covers/*.png" → lint-staged could not find any staged files matching configured tasks. 083f4005e1 * public/covers/1.png 11d8f69d93 * public/covers/2.png ... version https://git-lfs.github.com/spec/v1 oid sha256:083f4005e1c1911bed16707b8824ad4a6a95868a9dcd890bad9a79427d9f8b73 size 1575768 ... 6
Git 1,932 stored a 132-byte pointer: the spec version, the content's SHA-256 and its size. The pre-push hook sent the files with the LFS Batch API: one POST .../objects/batch asking which objects the server lacks, then one PUT per missing object, six in the server log. The pre-receive hook of Fail or Warn? stayed silent, because only pointers reached Git.

Track a pattern before the first commit of such a file, and track only binaries, since diffs and merges of LFS files see just pointers. For unmergeable files such as design sources, git lfs lock gives one person exclusive editing.