Git 속도 향상: 필수 성능 최적화 기법
클론 비용 절감, Git LFS 현명하게 사용, 오래된 참조 정리, 생성된 파일 무시, 스파스 체크아웃 적용으로 Git 속도를 높이세요.
Git 속도 향상: 필수 성능 최적화 기법
느린 Git은 일반적으로 구체적인 원인이 있습니다: 너무 많은 히스토리, 너무 많은 추적되지 않은 파일, 대용량 바이너리 객체, 비싼 파일 시스템 스캔, 또는 네트워크 지연. Git 자체를 탓하기 전에 어떤 작업이 느리고 무엇을 읽거나 다운로드하려고 하는지 확인하세요.
Git 성능 최적화는 증상에 맞는 해결책을 적용할 때 가장 효과적입니다. 느린 CI 클론은 거대한 작업 트리에서 느린 git status와는 다른 해결책이 필요합니다.
느린 Git 성능의 원인 이해하기
일반적인 원인부터 시작하세요:
- 많은 파일과 참조가 있는 긴 히스토리.
- Git에 직접 커밋된 대용량 바이너리 파일.
- 작업 트리에 무시되지 않은 빌드 출력물, 의존성 폴더, 로그.
- 많은 오래된 원격 추적 브랜치와 태그.
- 원격으로의 느린 네트워크 링크.
- 최신 유지 관리 및 스파스 체크아웃 개선 사항이 없는 오래된 Git 버전.
의도를 가지고 느린 명령어를 실행하세요. git clone이 느리면 히스토리 크기와 네트워크 전송을 살펴보세요. git status가 느리면 작업 트리 크기, 무시된 파일, 파일 시스템 동작을 살펴보세요. git fetch가 느리면 원격 참조, 태그, 변경된 객체를 살펴보세요.
클론 및 페치 비용 줄이기
CI, 배포 작업, 읽기 전용 검사의 경우 전체 히스토리가 필요하지 않은 경우가 많습니다.
얕은 클론 사용:
git clone --depth <숫자> <저장소_URL>
예를 들어, 마지막 10개 커밋만 클론하려면:
git clone --depth 10 https://github.com/example/repo.git
현재 커밋만 빌드하는 CI 작업의 경우 --depth 1이면 충분합니다. 개발자 작업의 경우 전체 클론이 일반적으로 덜 놀랍습니다. 깊은 git log, 오래된 태그 체크아웃, 일부 리베이스 같은 명령어는 더 많은 히스토리가 필요하기 때문입니다.
이미 얕은 클론이 있고 더 많은 히스토리가 필요하다면 깊게 만드세요:
git fetch --deepen=50 origin
또는 전체 클론으로 변환:
git fetch --unshallow origin
부분 데이터가 필요한 경우 최신 Git 버전은 --filter=blob:none과 같은 부분 클론 필터도 지원하지만, Git 호스트와 워크플로우가 이를 잘 지원하는 경우에만 사용하세요:
git clone --filter=blob:none https://github.com/example/large-repo.git
대용량 파일을 일반 Git 히스토리 밖에 유지하기
대용량 바이너리는 Git을 느리게 만드는 가장 빠른 방법 중 하나입니다. 이미지, 비디오, 아카이브, 디자인 파일, 모델 파일은 일반적으로 압축이나 diff가 잘 되지 않습니다.
저장소에 실제로 속해야 하는 대용량 자산에는 Git LFS를 사용하세요:
git lfs install
git lfs track "*.psd"
git lfs track "assets/*.mp4"
git add .gitattributes
git commit -m "대용량 자산을 Git LFS로 추적"
Git LFS는 추적 규칙이 적용된 이후의 커밋에 영향을 미칩니다. 누군가 이미 대용량 파일을 일반 Git 히스토리에 커밋했다면, 현재 트리에서 제거하는 것만으로는 충분하지 않습니다. git lfs migrate import나 git filter-repo와 같은 도구를 사용한 조정된 히스토리 재작성이 필요할 수 있습니다.
생성된 빌드 아티팩트의 경우 일반적으로 LFS보다 더 나은 답은 없습니다. 커밋하지 마세요. 대신 .gitignore에 추가하세요:
node_modules/
dist/
coverage/
*.log
로컬 참조 및 객체 정리하기
오래된 원격 추적 브랜치는 혼란을 추가하고 참조를 나열하거나 검사하는 명령어를 느리게 할 수 있습니다. 페치 중에 정리하세요:
git fetch --prune
이미 병합되어 더 이상 필요하지 않은 로컬 브랜치를 삭제하세요:
git branch --merged
git branch -d old-feature-branch
Git이 유지 관리를 실행하도록 하세요:
git maintenance run
오래된 워크플로우에서는 git gc가 여전히 유용합니다:
git gc
필요한 이유를 알지 못한다면 공격적인 정리 명령어는 피하세요. 예를 들어, reflog를 만료시키면 잘못된 리셋에서 복구하기 어려워질 수 있습니다.
git status 비용 낮추기
git status는 작업 트리를 검사해야 합니다. 프로젝트 디렉토리에 수천 개의 생성된 파일이나 의존성 파일이 있으면 상태가 시끄럽고 느려질 수 있습니다.
Git이 고려하지 말아야 할 파일에는 .gitignore를 사용하세요. 파일이 이미 추적 중이라면 .gitignore가 Git이 추적하는 것을 막지 않습니다; 먼저 인덱스에서 제거해야 합니다:
git rm --cached path/to/generated-file
트리의 일부만 필요한 매우 큰 저장소의 경우 스파스 체크아웃이 도움이 될 수 있습니다:
git sparse-checkout init --cone
git sparse-checkout set services/api docs
이렇게 하면 선택한 경로만 작업 트리에 유지됩니다. 모노레포에서 유용하지만, 팀이 필요한 스파스 경로를 문서화하여 개발자가 필요한 파일을 놓치지 않도록 해야 합니다.
페치와 통합 분리하기
git pull은 페치한 다음 구성에 따라 병합 또는 리베이스로 변경 사항을 통합합니다. 저장소가 크거나 브랜치가 분기된 경우 먼저 페치하는 것이 더 명확할 때가 많습니다:
git fetch origin
git log --oneline HEAD..origin/main
git merge origin/main
이 자체로 네트워크 전송을 작게 만들지는 않습니다. 작업 브랜치를 변경하기 전에 제어권을 줍니다.
실용적인 요점
단기 작업에는 얕은 클론, 대용량 자산에는 Git LFS, 생성된 파일에는 .gitignore, 오래된 참조에는 정리, 큰 트리에서 일부만 필요할 때는 스파스 체크아웃을 사용하세요. Git을 최신 상태로 유지하되, 저장소 손상이 의심되지 않는 한 git fsck와 같은 무결성 도구를 성능 수정으로 사용하지 마세요.
Git이 느리다고 느껴지면 정확한 명령어와 시간이 어디에 소요되는지 기록하세요: 네트워크 전송, 객체 처리, 또는 작업 트리 스캔. 그 한 가지 세부 사항이 일반적으로 올바른 최적화를 가리킵니다.