리포지토리 크기
- GitLab 15.3에 도입됨, 대체 리포지토리 크기 계산을 위한 기능 플래그
gitaly_revlist_for_repo_size
와gitaly_catfile_repo_size
.
자체 관리 GitLab에서는 기본적으로 GitLab이
du -sk
명령을 사용하여 리포지토리의 크기를 결정합니다. GitLab은 기능 플래그 gitaly_revlist_for_repo_size
로 활성화된 git-rev-list
또는 기능 플래그 gitaly_catfile_repo_size
로 활성화된 git-cat-file
을 대신 사용할 수 있습니다. 다양한 계산 방법 간 전환을 원할 경우 관리자가 기능 플래그를 활성화하거나 비활성화하면 됩니다.프로젝트 개요 페이지는 리포지토리의 모든 파일 크기를 보여줍니다. 크기는 15분마다 업데이트됩니다. 파일 크기는 리포지토리 파일, 아티팩트, LFS를 포함합니다.
크기는 압축, 유지 관리 및 기타 요인으로 인해 한 인스턴스에서 다른 인스턴스로 약간 차이가 있을 수 있습니다. 관리자는 리포지토리 크기 제한을 설정할 수 있습니다.
GitLab은 GitLab.com의 크기 제한을 설정합니다. 더 많은 정보는 계정 및 제한 설정을 참조하세요.
리포지토리 크기 줄이기
Git 리포지토리는 시간이 지남에 따라 커집니다. 대형 파일이 Git 리포지토리에 추가되면:
- 리포지토리를 가져오는 것이 느려집니다. 모든 사용자가 파일을 다운로드해야 하므로
- 서버에 큰 저장 공간을 차지합니다.
- Git 리포지토리 저장소 한도 에 도달할 수 있습니다.
리포지토리를 재작성하면 원치 않는 기록을 제거하여 리포지토리를 작게 만들 수 있습니다. 우리는 git filter-repo
를 git filter-branch
및 BFG보다 권장합니다.
리포지토리 크기 계산
리포지토리의 크기는 리포지토리에 있는 모든 파일의 누적 크기를 계산하여 결정됩니다. 이는 리포지토리의 해시 저장 경로에서 du --summarize --bytes
를 실행하는 것과 유사합니다.
리포지토리 기록에서 파일 제거
GitLab은 유지 관리의 일환으로 도달할 수 없는 객체를 정리합니다. GitLab에서 리포지토리의 디스크 크기를 수동으로 줄이려면 먼저 대형 파일에 대한 참조를 브랜치, 태그, 및 GitLab에 의해 생성된 기타 내부 참조(ref)에서 제거해야 합니다. 이러한 refs에는 다음이 포함됩니다.
refs/merge-requests/*
refs/pipelines/*
refs/environments/*
refs/keep-around/*
이 refs는 자동으로 다운로드되지 않으며 숨겨진 refs는 광고되지 않지만, 프로젝트 내보내기를 사용하여 이러한 refs를 제거할 수 있습니다.
GitLab 리포지토리에서 파일을 제거하려면:
-
git filter-repo
와 선택적으로git-sizer
를 지원 패키지 관리자를 사용하거나 소스에서 설치합니다. -
프로젝트 내보내기에서 새 내보내기를 생성하고 다운로드합니다. 이 프로젝트 내보내기는 리포지토리 및 refs의 백업 복사본을 포함하여 파일을 제거하는 데 사용됩니다.
전체 프로젝트 내보내기가 프로젝트 크기로 인해 신뢰성 있게 완료되지 않으면, 프로젝트 관계 내보내기 API를 사용하여 다른 내보내기 구성 요소와 독립적으로 리포지토리의 복사본을 얻을 수 있습니다.
-
백업을
tar
로 압축 해제합니다:tar xzf project-backup.tar.gz
여기에는
git bundle
로 생성된project.bundle
파일이 포함됩니다. -
--bare
및--mirror
옵션을 사용하여 번들에서 리포지토리의 새 복사본을 클론합니다:git clone --bare --mirror /path/to/project.bundle
-
project.git
디렉토리로 이동합니다:cd project.git
-
번들 파일에서 클론하면
origin
원격이 로컬 번들 파일로 설정되므로, 리포지토리의 URL로 변경합니다:git remote set-url origin https://gitlab.example.com/<namespace>/<project_name>.git
-
git filter-repo
또는git-sizer
를 사용하여 리포지토리를 분석하고 제거하고 싶은 항목을 결정하기 위해 결과를 검토합니다:# git filter-repo 사용 git filter-repo --analyze head filter-repo/analysis/*-{all,deleted}-sizes.txt # git-sizer 사용 git-sizer
-
관련
git filter-repo
옵션을 사용하여 리포지토리의 기록을 제거합니다. 두 가지 일반적인 옵션은 다음과 같습니다:-
특정 파일 제거를 위한
--path
및--invert-paths
:git filter-repo --path path/to/file.ext --invert-paths
-
예를 들어 10M보다 큰 모든 파일을 제거하기 위한
--strip-blobs-bigger-than
:git filter-repo --strip-blobs-bigger-than 10M
더 많은 예제와 전체 문서는
git filter-repo
문서를 참고하세요. -
-
내부 refs를 제거하려고 하므로 각 실행에서 생성된
commit-map
파일이 필요하여 제거할 내부 refs를 알려줍니다. 각git filter-repo
실행은 새로운commit-map
을 생성하며, 이전 실행의commit-map
을 덮어씁니다. 다음 명령을 사용하여 각commit-map
파일을 백업할 수 있습니다:cp filter-repo/commit-map ./_filter_repo_commit_map_$(date +%s)
이 단계와 이후 모든 단계(예: 리포지토리 정리 단계)를 모든
git filter-repo
명령을 실행할 때마다 반복합니다. -
변경 사항을 강제로 푸시할 수 있도록 미러 플래그를 해제해야 합니다:
git config --unset remote.origin.mirror
-
모든 브랜치를 GitLab에서 덮어쓰도록 강제 푸시합니다:
git push origin --force 'refs/heads/*'
보호된 브랜치로 인해 이 작업이 실패할 수 있습니다. 진행하려면 브랜치 보호를 제거하고 푸시한 후 보호된 브랜치를 다시 활성화해야 합니다.
-
태그 릴리스에서 대형 파일을 제거하려면, GitLab의 모든 태그에 강제 푸시합니다:
git push origin --force 'refs/tags/*'
보호된 태그로 인해 이 작업이 실패할 수 있습니다. 진행하려면 태그 보호를 제거하고 푸시한 후 보호된 태그를 다시 활성화해야 합니다.
-
더 이상 존재하지 않는 커밋에 대한 끊어진 링크를 방지하려면
git filter-repo
로 생성된refs/replace
를 푸시합니다.git push origin --force 'refs/replace/*'
이 작업이 작동하는 방법에 대한 정보는 Git
replace
문서를 참조하세요. -
다음 단계 시도 전에 최소 30분을 기다리세요.
-
리포지토리 정리를 실행하세요. 이 과정은 30분 이상 된 객체만 정리합니다. 공간이 해제되지 않음에 대한 자세한 정보는 это 번역하여 확인하세요.
리포지토리 정리
리포지토리 정리를 통해 객체의 텍스트 파일을 업로드하면 GitLab이 이 객체들에 대한 내부 Git 참조를 제거합니다.
git filter-repo
를 사용하여 리포지토리 정리에 사용할 수 있는 객체 목록( commit-map
파일)을 생성할 수 있습니다.
안전하게 리포지토리를 정리하려면 작업 기간 동안 읽기 전용으로 설정해야 합니다.
이 과정은 자동으로 발생하지만, 진행 중인 쓰기가 있을 경우 정리 요청 제출이 실패하므로, 계속하기 전에 진행 중인 git push
작업이 있으면 취소하세요.
경고:
내부 Git 참조를 제거하면 관련된 병합 요청 커밋, 파이프라인, 변경 사항 세부정보가 더 이상 사용할 수 없게 됩니다.
리포지토리를 정리하려면:
-
왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
-
설정 > 리포지토리로 이동합니다.
-
리포지토리 유지보수를 확장합니다.
-
객체 목록을 업로드합니다. 예를 들어,
filter-repo
디렉토리에 위치한git filter-repo
가 생성한commit-map
파일입니다.commit-map
파일이 너무 크면 백그라운드 정리 프로세스가 타임아웃되어 실패할 수 있습니다.이로 인해 리포지토리 크기가 예상대로 줄어들지 않을 수 있습니다. 이 문제를 해결하려면 파일을 나누어 여러 부분으로 업로드합니다.
20000
부터 시작하고 필요에 따라 줄입니다. 예를 들어:split -l 20000 filter-repo/commit-map filter-repo/commit-map-
-
정리 시작을 선택합니다.
이 과정은:
-
오래된 커밋에 대한 내부 Git 참조를 제거합니다.
-
리포지토리에 대해
git gc --prune=30.minutes.ago
를 실행하여 참조되지 않은 객체를 제거합니다. 리포지토리를 재패킹하면 일시적으로 리포지토리 크기가 크게 증가하는데, 이는 이전 패키지 파일이 새로운 패키지 파일이 생성될 때까지 제거되지 않기 때문입니다. -
프로젝트에 연결된 사용하지 않는 LFS 객체를 링크 해제하여 저장 공간을 해제합니다.
-
디스크에서 리포지토리의 크기를 재계산합니다.
GitLab은 정리가 완료된 후 재계산된 리포지토리 크기와 함께 이메일 알림을 보냅니다.
리포지토리 크기가 줄어들지 않는 경우, 이는 최근 30분 이내에 발생한 Git 작업에 참조된 느슨한 객체가 남아 있어서일 수 있습니다.
리포지토리가 최소 30분간 사용되지 않은 상태에서 이러한 단계를 다시 실행해 보세요.
리포지토리 정리를 사용할 때 유의사항:
-
프로젝트 통계는 캐시됩니다. 저장소 사용량이 감소하는 것을 보려면 5-10분 기다려야 할 수 있습니다.
-
정리는 30분 이상 된 느슨한 객체를 제거합니다. 이는 최근 30분 이내에 추가되거나 참조된 객체가 즉시 제거되지 않음을 의미합니다.
Gitaly 서버에 접근할 수 있는 경우, 해당 지연을 생략하고
git gc --prune=now
명령을 실행하여 모든 느슨한 객체를 즉시 제거할 수 있습니다. -
이 과정은 GitLab 캐시 및 데이터베이스에서 일부 다시 작성된 커밋 복사본을 제거하지만, 여전히 여러 격차가 존재하며 일부 복사본은 무기한 지속될 수 있습니다.
인스턴스 캐시 지우기는 일부를 제거하는 데 도움이 될 수 있지만, 보안 목적을 위해 의존해서는 안 됩니다!
블롭 제거
- GitLab 17.1에서
rewrite_history_ui
라는 플래그와 함께 도입됨. 기본값으로 비활성화 되어 있습니다.- GitLab 17.2에서 GitLab.com에서 활성화됨.
- GitLab 17.3에서 셀프 관리 및 GitLab 전용에서 활성화됨.
사고로 커밋된 민감한 정보나 기밀 정보를 영구적으로 삭제하여 리포지토리의 기록에서 더 이상 접근할 수 없도록 합니다.
대신 문자열을 ***REMOVED***
로 바꾸려면 텍스트 수정을 참조하세요.
사전 요구사항:
- 프로젝트에 대한 소유자 역할이 있어야 합니다.
- 제거할 객체 ID 목록가 필요합니다.
리포지토리에서 블롭을 제거하려면:
-
왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
-
설정 > 리포지토리를 선택합니다.
-
리포지토리 유지보수를 확장합니다.
-
블롭 제거를 선택합니다.
-
서랍에서 제거할 블롭 ID 목록을 입력하고, 각 ID를 별도의 줄에 입력합니다.
-
블롭 제거를 선택합니다.
-
확인 대화상자에서 프로젝트 경로를 입력합니다.
-
예, 블롭 제거를 선택합니다.
-
왼쪽 사이드바에서 설정 > 일반을 선택합니다.
-
고급이라는 섹션을 확장합니다.
-
하우스키핑 실행을 선택합니다.
객체 ID 목록 가져오기
Blob을 제거하려면 제거할 객체 목록이 필요합니다.
이 ID를 얻으려면 Git ls-tree
명령을 사용하세요.
사전 요구 사항:
- 리포지토리가 로컬 머신에 클론되어 있어야 합니다.
예를 들어, 특정 커밋 또는 브랜치에서 크기별로 정렬된 파일 목록을 가져오려면:
- 터미널을 열고 리포지토리 디렉터리로 이동합니다.
-
다음 명령어를 실행합니다:
git ls-tree -r -t --long --full-name <COMMIT/BRANCH> | sort -nk 4
예제 출력:
100644 blob 8150ee86f923548d376459b29afecbe8495514e9 133508 doc/howto/img/remote-development-new-workspace-button.png 100644 blob cde4360b3d3ee4f4c04c998d43cfaaf586f09740 214231 doc/howto/img/dependency_proxy_macos_config_new.png 100644 blob 2ad0e839a709e73a6174e78321e87021b20be445 216452 doc/howto/img/gdk-in-gitpod.jpg 100644 blob 115dd03fc0828a9011f012abbc58746f7c587a05 242304 doc/howto/img/gitpod-button-repository.jpg 100644 blob c41ebb321a6a99f68ee6c353dd0ed29f52c1dc80 491158 doc/howto/img/dependency_proxy_macos_config.png
출력의 세 번째 열은 blob의 객체 ID입니다.
대안으로, Repositories API list repository tree 엔드포인트를 사용하여 이러한 ID를 얻을 수 있습니다.
저장소 제한
리포지토리 크기 제한:
프로젝트가 크기 제한에 도달하면 다음을 수행할 수 없습니다:
- 프로젝트에 푸시할 수 없습니다.
- 새 병합 요청을 생성할 수 없습니다.
- 기존 병합 요청을 병합할 수 없습니다.
- LFS 객체를 업로드할 수 없습니다.
여전히 다음을 수행할 수 있습니다:
- 새 이슈 생성.
- 프로젝트 클론.
리포지토리 크기 제한을 초과하는 경우 다음을 수행할 수 있습니다:
- 일부 데이터 제거.
- 새 커밋 만들기.
- 리포지토리에 푸시.
이러한 조치가 불충분한 경우 다음을 수행할 수 있습니다:
- 일부 blob을 LFS로 이동.
- 기록에서 오래된 종속성 업데이트 제거.
불행히도 이 워크플로우는 작동하지 않습니다. 커밋에서 파일을 삭제하는 것이 실제로 리포지토리 크기를 줄이지 않기 때문입니다. 이전 커밋과 blob은 여전히 존재합니다. 대신에, 기록을 다시 작성해야 합니다. 오픈 소스 커뮤니티에서 유지 관리되는 도구인 git filter-repo
를 사용해야 합니다.
참고:
git gc
가 GitLab 측에서 실행될 때까지 “제거된” 커밋과 blob은 여전히 존재합니다. 또한, 변경된 기록을 GitLab에 푸시할 수 있어야 하며, 이는 이미 최대 크기 제한을 초과한 경우 불가능할 수 있습니다.
이러한 제한을 해제하려면, 자체 관리 GitLab 인스턴스의 관리자가 초과한 특정 프로젝트의 제한을 증가시켜야 합니다. 따라서 항상 제한 이하로 유지하는 것이 좋습니다. 제한에 도달하고 임시로 증가시킬 수 없는 경우, 유일한 선택은:
- 로컬에서 불필요한 모든 내용을 정리합니다.
- GitLab에서 새 프로젝트를 만들어 대신 사용하기 시작합니다.
문제 해결
GUI에 잘못된 리포지토리 통계 표시
표시된 크기 또는 커밋 수가 내보낸 .tar.gz
또는 로컬 리포지토리와 다를 경우,
GitLab 관리자가 업데이트를 강제로 진행할 수 있도록 요청할 수 있습니다.
rails 콘솔을 사용하여:
p = Project.find_by_full_path('<namespace>/<project>')
pp p.statistics
p.statistics.refresh!
pp p.statistics
# 이전 값과 비교
# 프로젝트 통계를 지우는 대체 방법
p.repository.expire_all_method_caches
UpdateProjectStatisticsWorker.perform_async(p.id, ["commit_count","repository_size","storage_size","lfs_objects_size"])
# 총 아티팩트 스토리지 공간을 별도로 확인
builds_with_artifacts = p.builds.with_downloadable_artifacts.all
artifact_storage = 0
builds_with_artifacts.find_each do |build|
artifact_storage += build.artifacts_size
end
puts "#{artifact_storage} bytes"
공간이 해제되지 않음
이 페이지에 정의된 프로세스는 리포지토리 내보내기의 크기를 줄일 수 있지만,
웹 UI와 터미널 모두에서 파일 시스템의 사용량은 변하지 않는 것처럼 보일 수 있습니다.
프로세스는 리포지토리에 많은 접근할 수 없는 객체들을 남깁니다.
이 객체들은 접근할 수 없기 때문에 내보내기에 포함되지 않지만 여전히 파일 시스템에 저장됩니다.
이 파일들은 두 주의 유예 기간 후에 정리됩니다. 정리는 이러한 파일들을 삭제하고
저장소 사용 통계가 정확하게 유지되도록 보장합니다.
이 프로세스를 빠르게 진행하려면
‘접근할 수 없는 객체 정리’ 유지 보수 작업을 참조하세요.
Sidekiq 프로세스가 프로젝트 내보내기에 실패함
가끔 Sidekiq 프로세스가 프로젝트를 내보내는 데 실패할 수 있으며, 이는
실행 중에 종료되는 경우와 같습니다.
GitLab.com 사용자들은 이 문제를 해결하기 위해 지원팀에 연락해야 합니다.
자체 관리 사용자들은 Rails 콘솔을 사용하여 Sidekiq 프로세스를 우회하고
수동으로 프로젝트 내보내기를 트리거할 수 있습니다:
project = Project.find(1)
current_user = User.find_by(username: 'my-user-name')
RequestStore.begin!
ActiveRecord::Base.logger = Logger.new(STDOUT)
params = {}
::Projects::ImportExport::ExportService.new(project, current_user, params).execute(nil)
이렇게 하면 UI를 통해 내보내기가 가능해지지만 사용자에게 이메일이 전송되지는 않습니다.
수동으로 프로젝트 내보내기를 트리거하고 이메일을 전송하려면:
project = Project.find(1)
current_user = User.find_by(username: 'my-user-name')
RequestStore.begin!
ActiveRecord::Base.logger = Logger.new(STDOUT)
params = {}
ProjectExportWorker.new.perform(current_user.id, project.id)