リポジトリサイズの縮小

Git リポジトリは時間とともに大きくなります。 大きなファイルが Git リポジトリに追加されると:

  • 全員がファイルをダウンロードする必要があるため、リポジトリの取得が遅くなります。
  • サーバーのストレージスペースを大量に消費します。
  • git リポジトリの保存制限に達する可能性があります。

リポジトリを書き換えることで、不要な履歴を削除してリポジトリを小さくすることができます。git filter-repo は、Git リポジトリの履歴をすばやく書き換えるためのツールで、この両方よりも推奨されます:

危険:リポジトリの履歴の書き換えは破壊的なオペレーションです。 作業を始める前に、必ずリポジトリをバックアップしてください。 リポジトリをバックアップする最善の方法は、プロジェクトをエクスポートすることです。
注意:git LFS ファイルの削除は、管理者がRake タスクを使用してのみ行うことができます。 この制限の撤廃が予定されています。

リポジトリ履歴からファイルをパージ

プロジェクトのクローンを高速化するには、ブランチやタグを書き換えて不要なファイルを削除します。

  1. サポートされているパッケージマネージャを使用するか、ソースからgit filter-repoをインストールしてください。

  2. --bareを使ってリポジトリの新しいコピーをクローンします:

    git clone --bare https://example.gitlab.com/my/project.git
    
  3. git filter-repoを使って、リポジトリの履歴からファイルをパージします。

    大きなファイルをパージするには、--strip-blobs-bigger-than オプションを使用できます:

    git filter-repo --strip-blobs-bigger-than 10M
    

    Git LFS を使って保存されている大きなファイルをパージするには、--blob--callback オプションを使います。以下の例では、コールバックを使って Git LFS ポインタからファイルサイズを読み込み、10MB 以上のファイルを削除しています。

    git filter-repo --blob-callback '
      if blob.data.startswith(b"version https://git-lfs.github.com/spec/v1"):
        size_in_bytes = int.from_bytes(blob.data[124:], byteorder="big")
        if size_in_bytes > 10*1000:
          blob.skip()
      '
    

    特定の大容量ファイルをパス単位でパージするには、--path--invert-paths オプションを組み合わせます:

    git filter-repo --path path/to/big/file.m4v --invert-paths
    

    その他の例や完全なドキュメントはgit filter-repo ドキュメントをご覧ください。

  4. git filter-repo を実行すると、すべてのリモートが削除されます。プロジェクトのリモートを復元するには、以下を実行します:

    git remote add origin https://example.gitlab.com/<namespace>/<project_name>.git
    
  5. 変更を強制的にプッシュし、GitLab上のすべてのブランチを上書きします:

    git push origin --force --all
    

    ブランチ保護を解除してプッシュし、保護されたブランチを再度有効にしてください。

  6. タグ付きリリースから大きなファイルを削除するには、変更をGitLabのすべてのタグに強制プッシュします:

    git push origin --force --tags
    

    タグの保護を解除してプッシュし、保護されたタグを再度有効にする必要があります。

  7. プロジェクトのハウスキーピングを手動で実行

プロジェクトの統計は、パフォーマンスのためにキャッシュされます。 ストレージ使用率の減少を確認するには、5-10分待つ必要があるかもしれません。

GitLabストレージからファイルをパージ

GitLab でリポジトリのサイズを小さくするには、大きなファイルを含むコミットへの GitLab 内部参照を削除する必要があります。 これらの手順を完了する前に、リポジトリ履歴からファイルをパージしてください。

Git Refの一種であるブランチやタグだけでなく、GitLabは他のRefも自動的に作成します。 これらのRefは、コミットへのデッドリンクやマージリクエストを表示する際の差分の欠落を防ぎます。リポジトリのクリーンアップを使用すると、GitLabからこれらを削除することができます。

以下の内部参照はアドバタイズされません:

  • refs/merge-requests/* をマージリクエストに使用します。
  • refs/pipelines/*パイプライン用。
  • refs/environments/* 環境のために。

また、refs/keep-around/* はディスカッションを含むコミットが削除されないようにするための隠し参照であり、フェッチすることはできません。

しかし、これらの参照はプロジェクトエクスポート内のGitバンドルからアクセスすることができます。

  1. サポートされているパッケージマネージャを使用するか、ソースからgit filter-repoをインストールしてください。

  2. プロジェクトから新しいエクスポートを作成し、ダウンロードします。

  3. tarを使用してバックアップを解凍します:

    tar xzf project-backup.tar.gz
    

    このコンテナには、git bundleによって作成されたproject.bundle ファイルが含まれます。

  4. バンドルからリポジトリの新しいコピーをクローンします:

    git clone --bare --mirror /path/to/project.bundle
    
  5. git filter-repoを使って、リポジトリの履歴からすべてのファイルをパージします。内部参照を削除しようとしているので、どの内部参照を削除するかは、各実行によって生成されるcommit-map を頼りにします。

    注:git filter-repo commit-map 実行するたびに commit-map新しいcommit-map ファイルを commit-map作成git filter-repogit filter-repo commit-mapcommit-map前回のgit filter-repoファイルをgit filter-repo commit-map 上書き commit-mapgit filter-repoしますgit filter-repo 。 実行するたびにこのファイルが必要になります。 を実行するたびに次のステップをgit filter-repo実行します。

    すべての大きなファイルをパージするには、--strip-blobs-bigger-than オプションを使用できます:

    git filter-repo --strip-blobs-bigger-than 10M
    

    特定の大容量ファイルをパス単位でパージするには、--path--invert-paths オプションを組み合わせます。

    git filter-repo --path path/to/big/file.m4v --invert-paths
    

    その他の例や完全なドキュメントはgit filter-repo ドキュメントをご覧ください。

  6. リポジトリのクリーンアップを実行します。

リポジトリのクリーンアップ

GitLab 11.6から導入されました

リポジトリのクリーンアップでは、オブジェクトのテキストファイルをアップロードすると、GitLabがこれらのオブジェクトへのGit内部参照を削除します。git filter-repo を使って、リポジトリのクリーンアップで使えるオブジェクトのリスト(commit-map ファイル)を作成することができます。

リポジトリをクリーンアップするには

  1. リポジトリのプロジェクトに移動します。
  2. settings} 設定 >リポジトリに移動します。
  3. オブジェクトのリストをアップロードします。 たとえば、commit-map ファイルです。
  4. クリーンアップを開始]をクリックします。

これは

  • 古いコミットへの Git 内部からの参照を削除します。
  • リポジトリに対してgit gc を実行します。

完了するとメールが届きます。

リポジトリのクリーンアップを使用する場合は、注意してください:

  • プロジェクト統計はキャッシュされます。 ストレージ使用率の削減を確認するには、5~10分待つ必要があるかもしれません。
  • ハウスキーピングは、2週間以上前のルーズオブジェクトを削除します。 つまり、過去2週間に追加されたオブジェクトは、すぐに削除されません。Gitalyサーバーにアクセスできる場合は、git gc --prune=now 、すべてのルーズオブジェクトをすぐに削除することができます。
  • この処理によって、GitLab のキャッシュやデータベースから書き換えられたコミットのコピーがいくつか削除されますが、カバレッジにはまだ多くのギャップがあり、コピーの一部は無期限に存続する可能性があります。 インスタンスキャッシュをクリアすることで、それらの一部を削除することができるかもしれませんが、セキュリティのために依存すべきではありません!

保管制限

リポジトリサイズの制限:

プロジェクトのサイズが上限に達した場合、プロジェクトを削除することはできません:

  • プロジェクトにプッシュ。
  • 新しいマージリクエストを作成してください。
  • 既存のマージリクエストをマージします。
  • LFSオブジェクトをアップロードします。

まだできます:

  • 新しいイシューを作成します。
  • プロジェクトのクローンを作成します。

リポジトリサイズの制限を超える場合は、次のようにしてください:

  1. 一部のデータを削除します。
  2. 新しいコミットを作成します。
  3. リポジトリにプッシュバックします。

もしかしたら、あなたもそうかもしれません:

  • いくつかのブロブをLFSに移動。
  • 履歴からいくつかの古い依存関係の更新を削除します。

残念ながら、このワークフローはうまくいきません。 コミットでファイルを削除しても、それ以前のコミットやブロブはまだ存在しているので、リポジトリのサイズは実際には小さくなりません。

そのために必要なのは、履歴の書き換えです。私たちは、オープンソースのコミュニティがメンテナンスしているツールgit filter-repoをお勧めします。

注意:git gc が GitLab 側で実行されるまで、”削除された” コミットと blob はまだ存在します。また、書き換えた履歴を GitLab にプッシュできなければなりませんが、すでに最大サイズの制限を超えている場合は不可能かもしれません。

これらの制限を解除するには、自己管理型 GitLab インスタンスの管理者が、制限を超えた特定のプロジェクトの制限を増やす必要があります。 したがって、常に積極的に制限を下回るようにするのがよいでしょう。 制限にぶつかり、それを一時的に増やしてもらうことができない場合は、唯一の選択肢となります:

  1. 現地で不要なものをすべて刈り込みます。
  2. GitLab で新しいプロジェクトを作成し、それを代わりに使い始めましょう。
注意:このプロセスは、リポジトリからパスワードや鍵のような機密データを削除するのには適していません。 ファイルの内容を含むコミットに関する情報はデータベースにキャッシュされ、リポジトリから削除された後も表示されたままになります。