How it works
The explanation, with examples you can run.
Try all three on a small repository
A local repository with five services stands in for a big one. Partial clone needs the server to allow filters, which hosting services do; locally you switch it on with uploadpack.allowFilter.
mkdir big-demo && cd big-demogit init -q -b main srcfor n in 1 2 3 4 5; do mkdir src/svc$n; echo "code $n" > src/svc$n/main.txt; git -C src add .; git -C src commit -q -m "Commit $n"; donegit -C src config uploadpack.allowFilter truegit clone -q --depth 1 "file://$PWD/src" shallowgit -C shallow log --onelinegit -C shallow rev-parse --is-shallow-repositoryb2ac409 Commit 5trueThe shallow clone has only the tip commit. That is ideal for CI that builds once and throws the clone away, and it is what many CI systems do by default. The cost: git log, git blame and finding a merge base stop at the cut. git fetch --deepen=50 or git fetch --unshallow brings history back.
git clone -q --filter=blob:none "file://$PWD/src" partialgit -C partial log --oneline | wc -lgit -C partial config remote.origin.partialclonefilter 5blob:noneThe partial clone has all five commits and every tree, but only the blobs needed for the files checked out. When you check out an old commit or run a diff that needs an old version, Git fetches the missing blobs from the remote (the "promisor") on demand. For day-to-day development in a big repository this is usually the best default. --filter=tree:0 also skips trees and suits throwaway builds; it is slower if you later need history.
git clone -q --filter=blob:none --sparse "file://$PWD/src" sparsels sparsegit -C sparse sparse-checkout set svc2ls sparsesvc2With --sparse, the clone starts with only top-level files (there are none here), and sparse-checkout set adds the directories you work on. Cone mode, the default, matches whole directories, which keeps it fast. Combined with a partial clone, Git downloads only the blobs for those directories. wc -l pads its count with spaces on macOS; on Linux it prints just 5.
Git LFS for large binaries
Git stores every version of every file, and binary files such as videos, models and design files don't delta-compress well. Once a big file is committed, every future clone downloads it, even if a later commit deletes it. Git Large File Storage, a separate extension, replaces tracked files in the repository with small text pointers and stores the real content on an LFS server (GitHub, GitLab and Bitbucket provide one).
git init -q -b main lfs-demo && cd lfs-demohead -c 100000 /dev/urandom > design.psdgit lfs installgit lfs track "*.psd"git add .gitattributes design.psdgit commit -q -m "Add design file via LFS"cat .gitattributesgit cat-file -p HEAD:design.psdUpdated Git hooks.Git LFS initialized.Tracking "*.psd"*.psd filter=lfs diff=lfs merge=lfs -textversion https://git-lfs.github.com/spec/v1oid sha256:3bc10117a15eedb0de1bbf832527122ba5724febe85bcf29cf32600f646887acsize 100000git lfs track writes a rule to .gitattributes. The blob Git committed for design.psd is the three-line pointer: the SHA-256 of the real content (random here, so yours will differ) and its size. The 100 kB of real content sits in .git/lfs/objects and is uploaded to the LFS server on push; clones download it only for the commits they check out. LFS is a separate program, not part of Git: this was run with git-lfs 3.4.1 in an Ubuntu container, since it is not installed on the Mac used for the other examples. Moving files that are already committed into LFS means rewriting history with git lfs migrate.
Other levers for very large repositories: git maintenance start schedules background repacking and prefetching, and scalar (shipped with Git) clones with partial clone, sparse checkout and maintenance already set up.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.