読者です 読者をやめる 読者になる 読者になる

weblog of key_amb

主にIT関連の技術メモ

Git のリポジトリを1コマンドで統合できるシェルスクリプトを書いた

気づいたら GitHubリポジトリが40個以上ありました。
古いものは作りかけだったり、実験して後に放置したものなどがいろいろありました。*1

そのままでも特に困ることはなく、これまで気にすることはなかったのですが、最近ときどき邪魔だなと思うことがあったので、少し整理することにしました。

本当にこれは要らないなと思うものはリポジトリを削除したのですが、一応取っておこうかなと思うものもあったので、リポジトリを統合する方法はないかなと検索してみたところ、下の記事を見つけました。

何度かこの通りにやって上手く行ったのですが、まだいくつか統合したいリポジトリがあったので、1コマンドで統合作業ができるようなスクリプトを書いてみました。

こんな感じで叩きます。

# 親リポジトリのトップディレクトリで
git-merge-repository <統合対象のリポジトリURL> [ディレクトリ(省略可)]

第2引数のディレクトリを省略した場合は、統合対象のリポジトリ名がそのままディレクトリ名になります。

処理の流れは次のような感じ:

  1. 統合対象のリポジトリgit clone
  2. clone したディレクトリに cd して、 git filter-branch でコミット履歴を書き換え
    ... 全てサブディレクトリ下の変更になるように書き換える
  3. filter-branch の終了コードが 0 だったら確認プロンプトを表示。Y なら次に進む。(N なら終了)
  4. git remote set-url で remote origin を親リポジトリの remote origin に変更
  5. git pull --rebase && git push origin master
    ... ここまでで remote リポジトリでは統合完了
  6. cd .. で親リポジトリディレクトリに戻り、clone したディレクトリを rm -rf して git pull する
    => 統合されたディレクトリが fetch & merge される

注意点が2つあります。

  1. Qiita の記事のコメントにもありますが、Macsed では \t がタブとして変換できませんでした。ので、 CMD_SED=gsed とシェル変数(or 環境変数)を付けて実行すれば sed の代わりに gsed を使うようにしました。
  2. Qiita の記事では全てのブランチの履歴を取得する方法も載っていますが、このスクリプトでは HEAD 固定になっています。

実行しているコマンド等、改良の余地はあるかと思いますが、とりあえず自分はこれで困ってないので、このまま紹介しておきます。

また、参考として、実際に動作させた環境情報は、MacOSX El Captain, git v2.5.4 (Apple Git), bash 4.3.x (Homebrew) です。

ユースケースはそんなにないかなと思いますが、機会がありましたらどうぞご自由にご利用ください。

余談

削除と統合の結果、GitHub 上のリポジトリは34個に減りました。

*1:そういうのは BitBucket に置くといいよ、というような話も聞いたことはあります。