git 저장소에서 사용하지 않는 객체를 제거하는 방법은 무엇입니까?


90

실수로 가장 최근 커밋이 포함 된 거대한 바이너리 파일을 Git 저장소에 추가, 커밋 및 푸시했습니다.

Git에서 해당 커밋에 대해 생성 된 / 만든 객체를 제거하여 .git디렉터리가 다시 정상적인 크기로 축소되도록하려면 어떻게해야합니까?

편집 : 답변 해 주셔서 감사합니다. 몇 가지 해결책을 시도했습니다. 작동하지 않았습니다. 예를 들어 GitHub의 파일은 기록에서 파일을 제거했지만 .git디렉터리 크기는 줄어들지 않았습니다.

$ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD
Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66)
rm 'test_data/images/001.jpg'
[...snip...]
rm 'test_data/images/281.jpg'
Ref 'refs/heads/master' was rewritten

$ git log -p # looks nice

$ rm -rf .git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
Counting objects: 625, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (598/598), done.
Writing objects: 100% (625/625), done.
Total 625 (delta 351), reused 0 (delta 0)

$ du -hs .git
174M    .git
$ # still 175 MB :-(

13
중재자를위한 알림 일뿐입니다.이 질문은 100 % 수퍼 유저가 아닌 SO에 속합니다.
VonC


여기에서 언급했듯이 ( stackoverflow.com/questions/685319/… ), gc 후에 재 포장을 시도 했습니까? 예를 들어 git-repack -a뒤에 git-prune-packed. blog.felipebalbi.com/2007/12/19/…
VonC

2
@Jonas : 모든 작업을 수행 한 후 저장소를 복제하면 어떨까요? 그러면 원하는 축소 크기의 클론 얻을 수 있습니까?
VonC

1
@Jonas : 당신이 한 모든 것을 후 ( filter-branch, gc, repack, ...), 아니, 당신이 어떤 나쁜 전혀 커밋 볼 수 있습니다. 예상대로 청소가 이루어지지 않았다는 신호입니다.
VonC

답변:


128

나는 이것을 다른 곳에서 대답했고, 자랑스럽기 때문에 여기에 복사 할 것입니다!

... 더 이상 고민하지 않고 추가 설정 변수가 나올 때까지 모든 git 쓰레기를 제거 할 수 있도록 보장하는이 유용한 스크립트 인 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 "$@"

--aggressive 옵션이 도움이 될 수 있습니다.

참고 : 이렇게하면 참조되지 않은 모든 항목이 제거되므로 나중에 일부 항목을 유지하기로 결정한 경우 나에게 울지 마세요!

먼저 이와 같은 것을 실행해야 할 수도 있습니다. 오 이런, 자식은 복잡합니다!

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

이 모든 것을 스크립트에 넣습니다.

http://sam.nipl.net/b/git-gc-all-ferocious



18
우수한 : D 답변을 복제하여 더 많은 점수를 얻으려는 나의 사악한 계획이 효과가
Sam Watkins

예! 이것은 효과가 있었지만 전체 스크립트를 실행해야했습니다. gc 명령 (구성 옵션 포함) 만 실행하는 것만으로는 충분하지 않았습니다.
다니엘

4
효과적인 160K에 102m ... 파괴
prusswan

4
스크립트에 감사드립니다! 보너스 정보 :이 xargs명령은 인식 할 수없는 옵션으로 인해 OS X에서 오류를 생성합니다. 가장 간단한 솔루션 : 사제를 통해 GNU의 xargs를 설치 brew install findutils및 교체 xargs에 의해 gxargs.
qqilihq

26

귀하의 git reflog expire --all잘못입니다. 만료 시간 (기본값 : 90 일)보다 오래된 reflog 항목을 제거합니다. 사용 git reflog expire --all --expire=now.

비슷한 질문에 대한 저의 대답 은 저장소에서 사용하지 않는 객체를 실제로 제거하는 문제를 다룹니다.


18

1) git repo에서 파일을 제거하십시오 (파일 시스템이 아닙니다).

  • git rm --cached path/to/file

2) 다음을 사용하여 repo를 축소합니다.

  • git gc,

  • 또는 git gc --aggressive

  • 또는 git prune

또는이 질문에서 제안 된 위의 조합 : git 저장소 크기 줄이기


10

민감한 데이터 제거에 대한 이 가이드 는 동일한 방법을 사용하여 적용 할 수 있습니다. 기록을 다시 작성하여 파일이있는 모든 개정판에서 해당 파일을 제거하게됩니다. 이것은 파괴적이며 다른 체크 아웃과 저장소 충돌을 일으킬 수 있으므로 먼저 공동 작업자에게 경고하십시오.

다른 사람들을 위해 저장소에서 바이너리를 사용할 수 있도록 유지하려면 원하는 작업을 수행 할 실제 방법이 없습니다. 거의 전부 또는 전혀 없습니다.


8

나를 위해 열쇠는 실행 밝혀졌다 git repack -A -d -f다음, git gc내가 가진 하나의 자식 팩의 크기를 줄일 수 있습니다.


6

Hy!

Git은 저장소를 복제 할 때 실제로 필요한 객체 만받습니다 (올바르게 이해하는 경우).

따라서 실수로 추가 된 파일을 제거하여 마지막 커밋을 수정 한 다음 변경 사항을 원격 저장소에 푸시 할 수 있습니다 (서버의 이전 커밋도 덮어 쓰는 -f 옵션 사용).

그런 다음 해당 저장소의 새 복제본을 만들 때 .git 디렉토리는 큰 파일이 커밋되기 전만큼 작아야합니다.

필요에 따라 서버에서도 불필요한 파일을 제거하려면 서버에서 저장소를 삭제하고 새로 복제 된 복사본 (전체 기록이 있음)을 푸시 할 수 있습니다.



4
git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all

Filename저장소에서 제거하려는 항목 을 변경해야 합니다.


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