はじめに
自宅のGitLabでホスティングしているリポジトリをGitHubに移行しました。
以降自体は難しくなく、Qiitaでもたくさんの記事が見つかります。
しかし、自分の場合はこれらで考慮されていないトラブルに遭遇してしまったので、記録として記事を書きます。
対象リポジトリの情報
移行対象のリポジトリは下記のようなスペックです。
- GitLab使用
- 75,000ファイル(master)
- リポジトリ容量 9GB
- LFS未使用
- 800コミット
- 1ファイルの最大ファイルサイズ 1.5GB(過去コミット含む)
移行の際のポイント
自分の知る限り、GitHubには次の制限があります。
GitHubの制限
- 1ファイルは100MB未満である必要がある
- 一度にpushできるサイズは2GB未満である必要がある
これらのうち、1つ目めの「1ファイルは100MB未満である必要がある」は、LFSを使うことで回避できるようになります。「Gitリポジトリのコピー時、git lfs migrateでGIT-LSF移行 - Qiita」をそのまま作業できます。
問題は2つ目の「一度にpushできるサイズは2GB未満である必要がある」です。これを解決するために、pushを1コミットずつ行うスクリプトを作成して対応しました。
なお、今回移行対象となったリポジトリは、1コミット2GBを超えることはありませんでしたが、もし1コミットで大容量のファイルをコミットしてしまっているような場合(50MBのアセットを40ファイル同時にコミットしている等)は、コミットを分割することで対応する必要があります。
移行の流れ
おおむね、「Gitリポジトリのコピー時、git lfs migrateでGIT-LSF移行 - Qiita」に沿っています。
git clone --mirror https://gitlab.example.com/user/myrepo.git
cd myrepo.git/
git lfs migrate info --everything
git lfs migrate import --include="*.weights,*.png,*.jpg" --everything
git push --mirror https://github.com/example/new-myrepo.git # ここで失敗する
最後のgit push
では、下記のようなエラーメッセージが表示されました。
Enumerating objects: 62968, done.
Counting objects: 100% (62968/62968), done.
Delta compression using up to 16 threads
Compressing objects: 100% (62968/62968), done.
remote: fatal: pack exceeds maximum allowed size (2.00 GiB)
error: remote unpack failed: index-pack abnormal exit
To github.com:example/new-myrepo.git
! [remote rejected] master -> master (failed)
error: failed to push some refs to 'git@github.com:example/new-myrepo.git'
packファイルは2GBを超えてはいけないとのエラーです。
packファイルのサイズを制限したり分割させたりといったgit設定はなさそうなので、1コミットずつpushするスクリプトを作成しました。
(https://gist.github.com/piki/10d57cda6d5b25744fdeefb56b421fe4 のものを流用し、rubyを使わないようにしたり、内容をシンプルにしたりしています)
#!/bin/bash -e
COMMIT_STEP=1 # 何コミットずつpushするか。1でよい。時間がかかるようなら、100とかを試してもよい。
START_COMMIT=1 # 一番最初は何コミット目から始めるか。通常1でよい。
git log --pretty=%H | tac > commits
COMMIT_COUNT=$(wc -l commits | cut -d' ' -f1)
for i in `seq $START_COMMIT $COMMIT_STEP $COMMIT_COUNT`; do
echo ====== $i
COMMIT=$(head -$i commits | tail -1)
git tag -d foo || true
git tag foo $COMMIT
git push -f origin foo
done
git tag -d foo
git push origin HEAD
git push --mirror
git lfs push --all # 念のため
git config --unset remote.origin.mirror # コミット単位でpushしたいのでmirror設定を解除する
./push-big-repo.sh
これで、無事、移行できました。