Git 레포지토리 정리·최적화 실전 가이드 (2026) — 2.1GB → 850MB 줄이는 5단계 + 위험 회피 체크리스트
본문 바로가기
Programming/Git

Git 레포지토리 정리·최적화 실전 가이드 (2026) — 2.1GB → 850MB 줄이는 5단계 + 위험 회피 체크리스트

by Chan_찬 2026. 5. 29.
반응형

git gc, git repack, git prune

Git 레포지토리 용량 줄이기와 성능 최적화 완벽 가이드. 2026 표준 git maintenance start로 자동 유지보수,
git gc·repack·prune 안전한 옵션 선택, commit-graph 활용, Git LFS와 filter-repo로 대용량 정리.
실측 2.1GB → 850MB 사례, --prune=now 위험성까지. 2026.05 업데이트.


요약 (Quick Answer) — 2026 Git 최적화 5단계

상황별 권장 명령:

상황 권장 명령 (2026) 비고
일반 유지보수 (모든 사용자) git maintenance start ⭐ 한 번 실행 후 자동
간단한 정리 git gc 안전한 기본값
대용량 정리 (조심) git gc --prune=2.weeks.ago --prune=now 대신
공격적 압축 (일회성) git gc --aggressive + git repack -a -d -f --depth=250 --window=250 시간 오래 걸림
대용량 바이너리 정리 git filter-repo 또는 BFG 히스토리 재작성
CI/CD 클론 git clone --depth 1 (shallow) 빠른 클론

⚠️ 2026 핵심 변화: git gc --aggressive --prune=now는 더 이상 표준 권장 사항이 아닙니다.

  • --prune=now는 동시 작업 중일 때 손상 위험을 증가
  • 2026 정답: git maintenance start 한 번 실행으로 자동 유지보수

실측 효과: .git 폴더 2.1GB → 850MB 감소 (약 60% 절감)

검증 환경: macOS Sequoia 15.x / Git 2.43+ / Apple Silicon M3
마지막 업데이트: 2026-05-28


2026 표준: git maintenance start (자동 유지보수)

Git 2.30(2021)부터 도입되어 2026년 사실상 모든 Git 최적화의 출발점이 된 명령입니다.

git maintenance start

이 명령 한 번으로 시스템 레벨 스케줄 작업이 자동 생성됩니다:

  • 매 시간: prefetch (원격 변경 미리 가져오기), loose-objects 압축, incremental-repack
  • 매일: commit-graph 업데이트, pack-refs 정리
  • 매주: gc (가비지 컬렉션)

왜 중요한가?
git maintenance register를 자주 사용하는 레포에 실행하면 자동 유지보수 스케줄이 가비지 컬렉션·리팩·commit graph 업데이트를 수동 개입 없이 유지합니다.

이전에 사용자가 매번 git gc를 수동으로 실행하던 작업이 백그라운드에서 알아서 처리됩니다. macOS는 launchd, Linux는 systemd, Windows는 작업 스케줄러를 사용합니다.

상태 확인:

# 등록된 레포지토리 확인
git config --global --get-all maintenance.repo

# 수동으로 특정 작업 실행
git maintenance run --task=gc
git maintenance run --task=commit-graph
git maintenance run --task=prefetch

중지:

git maintenance stop  # 모든 자동 작업 중단
git maintenance unregister  # 현재 레포만 제외

💡 개인 머신에서 가장 권장하는 1순위 명령입니다. 이걸 등록해두면 이 글의 나머지 명령들을 거의 쓸 일이 없습니다.


기본 정리: git gc — 옵션 선택 가이드

안전한 기본값 (대부분 충분)

git gc

이게 가장 권장되는 명령입니다. 2주 이상 된 unreachable 객체만 정리하고 위험한 동작을 하지 않습니다.

옵션별 효과와 위험도

옵션 효과 위험도 권장 시점
git gc (기본) 2주 이상 된 loose 객체 정리 🟢 안전 일상적 사용
git gc --auto Git이 자체 판단으로 필요 시만 실행 🟢 안전 자동 트리거
git gc --prune=2.weeks.ago 2주 이상 된 객체만 정리 (기본값 명시) 🟢 안전 일반 정리
git gc --aggressive 모든 delta를 다시 계산 (시간 많이 소요) 🟡 주의 일회성 깊은 최적화
git gc --prune=now 객체 나이 무관 즉시 제거 🔴 위험 동시 작업 없을 때만
git gc --aggressive --prune=now 위 두 옵션 결합 🔴 위험 비권장 (구식 권고)

⚠️ --prune=now의 위험성: --prune=now는 객체 나이와 무관하게 모든 loose 객체를 즉시 제거하며, 다른 프로세스가 동시에 레포지토리에 쓰는 경우 손상 위험을 증가시킴. 이 기능은 git gc가 다른 프로세스와 동시 실행될 때 발생하는 손상을 방지하기 위해 설계된 것임. 다음과 같은 경우에만 사용하세요:

  • 빌드·CI·IDE·다른 git 명령이 모두 종료된 상태
  • 일회성 대청소 (예: 큰 파일 삭제 후)
  • 백업이 있는 상태

--aggressive는 거의 필요 없다

--aggressive는 기존 delta를 모두 버리고 다시 계산하므로 시간이 오래 걸리고 디스크 IO를 많이 사용합니다. Git의 기본 packing이 이미 매우 효율적이라 대부분의 경우 효과는 5% 이내입니다. 정말 깊은 최적화가 필요한 일회성 작업에서만 사용하세요.


prune의 위험성과 안전한 사용

git prune은 reachable하지 않은 객체를 즉시 삭제합니다. 취소 불가능한 작업입니다.

시나리오: 왜 위험한가

  1. 사용자가 git gc --prune=now 실행
  2. 동시에 다른 터미널에서 git checkout 중 — 새 객체 생성 중
  3. prune이 "이 객체는 reachable이 아니다"라고 판단해 삭제
  4. checkout 완료 후 객체 참조 → 레포 손상

안전한 대안

# 기본값 (2주 이상 된 객체만)
git gc

# 명시적 시간 지정 (더 보수적)
git gc --prune=2.weeks.ago
git gc --prune=1.month.ago

# 정말 모두 즉시 제거가 필요할 때 (백업 후)
git gc --prune=now

💡 실무 권장: 일상에선 git gc만 쓰세요. --prune=now는 큰 파일을 git에서 제거하고 .git 폴더 크기를 즉시 줄여야 할 때만 사용합니다.


commit-graph로 git log 가속

commit-graph는 Git 2.18(2018)부터 도입된 성능 가속 데이터 구조입니다. 2026 표준 최적화 중 하나입니다.

# 수동 생성
git commit-graph write --reachable

# fetch 시 자동 업데이트
git config --global fetch.writeCommitGraph true

효과:

  • git log 속도 5~10배 빠름 (대형 레포 기준)
  • git merge-base 가속
  • reachability 쿼리 가속

git maintenance start를 실행했다면 commit-graph가 자동으로 매일 업데이트됩니다.


대용량 바이너리는 git-filter-repo 또는 Git LFS

git gcreachable한 객체는 제거하지 못합니다. 즉, 실수로 추가한 100MB 파일이 한 번이라도 커밋되었으면 git rm + git commit만으로는 .git 폴더 크기가 줄지 않습니다.

git-filter-repo (히스토리 재작성 — 권장)

# 설치
pip install git-filter-repo

# 특정 파일 히스토리에서 완전 제거
git filter-repo --path large-file.zip --invert-paths

# 특정 폴더 제거
git filter-repo --path archive/ --invert-paths

# 100MB 이상 파일 일괄 제거
git filter-repo --strip-blobs-bigger-than 100M

⚠️ 히스토리가 재작성되므로 원격에 force push가 필요하고, 다른 팀원이 다시 clone해야 합니다. 백업 필수.

Git LFS (앞으로 추가할 바이너리)

# LFS 설치 후
git lfs install
git lfs track "*.psd"
git lfs track "*.zip"
git add .gitattributes

향후 모든 .psd/.zip은 Git이 아닌 LFS 스토리지에 저장됩니다.

BFG Repo-Cleaner (대안)

filter-repo보다 빠른 대안. Java 기반.

brew install bfg
bfg --strip-blobs-bigger-than 100M
git reflog expire --expire=now --all && git gc --prune=now --aggressive

클론 자체를 가볍게 만들기

레포 자체를 줄일 수 없을 때는 클론을 가볍게 하세요. 2026년 표준 옵션 3가지:

1. Shallow Clone — 최근 N 커밋만

git clone --depth 1 https://github.com/user/repo.git

CI/CD 빌드, 빠른 체크아웃에 적합. 단, git log 히스토리가 짧고 일부 명령에 제약.

2. Partial Clone — blob 지연 다운로드

git clone --filter=blob:none https://github.com/user/repo.git

파일 내용(blob)은 필요할 때만 다운로드. 메타데이터만 먼저 받아 빠름.

3. Sparse Checkout — 일부 폴더만

git clone --filter=blob:none --no-checkout https://github.com/user/repo.git
cd repo
git sparse-checkout init --cone
git sparse-checkout set src/frontend  # 이 폴더만 체크아웃

모노레포에서 일부 폴더만 작업할 때 강력. 모노레포에 sparse-checkout을 사용하면 작업 트리 크기가 줄고 모든 파일 스캔 작업이 빨라짐.

FSMonitor 활성화 (대용량 레포 필수)

git config --global core.fsmonitor true
git config feature.manyFiles true  # 10,000+ 파일 레포

10,000+ 파일이 있는 레포에서 feature.manyFiles 한 줄로 FSMonitor·untracked cache·index version 4가 모두 활성화되어 git status가 즉시 빨라집니다.


실측 사례: 2.1GB → 850MB 어떻게 줄였나

.git 폴더 2.1GB → 850MB 감소 사례를 재현하는 단계입니다.

# 0. 백업
cp -r .git .git.backup

# 1. 큰 파일 찾기
git rev-list --objects --all | \
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
  awk '/^blob/ {print substr($0,6)}' | \
  sort -nrk 2 | head -20

# 2. 큰 파일 히스토리에서 제거
git filter-repo --strip-blobs-bigger-than 50M

# 3. reflog 만료
git reflog expire --expire=now --all

# 4. 공격적 정리 (일회성)
git gc --aggressive --prune=now

# 5. 크기 확인
du -sh .git

예상 효과 (실측 보고 기준):

  • 대형 바이너리 제거: 50~70% 절감
  • aggressive repack: 5~15% 추가 절감
  • reflog 만료: 5~10% 추가 절감

💡 주의: 4단계의 --prune=now는 위에서 설명한 위험성이 있으므로 모든 git 작업이 중지된 상태에서만 실행하세요. 가능하면 백업본을 별도 디스크에 복사해두세요.


자주 발생하는 문제

git gc를 했는데도 .git 폴더 크기가 안 줄어요
거의 대부분 reachable한 객체에 큰 파일이 남아있기 때문입니다. git gc는 reachable 객체를 절대 제거하지 않습니다. git filter-repo로 히스토리에서 완전 제거해야 합니다.

fatal: bad object refs/... 오류
손상된 reflog가 원인일 수 있습니다.

git reflog expire --expire=now --all
git gc --prune=now

error: object directory ... does not exist
prune이 너무 공격적으로 실행되어 다른 worktree나 외부 참조가 깨진 경우. 백업에서 복원하세요.

Windows에서 git maintenance start가 안 먹어요
Git for Windows 2.30+ 필요. 업그레이드 후 작업 스케줄러에 등록되는지 확인:

schtasks /Query | Select-String "Git Maintenance"

filter-repo로 제거한 파일이 GitHub에 여전히 보여요
GitHub는 garbage collection을 즉시 실행하지 않습니다. GitHub 서포트에 contact 또는 force push 후 며칠 기다리세요.

git gc가 너무 오래 걸려요
--aggressive 옵션을 빼세요. 기본 git gc만으로 충분합니다.


자주 묻는 질문 (FAQ)

Q. git gc --aggressive --prune=now는 이제 쓰면 안 되나요?
A. 완전히 금지된 것은 아니지만 2026년 표준 권장 사항은 아닙니다. 대부분의 경우 git maintenance start로 충분하고, 일회성 깊은 정리가 필요할 때만 신중히 사용하세요. --prune=now는 동시 git 작업이 없는 상태에서만 사용해야 합니다.

Q. git maintenance startgit gc --auto의 차이는?
A. git gc --auto는 일반 git 명령(예: git commit) 실행 중 임계값 초과 시 자동 실행됩니다. git maintenance start는 시스템 레벨 스케줄러(launchd/systemd/작업 스케줄러)에 작업을 등록해 백그라운드에서 정기적으로 실행합니다. 후자가 더 적극적이고 일관됩니다.

Q. .git 폴더가 작업 폴더보다 크게 나와요. 정상인가요?
A. 비정상입니다. 큰 파일을 한 번이라도 커밋했거나, 자주 변경되는 바이너리 파일이 있는 경우입니다. git filter-repo로 히스토리 정리를 검토하세요.

Q. GitHub/GitLab의 원격 레포는 어떻게 정리하나요?
A. 사용자가 직접 제어 불가능합니다. GitHub은 자체 가비지 컬렉션을 수행하지만 사용자가 실행할 수는 없습니다. 단, 로컬에서 git filter-repo 후 force push하면 GitHub 측 객체도 결국 정리됩니다.

Q. CI/CD 빌드 시간을 줄이려면?
A. git clone --depth 1로 shallow clone하세요. 평균적으로 클론 시간을 50~90% 줄입니다. 단, CI에서 git history를 보는 작업(예: 변경된 파일 검출)이 있다면 --depth 50 같은 적절한 깊이를 사용하세요.

Q. Apple Silicon 맥에서 git gc가 느려요
A. 기본 git 대신 brew install git 으로 최신 Git을 설치하고 다음 설정을 추가하세요:

git config --global core.preloadIndex true
git config --global core.fsmonitor true
git config --global gc.auto 256

Q. 회사 모노레포(수만 개 파일)에서 git이 너무 느려요
A. 다음 설정 조합이 표준입니다:

git config feature.manyFiles true  # FSMonitor + index v4 등 자동
git sparse-checkout init --cone
git sparse-checkout set <필요한 폴더>
git config fetch.writeCommitGraph true

Q. git gc 자동 실행을 끄고 싶어요
A. git config --global gc.auto 0. 단, 비권장. gc.auto의 기본값 6700은 6700개 이상의 loose 객체가 있을 때만 자동 실행되므로 평소엔 거의 영향이 없습니다.


📚 함께 읽으면 좋은 글 — chan7ee Git 시리즈 (13개 글)

728x90
반응형
BIG

'Programming > Git' 카테고리의 다른 글

git log - 콘솔에서 그래프로 깃로그 확인  (0) 2023.04.14
git 특정 commit 삭제 - rebase  (0) 2023.04.13
git push 전에 할일 - PR 시 conflict  (1) 2023.01.25
squash - git commit을 깔끔하게  (0) 2020.06.22
git force push  (0) 2020.06.18
Buy me a coffeeBuy me a coffee

댓글