저장소 크기

  • GitLab 15.3에서 도입된 기능 플래그 gitaly_revlist_for_repo_sizegitaly_catfile_repo_size는 대체 저장소 크기 계산을 위한 것입니다.

플래그: 자체 관리 GitLab에서 기본적으로 GitLab은 저장소의 크기를 결정하기 위해 du -sk 명령을 사용합니다. 대신 gitaly_revlist_for_repo_size 기능 플래그로 활성화된 git-rev-list 또는 gitaly_catfile_repo_size 기능 플래그로 활성화된 git-cat-file을 사용할 수 있습니다. 서로 다른 계산 방법간 전환을 위해 관리자가 이러한 기능 플래그를 활성화 또는 비활성화할 수 있습니다.

프로젝트 개요 페이지에는 저장소의 모든 파일의 크기가 표시됩니다. 크기는 15분마다 업데이트됩니다. 파일 크기에는 저장소 파일, 아티팩트 및 LFS가 포함됩니다.

압축, 청소 및 기타 요인으로 인해 크기가 서로 다른 경우가 있을 수 있습니다. 관리자는 저장소 크기 제한을 설정할 수 있습니다.

GitLab에서는 GitLab.com의 크기 제한을 설정합니다. 더 많은 정보는 계정 및 제한 설정을 참조하세요.

저장소 크기 줄이기

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated

시간이 지남에 따라 Git 저장소는 커집니다. Git 저장소에 큰 파일을 추가하면:

  • 저장소를 가져오는 시간이 느려집니다. 왜냐하면 모든 사람이 파일을 다운로드해야 하기 때문입니다.
  • 서버에서 많은 저장 공간을 차지합니다.
  • Git 저장소 저장소 제한에 도달할 수 있습니다.

저장소를 재작성하면 원하지 않는 히스토리를 제거하여 저장소를 더 작게 만들 수 있습니다. git filter-repo권장합니다. git filter-branchBFG보다.

경고: 저장소 히스토리를 다시 작성하는 것은 파괴적인 작업입니다. 시작하기 전에 저장소를 백업하는 것이 중요합니다. 저장소를 백업하는 가장 좋은 방법은 프로젝트를 내보내기하는 것입니다.

저장소 크기 계산

저장소의 크기는 저장소의 모든 파일의 누적 크기를 계산하여 결정됩니다. 이는 저장소의 hashed storage path에서 du --summarize --bytes를 실행하는 것과 유사합니다.

저장소 히스토리에서 파일 제거

GitLab에서는 유지 관리를 위해 사용하지 않는 개체를 제거합니다. GitLab에서 저장소의 디스크 크기를 줄이려면 수동으로 먼저 큰 파일의 참조를 제거해야 합니다. 이러한 참조에는:

  • refs/merge-requests/*
  • refs/pipelines/*
  • refs/environments/*
  • refs/keep-around/*

참고: 각 참조에 대한 자세한 내용은 GitLab 특수 참조를 참조하세요.

이러한 참조는 자동으로 다운로드되지 않으며 숨겨진 참조는 공개되지 않지만 프로젝트 내보내기를 사용하여 이러한 참조를 제거할 수 있습니다.

경고: 이 프로세스는 저장소에서 비밀 데이터(예: 비밀번호 또는 키)를 제거하는 데 적합하지 않습니다. 커밋에 대한 정보(파일 내용 포함)는 데이터베이스에 캐시되어 있으며 저장소에서 제거된 후에도 보이는 상태로 유지됩니다. 민감한 데이터를 제거하려면 블롭 제거에서 설명된 메서드를 사용하세요.

GitLab 저장소에서 파일을 제거하려면:

  1. 지원되는 패키지 관리자 또는 소스에서 git filter-repo 및 필요에 따라 git-sizer를 설치합니다.

  2. 프로젝트를 내보낸 후에 이를 다운로드하여 새로운 프로젝트 내보내기를 생성합니다. 이 프로젝트 내보내기에는 저장소의 백업 복사본과 저장소에서 파일을 제거할 수 있는 참조가 포함되어 있습니다.

    프로젝트 크기로 인해 완전한 프로젝트 내보낸이 안정적으로 완료되지 않는 경우 프로젝트 관계 내보내기 API를 사용하여 다른 내보내기 구성 요소와 독립적으로 저장소의 사본을 얻을 수 있습니다.

  3. tar를 사용하여 백업을 압축 해제합니다:

    tar xzf project-backup.tar.gz
    

    이 작업은 git bundle로 생성된 project.bundle 파일이 포함되어 있습니다.

  4. --bare--mirror 옵션을 사용하여 번들에서 저장소의 새로운 복사본을 클론합니다:

    git clone --bare --mirror /path/to/project.bundle
    
  5. project.git 디렉터리로 이동합니다:

    cd project.git
    
  6. 번들 파일에서 클론하는 경우 origin 원격을 로컬 번들 파일의 URL로 변경해야 합니다:

    git remote set-url origin https://gitlab.example.com/<namespace>/<project_name>.git
    
  7. git filter-repo 또는 git-sizer를 사용하여 저장소를 분석하고 결과를 확인하여 제거할 항목을 결정합니다:

    # git filter-repo 사용
    git filter-repo --analyze
    head filter-repo/analysis/*-{all,deleted}-sizes.txt
    
    # git-sizer 사용
    git-sizer
    
  8. 관련 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 문서를 참조하세요.

  9. 내부 참조를 제거하려면 각 실행에서 생성된 commit-map 파일이 필요합니다. 모든 git filter-repo 실행은 새로운 commit-map을 작성하고 이전 실행의 commit-map을 덮어씁니다. 다음 명령을 사용하여 각 commit-map 파일을 백업할 수 있습니다:

    cp filter-repo/commit-map ./_filter_repo_commit_map_$(date +%s)
    

    이 단계와 다음 단계(포함하여 저장소 정리 단계)를 모든 git filter-repo 명령 실행할 때마다 반복해야 합니다.

  10. 변경 사항을 강제로 푸시하려면 변경 사항에서 미러 플래그를 지워야 합니다:

     git config --unset remote.origin.mirror
    
  11. GitLab의 모든 브랜치를 덮어쓰기 위해 변경 사항을 강제로 푸시합니다:

    git push origin --force 'refs/heads/*'
    

    보호된 브랜치로 인해 실패합니다. 계속 진행하려면 브랜치 보호를 제거한 후 푸시하고 다시 보호된 브랜치를 활성화해야 합니다.

  12. 태그된 릴리스에서 큰 파일을 제거하려면 변경 사항을 강제로 모든 태그에 푸시합니다:

    git push origin --force 'refs/tags/*'
    

    보호된 태그로 인해 실패합니다. 계속 진행하려면 태그 보호를 제거한 후 푸시하고 다시 보호된 태그를 활성화해야 합니다.

  13. 더 이상 존재하지 않는 커밋에 대한 데드 링크를 방지하려면 git filter-repo에서 생성된 refs/replace를 푸시합니다.

    git push origin --force 'refs/replace/*'
    

    이 작업 방법에 대한 자세한 내용은 Git의 replace 문서를 참조하세요.

  14. 다음 단계를 시도하기 전에 적어도 30분을 기다립니다.
  15. 저장소 정리를 실행합니다. 이 프로세스는 30분 이상 된 객체만 정리합니다. 더 많은 정보는 Space not being freed를 참조하세요.

저장소 정리

저장소 정리를 통해 객체 파일의 텍스트 파일을 업로드하고 GitLab은 이러한 객체에 대한 내부 Git 참조를 제거합니다. 저장소 정리에 사용할 수 있는 객체 목록(커밋 맵 파일)을 생성하기 위해 git filter-repo를 사용할 수 있습니다.

저장소를 안전하게 정리하려면 작업 기간 동안 읽기 전용으로 설정해야 합니다. 이 작업은 자동으로 수행되지만 진행 중인 쓰기가 있는 경우 정리 요청 제출이 실패하므로 계속하기 전에 진행 중인 git push 작업을 취소해야 합니다.

경고: 내부 Git 참조를 제거하면 관련된 병합 요청 커밋, 파이프라인, 변경 내용 세부 정보를 더 이상 사용할 수 없게 됩니다.

저장소를 정리하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 저장소로 이동합니다.
  3. 저장소 유지 관리를 확장합니다.
  4. 객체 목록을 업로드합니다. 예를 들어, git filter-repo에 의해 생성된 commit-map 파일을 업로드하며 해당 파일은 filter-repo 디렉터리에 있습니다.

    기 적용하면, 파일이 너무 커서 백그라운드 정리 프로세스가 시간 초과되고 실패할 수 있습니다. 결과적으로 저장소 크기가 예상과 같이 줄지 않습니다. 이를 해결하려면 파일을 분할하고 부분적으로 업로드합니다. 20000부터 시작하여 필요에 따라 줄입니다. 예:

    split -l 20000 filter-repo/commit-map filter-repo/commit-map-
    
  5. 정리 시작을 선택합니다.

이렇게 하면:

  • 오래된 커밋에 대한 내부 Git 참조가 제거됩니다.
  • 저장소에 대한 git gc --prune=30.minutes.ago 작업을 수행하여 참조되지 않는 객체를 제거합니다. 저장소를 일시적으로 다시 패킹하는 것은 저장소 크기가 증가하게 하지만, 새로운 팩 파일이 생성될 때까지 이전 팩 파일이 제거되지 않습니다.
  • 프로젝트에 연결된 사용되지 않는 LFS 객체가 링크 해제되어 저장 공간이 해제됩니다.
  • 디스크에서 저장소의 크기를 다시 계산합니다.

GitLab은 정리가 완료된 후 새로 계산된 저장소 크기와 관련하여 이메일 알림을 보냅니다.

저장소 크기가 감소하지 않는 경우, 최근 30분 동안 발생한 Git 작업에서 참조된 결과로 인해 느슨한 객체가 유지된 것일 수 있습니다. 저장소가 적어도 30분간 사용되지 않은 후에 이러한 단계를 다시 실행해 보세요.

저장소 정리를 사용할 때 다음을 참고하세요:

  • 프로젝트 통계는 캐시되어 있습니다. 저장 공간 사용량이 줄어드는 데 5-10분이 걸릴 수 있습니다.
  • 정리는 30분보다 오래된 느슨한 객체를 제거합니다. 이는 최근 30분 동안 추가되거나 참조된 객체가 즉시 제거되지 않음을 의미합니다. Gitaly 서버에 액세스할 수 있다면, 지연 시간을 건너뛰고 모든 느슨한 객체를 즉시 제거하려면 git gc --prune=now를 실행할 수 있습니다.
  • 이 프로세스는 GitLab 캐시와 데이터베이스의 재작성된 커밋 중 일부 사본을 제거하지만, 커버리지에 여전히 많은 공백이 있고 일부 사본이 영원히 남을 수 있습니다. 인스턴스 캐시 지우기를 사용하여 일부 사본을 제거하는 데 도움을 줄 수 있지만, 보안 목적으로 의존해서는 안 됩니다!

BLOB 제거

실수로 커밋된 민감하거나 기밀 정보를 영구적으로 삭제하여 저장소의 기록에서 더 이상 접근할 수 없도록합니다.

대안으로 ***REMOVED***로 문자열을 대체하려면 텍스트 삭제를 참조하세요.

전제 조건:

  • 프로젝트의 소유자 역할이어야 합니다.
  • 제거할 객체 ID 목록이 있어야 합니다.

저장소에서 BLOB를 제거하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 저장소를 선택합니다.
  3. 저장소 유지 관리를 확장합니다.
  4. BLOB 제거를 선택합니다.
  5. 서랍에서 제거할 BLOB ID 목록을 입력하고 각 ID를 개별 라인에 입력합니다.
  6. BLOB 제거를 선택합니다.
  7. 확인 대화상자에서 프로젝트 경로를 입력합니다.
  8. 예, BLOB 제거를 선택합니다.
  9. 왼쪽 사이드바에서 설정 > 일반을 선택합니다.
  10. 고급이라고 표시된 섹션을 확장합니다.
  11. Housekeeping 실행을 선택합니다.

객체 ID 목록 가져오기

BLOB를 제거하려면, 제거할 객체 목록이 있어야 합니다. 이러한 ID를 얻으려면 Git의 ls-tree 명령어를 사용합니다.

전제 조건:

  • 로컬 머신에 저장소를 복제해야 합니다.

예를 들어, 주어진 커밋 또는 브랜치에서 크기별로 정렬된 파일 목록을 얻으려면:

  1. 터미널을 열고 저장소 디렉터리로 이동합니다.
  2. 다음 명령을 실행합니다:

    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(Large File Storage) 개체를 업로드할 수 없습니다.

그럼에도 불구하고 다음을 할 수 있습니다:

  • 새 이슈를 생성할 수 있습니다.
  • 프로젝트를 클론할 수 있습니다.

저장소 크기 제한을 초과하는 경우 다음을 할 수 있습니다:

  1. 일부 데이터를 제거합니다.
  2. 새 커밋을 만듭니다.
  3. 저장소에 다시 푸시합니다.

이러한 조치가 충분하지 않은 경우 다음도 할 수 있습니다:

  • 일부 Blob을 LFS로 이동합니다.
  • 이전 종속성 업데이트를 히스토리에서 제거합니다.

이러한 워크플로는 작동하지 않습니다. 커밋에서 파일을 삭제하더라도 저장소 크기를 실제로 줄이지 않습니다. 왜냐하면 이전 커밋과 Blob이 여전히 존재하기 때문입니다. 대신에 히스토리를 다시 작성해야 합니다. 여러분은 오픈 소스 커뮤니티가 유지보수하는 git filter-repo 도구를 사용해야 합니다.

참고: GitLab 측에서 git gc가 실행될 때까지 “제거된” 커밋과 Blob이 계속 존재합니다. 또한 이미 최대 크기 제한을 초과한 경우, 다시 작성된 히스토리를 GitLab에 푸시할 수 있어야 하며, 이는 불가능할 수 있습니다.

이러한 제한을 해제하려면 Self-Managed GitLab 인스턴스의 관리자가 초과된 특정 프로젝트의 제한을 늘려야 합니다. 따라서 제한을 항상 넘지 않도록 사전에 예방하는 것이 좋습니다. 제한에 도달하고 임시로 증가시킬 수 없는 경우 유일한 옵션은 다음과 같습니다:

  1. 로컬로 모든 불필요한 것을 정리합니다.
  2. 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"])

# 총 artifact 저장 공간을 별도로 확인합니다
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} 바이트"

공간이 반환되지 않음

이 페이지에서 정의한 프로세스는 저장소 내보내기의 크기를 줄일 수 있지만, 웹 UI 및 터미널에서 변경되지 않은 파일 시스템 사용량을 줄이지 않습니다.

이 프로세스는 저장소에 많은 도달할 수 없는 객체가 남게 합니다. 도달할 수 없으므로 내보내기에 포함되지 않지만 여전히 파일 시스템에 저장됩니다. 이러한 파일은 2주의 유예 기간이 지난 후에 제거됩니다. 제거는 이러한 파일을 삭제하고 저장소 사용량 통계가 정확하게 유지되도록 보장합니다.

이 프로세스를 가속화하려면 ‘도달할 수 없는 객체 정리’ housekeeping 작업을 참조하십시오.

Sidekiq 프로세스가 프로젝트 내보내기에 실패함

Tier: Free, Premium, Ultimate Offering: Self-Managed, GitLab Dedicated

가끔 Sidekiq 프로세스가 프로젝트 내보내기에 실패할 수 있습니다. 예를 들어 실행 중에 종료된 경우입니다.

GitLab.com 사용자는 이 문제를 해결하기 위해 지원팀에 문의해야 합니다.

Self-Managed 사용자는 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)