git 상태 성능을 개선하는 방법


80

NFS에있는 Linux 시스템에 10GB의 저장소가 있습니다. 처음 git status에는 36 분이 git status걸리고 그 다음에 는 8 분이 걸립니다. Git은 파일 캐싱을 위해 OS에 의존하는 것 같습니다. 첫 번째 git명령은 좋아 commit, status그 / 팩을 포함 전체의 repo 거대한 환매 특약을 위해 매우 오랜 시간이 걸립니다 재 포장. git status그렇게 큰 저장소를 사용했는지 확실하지 않지만이 문제를 겪은 사람이 있습니까?

나는 시도 git gc, git clean, git repack하지만 걸리는 시간은 여전히 / 거의 같은.

하위 모듈이나 저장소를 더 작은 것으로 나누는 것과 같은 다른 개념이 도움이 될까요? 그렇다면 더 큰 저장소를 분할하는 것이 가장 좋습니다. 큰 저장소에서 git 명령에 걸리는 시간을 개선하는 다른 방법이 있습니까?


2
NFS는 여기에서 거의 병목 현상입니다. lstat는 상당히 동기적인 작업입니다.
user611775

답변:


45

더 정확하게 말하면 git은 lstat(2)시스템 호출 의 효율성에 의존 하므로 클라이언트의 "attribute cache timeout"을 조정 하면 트릭이 될 수 있습니다.

에 대한 매뉴얼 ( git-update-index기본적으로 수동 모드) 플래그사용하여 정상적인 동작을 억제하고 변경 한 경로를 수동으로 업데이트 git-status함으로써이를 완화하기 위해 수행 할 수있는 작업을 설명합니다 . 파일을 저장할 때마다이 플래그를 설정 해제하도록 편집기를 프로그래밍 할 수도 있습니다.--assume-unchanged

당신이 제안한 대안은 체크 아웃의 크기를 줄이는 것입니다 (팩 파일의 크기는 여기서 실제로 작동하지 않습니다). 옵션은 스파 스 체크 아웃, 하위 모듈 또는 Google의 저장소 도구입니다.

( NFS와 함께 Git을 사용하는 것에 대한 메일 링리스트 스레드가 있지만 많은 질문에 대답하지 않습니다.)


31
놓친 점 : Linus의 패치는 실제로 병합 core.preloadindex되었으며 true 로 설정 하여 활성화 할 수 있습니다 git-config. 자세한 설명 은 문서를 참조하십시오 . (제 직장에서 NFS를 사용하고 있는데 정확히이 문제가 발생했습니다.하지만 preloadindex 설정을 알아 차리지 못했습니다. 올바른 길을 알려 주셔서 감사합니다!)
Cascabel

1
여기에서 허용되는 답변에 'git config core.preloadindex true'를 추가해야합니다. 아마도 user1077329에서 -uno 플래그
ostler.c

2
core.preloadindex플래그는 힘내 2.1.0의 기본적으로 true로 설정됩니다 git.kernel.org/pub/scm/git/git.git/tree/Documentation/RelNotes/...
페트르 Gazarov

38

NFS를 통해 공유되는 대규모 프로젝트에서도이 문제가 발생합니다.

git commit과 git status 모두에 제공 할 수있는 플래그 -uno 를 발견하는 데 시간이 좀 걸렸습니다 .

이 플래그가하는 일은 추적되지 않는 파일 찾기를 비활성화하는 것입니다. 이렇게하면 nfs 작업 수가 크게 줄어 듭니다. 그 이유는 git이 추적되지 않은 파일을 발견하려면 모든 하위 디렉터리를 찾아야하므로 하위 디렉터리가 많으면 해를 입힐 수 있습니다. 추적되지 않는 파일을 찾지 못하도록 git을 비활성화하면 이러한 모든 NFS 작업이 제거됩니다.

이것을 core.preloadindex 플래그와 결합하면 NFS에서도 공감할 수있는 성능을 얻을 수 있습니다.


git-status (1) 에서 언급했듯이 status.showUntrackedFilesconfig 를 설정하여 기본값으로 설정할 수 있습니다 .
johankj

33

git gc 사용해보십시오 . 또한 git clean 도움이 수 있습니다.

업데이트 -반대표가 어디서 왔는지 확실하지 않지만 git 매뉴얼에는 구체적으로 다음과 같이 명시되어 있습니다.

파일 개정을 압축 (디스크 공간을 줄이고 성능을 높이기 위해 )하고 이전에 git add를 호출하여 생성되었을 수있는 도달 할 수없는 객체를 제거하는 등 현재 저장소 내에서 여러 가지 관리 작업을 실행합니다 .

사용자는 각 저장소 내에서이 작업을 정기적으로 실행하여 좋은 디스크 공간 활용도와 우수한 운영 성능을 유지하는 것이 좋습니다.

git 상태가 느릴 때 git gc를 실행 한 후 항상 차이가 있습니다!

업데이트 II- 내가 이것을 어떻게 놓쳤는 지 확실하지 않지만 OP는 이미 시도 git gc하고 git clean. 나는 그것이 원래 거기에 없었 음을 맹세하지만 편집에 어떤 변화도 보이지 않습니다. 그 죄송합니다!


5
나도 반대표를 이해하지 못합니다. 이것은 정말 도움이됩니다. 내 저장소 중 하나에서 실행 git gc시간을 git log15 초에서 0으로 줄였습니다.
GreenRaccoon23

트윗 담아 가기 내가 그것을 어떻게 놓쳤는 지 확실하지 않지만 그에 대한 내 대답에도 투표했습니다. : - /
자바리

1
git cg는 좋습니다. git clean은 원하지 않는 파일을 삭제할 수 있습니까?
Luca Reghellin

18

git 저장소가 하위 모듈을 많이 사용하는 경우 .git 디렉토리의 구성 파일을 편집하고 ignore = dirty특히 크거나 무거운 하위 모듈을 설정 하여 git 상태의 성능을 크게 높일 수 있습니다 . 예를 들면 :

[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty

잊었을 수있는 하위 모듈에 단계적이지 않은 변경 사항이 있다는 알림의 편의를 잃게되지만 하위 모듈이 주 저장소와 동기화되지 않은 경우를 아는 주된 편의는 여전히 유지됩니다. 또한 작업 디렉토리를 하위 모듈 자체로 변경하고 평소와 같이 git status를 사용하여 더 많은 정보를 볼 수 있습니다. 참조 이 질문에 무엇을 "더러운"수단에 대한 자세한 내용을.


7

Git 상태의 성능은 Git 2.13 (2017 년 2 분기)에서 개선 될 것입니다.

Jeff Hostetler ( )의 commit 950a234 (2017 년 4 월 14 일)를 참조하십시오 . (Merged by Junio ​​C Hamano -- in commit 8b6bba6 , 24 Apr 2017)jeffhostetler
gitster

> string-list: 재 할당시 ALLOC_GROW매크로 사용string_list

배열을 ALLOC_GROW()재 할당 할 때 string_list단순히 32만큼 늘리기보다는 매크로를 사용하십시오 .
이것은 성능 최적화입니다.

매우 큰 리포지토리의 상태와 많은 변경 사항이있는 동안 총 실행 시간의 상당 부분이 wt_status.changes어레이를 재 할당하는 데 소비 됩니다 .

이 변경으로 wt_status_collect_changes_worktree()매우 큰 저장소에서 시간이 125 초에서 45 초로 단축됩니다.


또한 Git 2.17 (2018 년 2 분기)은 인덱스가 많은 작업에서 시간이 소비되는 위치를 측정하기위한 새로운 추적을 도입합니다.

Nguyễn Thái Ngọc Duy ( )의 commit ca54d9b (2018 년 1 월 27 일)를 참조하십시오 . (Merged by Junio ​​C Hamano -- in commit 090dbea , 15 Feb 2018)pclouds
gitster

trace: 인덱스가 많은 작업에서 시간이 소요되는 위치 측정

알려진 모든 무거운 코드 블록이 측정됩니다 (객체 데이터베이스 액세스 제외). 이는 최적화가 효과적인지 여부를 식별하는 데 도움이됩니다.
최적화되지 않은 git-status는 다음과 같습니다.

0.001791141 s: read cache ...
0.004011363 s: preload index
0.000516161 s: refresh index
0.003139257 s: git command: ... 'status' '--porcelain=2'
0.006788129 s: diff-files
0.002090267 s: diff-index
0.001885735 s: initialize name hash
0.032013138 s: read directory
0.051781209 s: git command: './git' 'status'

동일한 Git 2.17 (2018 년 2 분기)이 다음 git status과 같이 개선 되었습니다.

revision.c: 개체 데이터베이스 쿼리 줄이기

에서는 mark_parents_uninteresting()커밋을 파싱 된 것으로 처리해야하는지 확인하기 위해 객체 파일이 있는지 확인합니다. 결과는 커밋에 "파싱 된"비트를 설정하는 것입니다.

has_object_file()결과가 구문 분석 된 비트를 변경 하는지 확인하도록 조건을 수정하십시오 .

로컬 브랜치가 업스트림 참조와 다른 경우 " git status"는 앞 / 뒤 카운트를 계산합니다.
이것은 사용 paint_down_to_common()하고 mark_parents_uninteresting().

origin/master~ 60,000 개 커밋에 의해 원격 브랜치 ""뒤에 "master"의 로컬 인스턴스가있는 Linux 리포지토리의 복사본에서 " "의 성능이 git status1.42 초에서 1.32 초로, 상대적 차이는 -7.0 %로 떨어졌습니다.


Git 2.24 (2019 년 3 분기)는 git status성능 향상을위한 또 다른 설정을 제안 합니다.

참조 aaf633c 커밋 , c6cc4c5 커밋 , ad0fb65 커밋 , 31b1de6 커밋 , b068d9a 커밋 , 7211b9e 커밋 에 의해 (2019년 8월 13일) 데릭 Stolee을 ( derrickstolee) .
(Merged by Junio ​​C gitsterHamano -- in commit f4f8dfe , 09 Sep 2019)

repo-settings : feature.manyFiles 설정 생성

feature.manyFiles설정은 작업 디렉토리에 많은 파일이있는 저장소에 적합합니다. 및
을 설정 하면 ' ' 와 같은 명령 이 향상됩니다.index.version=4core.untrackedCache=truegit status

그러나:

Git 2.24 (2019 년 4 분기)에서 index.version구성 을 읽는 코드 경로 가 수정 된 최근 업데이트로 인해 손상되었습니다.

Derrick Stolee ( )의 commit c11e996 (2019 년 10 월 23 일)을 참조하십시오 . (Merged by Junio ​​C Hamano -- in commit 4d6fb2b , 24 Oct 2019)derrickstolee
gitster

repo-settings: index.version에 대한 int 읽기

서명자 : Derrick Stolee

7211b9e ( " : 일부 구성 설정 통합", 2019-08-13, Git v2.24.0-rc1 repo_settings에서 "index.version"구성 설정 이동 포함) 여러 구성 옵션이 ds / feature-macros 의 구조체 로 결합되었습니다. - 일괄 # 0에 나열된 병합 ).repo-settings

불행하게도, 그 파일은 상용구의 많은처럼 보였다과 무슨 일이 명확하게 구성 설정과 구문 분석 복사 - 붙여 넣기 과부하의 요소입니다 repo_config_ge_bool()대신 repo_config_get_int(). 즉, "index.version = 4"설정이 올바르게 등록되지 않고 기본 버전 인 3으로 되돌아갑니다.

v2.24.0-rc0을 Git 코드베이스 용 VFS에 통합하는 동안이 문제를 포착했습니다. 여기서 색인이 버전 4에 있다는 사실을 정말 신경 씁니다.

버전 검사 t1600-index.sh가 "기본"시나리오를 충분히 테스트하지 않았기 때문에 이것은 코드베이스에 의해 포착 되지 않았습니다. 여기서는 features.manyFiles또는에 의해 재정의되지 않도록 이러한 일반 설정을 포함하도록 테스트를 수정합니다 GIT_INDEX_VERSION.
"기본"버전은 3이지만 do_write_index()필요하지 않은 경우 버전 2로 강등됩니다 .


참조 stackoverflow.com/a/43667992/6309 새로운 index.threads설정 설정
VonC

GIT_TRACE 사실 자식은 당신이 추적을 실행하는 방법 이것은 로그 병목 찾을 =
dhavale

@dhavale 실제로 Git .22 이후 trace2도 있습니다 : stackoverflow.com/a/56094711/6309
VonC

4

git config --global core.preloadIndex true

나를 위해 일했다. 여기 에서 공식 문서를 확인 하십시오 .


어떤 버전의 Git을 사용하고 있습니까?
VonC

2.7.4. Windows 용 Linux 하위 시스템을 사용하고 업데이트 된 경우에도 apt-get꽤 오래된 패키지에 대한 참조가있는 것 같습니다.
klimat

1
알겠습니다. 최신 버전에서는 필요하지 않다고 생각합니다.
VonC

이것은 심지어 git 버전 2.17.1로 나를 도왔습니다
Markus Zeller

1

20-30 개의 서브 모듈 범위에있는 코드베이스에서
git status --ignore-submodules
저를 위해 엄청난 속도를 냈습니다. 이것은 하위 모듈의 상태에 대해보고하지 않습니다. .


1

아직 언급되지 않은 것은 Windows 컴퓨터에서 파일 시스템 캐시를 활성화하는 것입니다 (리눅스 파일 시스템은 완전히 다르며 git이 최적화되었으므로 아마도 Windows에서만 도움이 될 것입니다).

git config core.fscache true


마지막 수단으로 git이 여전히 느리면 수정 시간 검사를 끌 수 있으며 git은 어떤 파일이 변경되었는지 확인해야합니다.

git config core.ignoreStat true

하지만 변경된 파일은 나중에 개발자가 git add. Git은 자체적으로 변경 사항을 찾지 못합니다.

출처


이것은 Windows 용 Git의 최신 버전을 가지고 있었지만 Windows 10에서 나를 도왔습니다. 감사합니다. 내 REPO는 ~ 100 .git 폴더에 기가 (자식 LFS)이었다
알렉스 Sorokoletov

0

나머지 index.lock 파일

git status 남은 음식이 있으면 병리 적으로 느려질 수 있습니다. index.lock 파일 .

이것은 특히를 가지고있을 때 발생 git submodules합니다. 왜냐하면 그런 남은 파일을 종종 알아 차리지 못하기 때문입니다.

요약 :을 실행 find .git/ -name index.lock하고 현재 실행중인 프로그램에서 실제로 사용되지 않는지 확인한 후 남은 파일삭제합니다 .


세부

내 쉘 자식 상태가 Ubuntu 16.04의 git 2.19와 함께 내 저장소에서 매우 느리다는 것을 발견했습니다.

파고 /usr/bin/time git status내에서 발견assets git 서브 모듈에서 1.7 초가 걸렸습니다.

strace그 자식 과 함께 거기에있는 모든 큰 파일을 mmap. 보통 그렇게하지 않고 보통 stat충분합니다.

나는 문제를 검색하고 색인 사용 및 Racy Git 문제를 발견했습니다 .

여기에 표시된 시도 git update-index somefile(내 경우 gitignore하위 모듈 체크 아웃) 했지만 실패했습니다.

fatal: Unable to create '/home/niklas/src/myproject/.git/modules/assets/index.lock': File exists.

Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.

이것은 고전적인 오류입니다. 일반적으로 어떤 git 작업에서나 알 수 있지만 자주 커밋하지 않는 하위 모듈의 경우 색인에 무언가를 추가 할 때만 나타나기 때문에 몇 달 동안 눈치 채지 못할 수 있습니다. 읽기 전용에서는 경고가 발생하지 않습니다 git status.

index.lock파일을 제거하고 git status즉시 빨라졌습니다.mmaps 사라졌으며 이제 1000 배 이상 빨라졌습니다.

따라서 git 상태가 부 자연스럽게 느린 find .git/ -name index.lock경우 남은 음식을 확인 하고 삭제하십시오.


0

꽤 오래된 질문입니다. 그러나 저장소 크기를 고려할 때 바이너리 파일에 대해 아무도 언급하지 않았다는 사실에 놀랐습니다.

git repo가 ​​~ 10GB라고 언급했습니다. NFS 문제 및 기타 git 문제 ( git gc다른 답변의 개요로 git 구성 변경으로 해결 가능 )를 제외하고 git 명령 (git status, git diff, git add)은 저장소에 많은 바이너리 파일이 있기 때문에 느릴 수 있습니다. . git은 바이너리 파일을 잘 처리하지 못합니다. 다음 명령을 사용하여 불필요한 바이너리 파일을 제거 할 수 있습니다 (NetCDF 파일에 대한 예제가 제공되며 이전에 git 저장소 백업이 있음).

git filter-branch --force --index-filter \  
'git rm --cached --ignore-unmatch *.nc' \   
--prune-empty --tag-name-filter cat -- --all

git이 파일을 다시 커밋하지 못하도록 '* .nc'를 gitignore 파일에 넣는 것을 잊지 마십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.