git gc --aggressive vs git repack
git
저장소 크기를 줄이는 방법을 찾고 있습니다. 검색은 나를 git gc --aggressive
대부분의 시간으로 인도합니다 . 나는 또한 이것이 선호되는 접근 방식이 아니라는 것을 읽었습니다.
왜? 내가 달리고 있다면 무엇을 알아야 gc --aggressive
합니까?
git repack -a -d --depth=250 --window=250
이상 권장됩니다 gc --aggressive
. 왜? repack
저장소의 크기를 줄이는 방법은 무엇입니까? 또한 플래그 --depth
및 --window
.
gc
과 중에서 무엇을 선택해야 repack
합니까? 언제 사용해야 gc
하고 repack
?
오늘날에는 차이가 없습니다. git gc --aggressive
Linus가 2007 년에 제안한 제안에 따라 작동합니다. 아래를 참조하십시오. 버전 2.11 (2016 년 4 분기)부터 git은 기본적으로 깊이가 50입니다. 크기가 250 인 창은 각 객체의 더 큰 섹션을 스캔하기 때문에 좋지만 250의 깊이는 모든 체인이 매우 오래된 것을 참조하기 때문에 좋지 않습니다. 이는 디스크 사용량을 약간 낮추기 위해 향후 모든 git 작업을 느리게 만듭니다 .
역사적 배경
Linus는 git gc --aggressive
" 정말 나쁜 팩"또는 "정말 끔찍한 델타" 가있을 때만 사용하도록 제안했습니다 (전체 메일 링리스트 게시물은 아래 참조). 그러나 "거의 항상, 다른 경우에는 실제로는 정말 나쁜 것입니다. 해야 할 일." 결과는 시작했을 때보 다 더 나쁜 상태로 저장소를 남길 수도 있습니다!
그가 "길고 복잡한 역사"를 가져온 후이를 제대로 수행하기 위해 제안한 명령은 다음과 같습니다.
git repack -a -d -f --depth=250 --window=250
그러나 이것은 당신이 이미 당신의 저장소 히스토리에서 원치 않는 건크 를 제거 했고 당신이 git filter-branch
문서 에있는 저장소 축소 체크리스트를 따랐다 고 가정합니다 .
git-filter-branch를 사용하여 파일의 하위 집합을 제거 할 수 있으며 일반적으로
--index-filter
및--subdirectory-filter
. 사람들은 결과 리포지토리가 원본보다 작을 것으로 예상하지만 실제로 작게 만들려면 몇 가지 단계가 더 필요합니다. Git은 사용자가 지시 할 때까지 개체를 잃지 않으려 고 노력하기 때문입니다. 먼저 다음 사항을 확인하십시오.
Blob이 수명 동안 이동 된 경우 파일 이름의 모든 변형을 제거했습니다.
git log --name-only --follow --all -- filename
이름을 찾는 데 도움이 될 수 있습니다.정말 모든 참조를 필터링했습니다 .을
--tag-name-filter cat -- --all
호출 할 때 사용git filter-branch
합니다.그런 다음 더 작은 저장소를 얻는 두 가지 방법이 있습니다. 더 안전한 방법은 원본을 그대로 유지하는 복제하는 것입니다.
- 그것을 복제
git clone file:///path/to/repo
. 복제본에는 제거 된 개체가 없습니다. git-clone을 참조하십시오. (일반 경로로 복제하면 모든 것이 하드 링크됩니다!)어떤 이유로 든 복제하고 싶지 않다면 대신 다음 사항을 확인하십시오 (이 순서대로). 이것은 매우 파괴적인 접근 방식이므로 백업을 만들거나 복제로 돌아가십시오. 경고를 받았습니다.
git-filter-branch에 의해 백업 된 원본 참조를 제거합니다.
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
를 사용하여 모든 리플 로그를 만료합니다
git reflog expire --expire=now --all
.가비지는 참조되지 않은 모든 객체를 수집합니다
git gc --prune=now
(또는git gc
에 대한 인수를 지원할만큼 새롭지 않은--prune
경우git repack -ad; git prune
대신 사용).
Date: Wed, 5 Dec 2007 22:09:12 -0800 (PST) From: Linus Torvalds <torvalds at linux-foundation dot org> To: Daniel Berlin <dberlin at dberlin dot org> cc: David Miller <davem at davemloft dot net>, ismail at pardus dot org dot tr, gcc at gcc dot gnu dot org, git at vger dot kernel dot org Subject: Re: Git and GCC In-Reply-To: <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com> Message-ID: <alpine.LFD.0.9999.0712052132450.13796@woody.linux-foundation.org> References: <4aca3dc20712051947t5fbbb383ua1727c652eb25d7e@mail.gmail.com> <20071205.202047.58135920.davem@davemloft.net> <4aca3dc20712052032n521c344cla07a5df1f2c26cb8@mail.gmail.com> <20071205.204848.227521641.davem@davemloft.net> <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
2007 년 12 월 6 일 목요일에 Daniel Berlin은 다음과 같이 썼습니다.
실제로
git-gc --aggressive
SVN 리포지토리에서 변환했는지 여부에 관계없이 때때로 파일을 압축하는 것이 바보 같은 일을합니다.물론.
git --aggressive
대부분 바보입니다. 이것은 " 정말 나쁜 팩 이 있다는 것을 알고 있으며, 제가 한 모든 나쁜 포장 결정을 버리고 싶습니다. "의 경우에만 유용 합니다.이를 설명하기 위해 git delta-chain이 어떻게 작동하는지, 그리고 대부분의 다른 시스템과 어떻게 다른지 설명 할 가치가 있습니다 (아마도 알고 있겠지만 기본 사항을 살펴 보겠습니다).
다른 SCM에서는 일반적으로 델타 체인이 고정되어 있습니다. "앞으로"또는 "뒤로"가 될 수 있으며 리포지토리 작업에 따라 약간 씩 발전 할 수 있지만 일반적으로 단일 SCM 엔터티로 표현되는 단일 파일에 대한 일련의 변경 사항입니다. CVS에서는 분명히
*,v
파일이고 다른 많은 시스템이 비슷한 일을합니다.Git은 또한 델타 체인을 수행하지만 훨씬 더 "느슨하게"수행합니다. 고정 된 개체가 없습니다. 델타는 git이 좋은 델타 후보로 간주하는 임의의 다른 버전에 대해 생성되며 (다양한 상당히 성공적인 휴리스틱을 사용하여) 절대적으로 엄격한 그룹화 규칙이 없습니다.
이것은 일반적으로 매우 좋은 것입니다. 다양한 개념적 이유 ( 즉 , git 내부적으로는 전체 개정 체인에 대해 전혀 신경을 쓸 필요조차 없습니다. 델타 측면에서 전혀 생각하지 않습니다).하지만 융통성없는 델타 규칙을 제거하는 것은 의미가 있기 때문에 좋습니다. 예를 들어 git은 두 파일을 병합하는 데 전혀 문제가 없습니다
*,v
. 숨겨진 의미가있는 임의의 "개정 파일" 이 없습니다 .또한 델타의 선택이 훨씬 더 개방적인 질문임을 의미합니다. 델타 체인을 하나의 파일로 제한하면 델타에 대해 할 일에 대한 선택권이 많지 않지만 git에서는 완전히 다른 문제가 될 수 있습니다.
그리고 이것은 정말 나쁜 이름
--aggressive
이 들어오는 곳입니다. git은 일반적으로 델타 정보를 재사용하려고 시도하지만 (좋은 생각이고 이전에 찾은 모든 좋은 델타를 다시 찾는 CPU 시간을 낭비하지 않기 때문입니다) 때때로 당신은 "빈 슬레이트로 다시 시작하고 모든 이전 델타 정보를 무시하고 새로운 델타 세트를 생성 해 보겠습니다."라고 말하고 싶습니다.따라서
--aggressive
실제로 공격적이지 않고 이전에 이미 결정한 결정을 다시 수행하는 데 CPU 시간을 낭비하는 것입니다!때때로 그것은 좋은 일입니다. 특히 일부 가져 오기 도구는 정말 끔찍하게 나쁜 델타를 생성 할 수 있습니다.
git fast-import
예를 들어 를 사용하는 모든 항목 에는 델타 레이아웃이 많지 않을 수 있으므로 "깨끗한 상태에서 시작하고 싶습니다."라고 말할 가치가있을 수 있습니다.그러나 거의 항상, 다른 경우에는 실제로는 정말 나쁜 일입니다. CPU 시간을 낭비하게 될 것입니다. 특히 이전에 델타를 잘 수행했다면 최종 결과는 이미 찾은 모든 좋은 델타 를 재사용하지 않을 것 입니다. 더 나쁜 결과도!
git gc --aggressive
문서를 제거하기 위해 Junio에 패치를 보내겠습니다 . 유용 할 수 있지만 일반적으로 수행하는 작업을 매우 심층적으로 이해하고 해당 문서가 도움이되지 않는 경우에만 일반적으로 유용합니다.일반적으로 증분을 수행하는
git gc
것이 올바른 접근 방식이며git gc --aggressive
. 이전 델타를 재사용 할 것이고, 이전 델타를 찾을 수 없을 때 (처음에 증분 GC를 수행하는 이유!) 새로운 델타를 생성 할 것입니다.다른 한편으로, "길고 관련된 역사의 초기 수입"은 정말 좋은 델타를 찾는 데 많은 시간을 할애 할 가치가있는 지점이라는 것은 확실히 사실입니다 . 그러면 이후 모든 사용자 (
git gc --aggressive
실행 취소에 사용하지 않는 한 )는 해당 일회성 이벤트의 이점을 얻게됩니다. 따라서 특히 오랜 역사를 가진 큰 프로젝트의 경우, 아마도 추가 작업을 수행하여 델타 검색 코드를 야생으로 전환하도록 지시하는 것이 좋습니다.따라서
git gc --aggressive
-그러나 올바르게 수행됨 -에 해당하는 것은 다음과 같이 (하룻밤)하는 것입니다.git repack -a -d --depth=250 --window=250
그 깊이는 델타 체인이 얼마나 깊을 수 있는지에 관한 것이고 (오래된 히스토리를 위해 그것들을 더 길게 만드십시오-공간 오버 헤드의 가치가 있습니다) 창은 우리가 각 델타 후보가 스캔하기를 원하는 객체 윈도우의 크기에 관한 것입니다.
그리고 여기에서
-f
플래그 를 추가 할 수 있습니다 ( "모든 이전 델타 삭제"). 이제 실제로 이것이 좋은 후보를 실제로 찾는 지 확인하려고하기 때문입니다.그리고 그것은 영원히 그리고 하루가 걸릴 것입니다 ( 즉 , "하룻밤"일). 그러나 최종 결과는 해당 저장소의 모든 다운 스트림이 직접 노력할 필요없이 훨씬 더 나은 팩을 얻을 수 있다는 것입니다.
Linus
언제 gc 및 repack을 사용해야합니까?
" Git 가비지 수집이 완전히 작동하지 않는 것 같습니다 "에서 언급했듯이 a git gc --aggressive
만으로는 충분하지 않거나 심지어 충분하지 않습니다.
그리고 아래 에서 설명했듯이 종종 필요하지 않습니다.
가장 효과적인 조합이 추가 될 수 git repack
도 있지만 git prune
:
git gc
git repack -Ad # kills in-pack garbage
git prune # kills loose garbage
참고 : Git 2.11 (2016 년 4 분기)은 기본 gc aggressive
깊이를 50 으로 설정합니다.
Jeff King ( )의 commit 07e7dbf (2016 년 8 월 11 일)를 참조하십시오 . (의해 병합 - Junio C 하마노 - 에 0952ca8 커밋 2,016 21 구월)peff
gitster
gc
: 기본 공격 깊이는 50"
git gc --aggressive
"는 델타 체인 길이를 250으로 제한하는 데 사용되었습니다. 이는 추가 공간을 절약하기에는 너무 깊고 런타임 성능에 해를 끼칩니다.
한도가 50으로 줄었습니다.요약은 다음과 같습니다. 현재 기본값 인 250은 많은 공간을 절약하지 않으며 CPU 비용이 듭니다. 좋은 절충안이 아닙니다.
"
--aggressive
"플래그git-gc
는 다음 세 가지 작업을 수행합니다.
- "
-f
"을 사용 하여 기존 델타를 버리고 처음부터 다시 계산합니다.- 델타를 더 자세히 보려면 "--window = 250"을 사용하십시오.
- 더 긴 델타 체인을 만들려면 "--depth = 250"을 사용하십시오.
Items (1) and (2) are good matches for an "aggressive" repack.
They ask the repack to do more computation work in the hopes of getting a better pack. You pay the costs during the repack, and other operations see only the benefit.Item (3) is not so clear.
Allowing longer chains means fewer restrictions on the deltas, which means potentially finding better ones and saving some space.
But it also means that operations which access the deltas have to follow longer chains, which affects their performance.
So it's a tradeoff, and it's not clear that the tradeoff is even a good one.
(See commit for study)
You can see that that the CPU savings for regular operations improves as we decrease the depth.
But we can also see that the space savings are not that great as the depth goes higher. Saving 5-10% between 10 and 50 is probably worth the CPU tradeoff. Saving 1% to go from 50 to 100, or another 0.5% to go from 100 to 250 is probably not.
Speaking of CPU saving, "git repack
" learned to accept the --threads=<n>
option and pass it to pack-objects.
See commit 40bcf31 (26 Apr 2017) by Junio C Hamano (gitster
).
(Merged by Junio C Hamano -- gitster
-- in commit 31fb6f4, 29 May 2017)
repack: accept
--threads=<n>
and pass it down topack-objects
We already do so for --window=<n>
and --depth=<n>
; this will help when the user wants to force --threads=1
for reproducible testing without getting affected by racing multiple threads.
The problem with git gc --aggressive
is that the option name and documentation is misleading.
As Linus himself explains in this mail, what git gc --aggressive
basicly does is this:
While git generally tries to re-use delta information (because it's a good idea, and it doesn't waste CPU time re-finding all the good deltas we found earlier), sometimes you want to say "let's start all over, with a blank slate, and ignore all the previous delta information, and try to generate a new set of deltas".
Usually there is no need to recalculate deltas in git, since git determines these deltas very flexible. It only makes sense if you know that you have really, really bad deltas. As Linus explains, mainly tools which make use of git fast-import
fall into this category.
Most of the time git does a pretty good job at determining useful deltas and using git gc --aggressive
will leave you with deltas which are potentially even worse while wasting a lot of CPU time.
Linus ends his mail with the conclusion that git repack
with a large --depth
and --window
is the better choice in most of time; especially after you imported a large project and want to make sure that git finds good deltas.
So the equivalent of
git gc --aggressive
- but done properly - is to do (overnight) something like
git repack -a -d --depth=250 --window=250
where that depth thing is just about how deep the delta chains can be (make them longer for old history - it's worth the space overhead), and the window thing is about how big an object window we want each delta candidate to scan.
And here, you might well want to add the
-f
flag (which is the "drop all old deltas", since you now are actually trying to make sure that this one actually finds good candidates.
Caution. Do not run git gc --agressive
with repository which is not synchronized with remote if you have no backups.
This operation recreates deltas from scratch and could lead to data loss if gracefully interrupted.
For my 8GB computer aggressive gc ran out of memory on 1Gb repository with 10k small commits. When OOM killer terminated git process - it left me with almost empty repository, only working tree and few deltas survived.
Of course, it was not the only copy of repository so I just recreated it and pulled from remote (fetch did not work on broken repo and deadlocked on 'resolving deltas' step few times I tried to do so), but if your repo is single-developer local repo without remotes at all - back it up first.
Note: beware of using git gc --aggressive
, as Git 2.22 (Q2 2019) clarifies.
See commit 0044f77, commit daecbf2, commit 7384504, commit 22d4e3b, commit 080a448, commit 54d56f5, commit d257e0f, commit b6a8d09 (07 Apr 2019), and commit fc559fb, commit cf9cd77, commit b11e856 (22 Mar 2019) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit ac70c53, 25 Apr 2019)
gc
docs: downplay the usefulness of--aggressive
The existing "
gc --aggressive
" docs come just short of recommending to users that they run it regularly.
I've personally talked to many users who've taken these docs as an advice to use this option, and have, usually it's (mostly) a waste of time.So let's clarify what it really does, and let the user draw their own conclusions.
Let's also clarify the "The effects [...] are persistent" to paraphrase a brief version of Jeff King's explanation.
That means the git-gc documentation now includes:
AGGRESSIVE
When the
--aggressive
option is supplied,git-repack
will be invoked with the-f
flag, which in turn will pass--no-reuse-delta
to git-pack-objects.
This will throw away any existing deltas and re-compute them, at the expense of spending much more time on the repacking.The effects of this are mostly persistent, e.g. when packs and loose objects are coalesced into one another pack the existing deltas in that pack might get re-used, but there are also various cases where we might pick a sub-optimal delta from a newer pack instead.
Furthermore, supplying
--aggressive
will tweak the--depth
and--window
options passed togit-repack
.
See thegc.aggressiveDepth
andgc.aggressiveWindow
settings below.
By using a larger window size we're more likely to find more optimal deltas.It's probably not worth it to use this option on a given repository without running tailored performance benchmarks on it.
It takes a lot more time, and the resulting space/delta optimization may or may not be worth it. Not using this at all is the right trade-off for most users and their repositories.
And (commit 080a448):
gc
docs: note how--aggressive
impacts--window
&--depth
Since 07e7dbf (
gc
: default aggressive depth to 50, 2016-08-11, Git v2.10.1) we somewhat confusingly use the same depth under--aggressive
as we do by default.As noted in that commit that makes sense, it was wrong to make more depth the default for "aggressive", and thus save disk space at the expense of runtime performance, which is usually the opposite of someone who'd like "aggressive gc" wants.
참고URL : https://stackoverflow.com/questions/28720151/git-gc-aggressive-vs-git-repack
'program tip' 카테고리의 다른 글
Rails에서 JSON 형식의 404 오류를 반환해야합니다. (0) | 2020.10.19 |
---|---|
프로그래밍 방식으로 android : animateLayoutChanges 설정 (0) | 2020.10.19 |
현재 Rails 환경을 기반으로 종이 클립의 저장 메커니즘을 어떻게 설정할 수 있습니까? (0) | 2020.10.19 |
두 개 이상의 공백과 일치하지만 새 줄은 일치하지 않는 정규식 (0) | 2020.10.19 |
연속 메모리가있는 C ++ 벡터에 해당하는 C #? (0) | 2020.10.19 |