Packfile과 gc가 큰 object store를 유지해
blob, tree, commit, tag마다 파일 하나를 두는 loose object는 단순하지만 규모가 커지면 비싸. commit이 10만 개이고 blob이 수백만 개인 repo는 .git/objects/에 파일 수백만 개를 만들어 filesystem과 listing, remote 전송에 부담을 줘. Git은 많은 object를 압축하고 연결한 .pack file과 동반 .idx index로 해결해. Pack된 object는 빠르게 다룰 수 있고 전송량도 크게 줄어.
git gc, 곧 garbage collect는 loose object를 pack하고 도달할 수 없는 것을 제거하며 index를 다시 만들어. 현대 Git은 loose object 200개, pack 7000개 같은 임계값을 넘으면 gc --auto를 실행하고 대부분 repo에는 그것으로 충분해. 오래된 공유 repo에서 git gc --aggressive로 pack을 더 철저히 다시 만들 수 있지만 CPU 비용이 크므로 server mirror나 비업무 시간에 실행해.
핵심은 도달 가능성이야. HEAD, branch, tag, reflog entry, stash 같은 ref에서 닿을 수 있는 object는 살아남고 어디에서도 닿지 않는 object가 GC 후보가 돼. Reflog는 90일짜리 안전망이라 orphaned commit도 entry가 만료될 때까지 닿을 수 있어. git gc --prune=now는 그 안전망을 건너뛰고 도달 불가능한 object를 즉시 없애므로, git filter-repo로 민감한 내용을 다시 쓴 뒤 진짜 제거할 때 쓸 수 있어.
git fsck는 object 무결성을 검사하고 git count-objects -v는 loose와 packed 수, disk 크기를 보여줘. Git 2.30+의 git maintenance start는 gc, pack-refs, commit-graph, prefetch 같은 background task를 등록해 별도 cron 없이 repo를 관리해. commit-graph file은 git log --graph나 git merge-base 같은 조상 query를 빠르게 하며 git config core.commitGraph true로 켜고 git commit-graph write로 갱신할 수 있어.