program story

내 자식 저장소에서 참조되지 않은 얼룩을 제거하는 방법

inputbox 2020. 8. 3. 08:22
반응형

내 자식 저장소에서 참조되지 않은 얼룩을 제거하는 방법


마스터 및 릴리스라는 두 가지 분기가있는 GitHub 리포지토리가 있습니다.

릴리스 브랜치에는 매우 큰 리포지토리 크기 (> 250MB)에 기여한 바이너리 배포 파일이 포함되어 있으므로 정리를 결정했습니다.

먼저 원격 릴리스 분기를 삭제했습니다. git push origin :release

그런 다음 로컬 릴리스 분기를 삭제했습니다. 먼저 시도 git branch -d release했지만 git은 "오류 : 분기 '릴리스'는 현재 HEAD의 조상이 아닙니다." 사실이므로 git branch -D release강제로 삭제했습니다.

그러나 로컬 및 GitHub의 저장소 크기는 여전히 컸습니다. 그래서 git gc --prune=today --aggressive운이없는 일반적인 git 명령 목록을 살펴 보았습니다 .

SO 1029969 에서 Charles Bailey의 지시에 따라 가장 큰 얼룩에 대한 SHA1 목록을 얻을 수있었습니다. 그런 다음 SO 460331 의 스크립트를 사용하여 blob을 찾았습니다 .5 개의 가장 큰 blob은 없지만 작은 blob이 발견되었으므로 스크립트가 작동한다는 것을 알고 있습니다.

이 블로그는 릴리스 지점의 이진 파일이라고 생각하며 해당 지점을 삭제 한 후에 어떻게 든 남아 있습니다. 그들을 제거하는 올바른 방법은 무엇입니까?


... 그리고 더 이상 고민하지 않고 추가 구성 변수가 나올 때까지 모든 자식 쓰레기 를 제거하도록 보장하는 유용한 명령 "git-gc-all"을 제시하겠습니다 .

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc

이런 것들을 먼저 실행해야 할 수도 있습니다.

git remote rm origin
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d

Zitrax 덕분에 일부 태그를 제거해야 할 수도 있습니다.

git tag | xargs git tag -d

나는이 모든 것을 스크립트에 넣었다 : git-gc-all-ferocious .


여기설명 된대로 간단히

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

git reflog expire --expire-unreachable=now --all에서 도달 할 수없는 커밋에 대한 모든 참조를 제거합니다 reflog.

git gc --prune=now 커밋 자체를 제거합니다.

주의 : git gc --prune=now커밋은 여전히 ​​reflog에서 참조되므로 사용 만 작동하지 않습니다. 따라서 거부를 지우는 것은 필수입니다.


에서 언급 한 바와 같이 ,이 SO 응답 , git gc실제로 REPO의 크기를 늘릴 수 있습니다!

이 스레드 참조

이제 git에는 ' '를 실행할 때 참조되지 않은 객체를 즉시 삭제 하지 않는 안전 메커니즘이 있습니다 git gc.
기본적으로 참조되지 않은 개체는 2 주 동안 유지됩니다. 이것은 실수로 삭제 된 브랜치 나 커밋을 쉽게 복구 할 수 있도록하거나 아직 참조되지 않은 프로세스에서 방금 생성 된 객체 git gc가 병렬로 실행 되는 ' '프로세스에 의해 삭제 될 수있는 경쟁을 피하기위한 것 입니다.

따라서 포장되었지만 참조되지 않은 객체에 유예 기간을 부여하기 위해 리 패킹 프로세스는 참조되지 않은 객체를 팩에서 느슨한 형태로 밀어서 노화되고 결국 정리 될 수 있도록합니다.
참조되지 않은 객체는 일반적으로 그리 많지 않습니다. 404855 참조되지 않은 객체를 갖는 것은 상당히 많으며 복제를 통해 해당 객체를 처음에 보내는 것은 어리 석고 네트워크 대역폭의 완전한 낭비입니다.

어쨌든 ... 문제를 해결하려면 인수 git gc와 함께 ' ' 를 실행 하여 --prune=now유예 기간을 비활성화하고 참조되지 않은 객체를 즉시 제거해야합니다 (다른 git 활동이 동시에 발생하지 않는 경우에만 안전합니다) 워크 스테이션에서 쉽게 확인할 수 있습니다).

그리고 BTW, ' git gc --aggressive'를 이후 git 버전 (또는 ' git repack -a -f -d --window=250 --depth=250') 과 함께 사용

같은 스레드는 언급 :

 git config pack.deltaCacheSize 1

이는 델타 캐시 크기를 기본값 0 대신 무제한으로 의미하는 1 바이트 (효과적으로 비활성화)로 제한합니다. 이를 통해 git repack4GB RAM이있는 x86-64 시스템 에서 위 명령을 사용하고 4 개의 스레드 (이것은 쿼드 코어)를 사용하여 해당 저장소를 다시 포장 할 수 있습니다. 그러나 상주 메모리 사용량은 거의 3.3GB로 증가합니다.

머신이 SMP이고 충분한 RAM이없는 경우 스레드 수를 하나만 줄일 수 있습니다.

git config pack.threads 1

또한 --window-memory argument' git repack' 사용하여 메모리 사용을 추가로 제한 할 수 있습니다 .
예를 들어, --window-memory=128Mrepo에 대용량 파일이 많이 포함되어 있으면 델타 검색 메모리 사용에 대한 상한을 적절하게 유지해야 델타 일치가 덜 최적화 될 수 있습니다.


필터 브랜치 전면 에서이 스크립트 를 신중하게 고려할 수 있습니다.

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch otherwise leaves behind for a long time
rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune

git gc --prune=now또는 낮은 수준 git prune --expire now입니다.


HEAD가 움직일 때마다 git은이를 추적합니다 reflog. 커밋을 제거한 경우에도 reflog~ 30 일 동안 여전히 참조되므로 "매달린 커밋"이 있습니다 . 실수로 커밋을 삭제할 때의 안전망입니다.

git reflog특정 커밋 제거, 리 패킹 등 명령을 사용하거나 고급 명령 만 사용할 수 있습니다 .

git gc --prune=now

You can use git forget-blob.

The usage is pretty simple git forget-blob file-to-forget. You can get more info here

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

It will disappear from all the commits in your history, reflog, tags and so on

I run into the same problem every now and then, and everytime I have to come back to this post and others, that's why I automated the process.

Credits to contributors such as Sam Watkins


Try to use git-filter-branch - it does's not remove big blobs, but it can remove big files which you specify from the whole repo. For me it reduces repo size from hundreds MB to 12 MB.


Before doing git filter-branch and git gc, you should review tags that are present in your repo. Any real system which has automatic tagging for things like continuous integration and deployments will make unwanted objects still referenced by these tags, hence gc can't remove them and you will still keep wondering why the size of repo is still so big.

The best way to get rid of all un-wanted stuff is to run git-filter & git gc and then push master to a new bare repo. The new bare repo will have the cleaned up tree.


Sometimes, the reason that "gc" doesn't do much good is that there is an unfinished rebase or stash based on an old commit.


To add another tip, don't forget to use git remote prune to delete the obsolete branches of your remotes before using git gc

you can see them with git branch -a

It's often useful when you fetch from github and forked repositories...

참고URL : https://stackoverflow.com/questions/1904860/how-to-remove-unreferenced-blobs-from-my-git-repo

반응형