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

平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

雑にgit cloneして管理していたリポジトリ群をghq管理下に移行してスッキリさせる

このエントリは はてなデベロッパアドベントカレンダーの21日目のエントリです。
developer.hatenastaff.com

id:motemen さん作のリポジトリ管理ツールであるところの ghq を最近ようやく使い始めたところ大変便利だったのですが、いかんせん手元の~/work/~/hobby/にはすでにgit cloneしたリポジトリが山ほど転がっています。今回、それをghq管理下のディレクトリにさっと移してghqライフをスタートさせた話をします。

ghq

ghq そのものについての説明は作者のid:motemenさんのエントリが詳しいので、そちらをご参照ください。
motemen.hatenablog.com
代表的な使い方は↓こういう感じで、まぁだいたいどういうことかわかっていただけるのではないかと思います。

[asato@praline01 ~]$ ghq get git@github.com:astj/p5-Test-WWW-Stub.git
     clone ssh://git@github.com/astj/p5-Test-WWW-Stub.git -> /Users/asato/.ghq/github.com/astj/p5-Test-WWW-Stub
       git clone ssh://git@github.com/astj/p5-Test-WWW-Stub.git /Users/asato/.ghq/github.com/astj/p5-Test-WWW-Stub
Cloning into '/Users/asato/.ghq/github.com/astj/p5-Test-WWW-Stub'...
remote: Counting objects: 329, done.
remote: Compressing objects: 100% (31/31), done.
remote: Total 329 (delta 16), reused 0 (delta 0), pack-reused 283
Receiving objects: 100% (329/329), 55.39 KiB | 0 bytes/s, done.
Resolving deltas: 100% (121/121), done.
Checking connectivity... done.
$ ghq list -p | grep p5
/Users/asato/.ghq/github.com/astj/p5-Test-WWW-Stub
$ ghq look p5-Test-WWW-Stub
        cd /Users/asato/.ghq/github.com/astj/p5-Test-WWW-Stub
[github.com/astj/p5-Test-WWW-Stub]$ pwd
/Users/asato/.ghq/github.com/astj/p5-Test-WWW-Stub

ghqを使い始めて何が良かったか

まぁいろいろあるのですが、個人的に感じている主なメリットは

  • "同じ名前だけど違うリポジトリ"を複数扱う時にどの名前でcloneしたらいいか悩まなくて良くなった
  • リポジトリを探す時に、後述のbash aliasで一発で探せるようになって、記憶力が不要になった

あたりです。なんだかあまり嬉しそうに見えませんが、リポジトリのディレクトリに移動したり新しくgit clone時は基本的に「やるぞ!」という気持ちなので、そこに水を差されずに済むのはそれだけで結構幸せという気持ちがあります。

後は、手元に入っていたpercolと組み合わせてaliasを定義してリポジトリ名をインクリメンタルサーチしてそのディレクトリに移動、というのをスムーズに行えるようにしてあります。

alias repo="ghq look \`ghq list | percol\`"

github.com

ghqを使い始める前に悩んだこと

とまぁ便利にghqを使っているのですが、ghqの便利さを説く人たちが周りに続々増えつつある中僕がずっとためらっていたのは、エントリの冒頭にも書いたように雑多にgit cloneしたディレクトリたちの末路でした。コード読むためだけにcloneしたリポジトリは最悪見捨てて再度ghq getすれば良いのですが、実際にコード書いてるリポジトリでは、秘蔵のブランチやgit stashがあったり、ローカルビルドの成果でgit管理していないファイルが転がっていたり……というのがままあるので捨てるわけにもいきません。また、数が増えてくるとどれが大事に使うべきでどれが雑に捨てていいリポジトリなのか考えるのも億劫です。

ghq-migrator

そこで、既存のリポジトリgit remoteを見ていい感じにディレクトリを移してくれる雑なシェルスクリプトを書いて、それでガーッと引越ししてしまうことにしました。
ghq-migratorなどとカッコつけた名前でgithubにもアップロードしてあります。bashスクリプトが1枚と、10分ほどで書いた雑なREADMEが置いてあるだけです。自分の引越しに使った程度なので中身は雑だしコメントや出力の英語はぶっ壊れていますが、最近のMacの環境でなら動くことは動くのではないかなと思います。
github.com

シェルスクリプトで凝ったオプションの解析をやるのも面倒だったので、手抜きして動作にまつわる設定もすべて環境変数で済ませてあります。~/work/SuperCoolRepository/ghq管理下に引っ越したい場合は

$ GHQ_MIGRATOR_ACTUALLY_RUN=1 ghq-migrator.bash ~/work/SuperCoolRepository

と実行すると、シェルスクリプトgit remoteを頑張って読んでいい感じにmvしてくれます。
頭のGHQ_MIGRATOR_ACTUALLY_RUN=1がないとdry-runになるので、いきなり実行する前に一度dry-runするとやや安全です。
また、デフォルトだとgit remote複数設定されている場合は引越しを行わないのですが、これまた環境変数GHQ_MIGRATOR_PREFER_ORIGIN=1を指定しておくとoriginのurlに合わせたディレクトリに勝手に移動してくれます。(originに複数urlが設定されていた場合のハンドリングは諦めています。諦めて手で動かしてください…)

urlを切り貼りするのに一部はsedを使いましたが、簡単な文字列の加工にはbashの変数の特殊展開を使っています。今回初めて知ったけど便利、ただしリファレンス毎回読まないとわからんという感想でした。以下のエントリにお世話になりました。

qiita.com

ghq-migratorを使った引越し

わたしの手元では、以下のように雑に~/work/以下を全部migratorにかけ、残ったリポジトリは必要に応じてGHQ_MIGRATOR_PREFER_ORIGIN=1を指定して走らせ直したり諦めて手で動かすなどしました。

$ export GHQ_MIGRATOR_ACTUALLY_RUN=1
$ cd ~/work; ls | xargs -I{} ~/hobby/ghq-migrator/ghq-migrator.bash {}
$ ls -l
(残ったディレクトリを眺める)
$ GHQ_MIGRATOR_PREFER_ORIGIN=1  ~/hobby/ghq-migrator/ghq-migrator.bash ./(originのurlに移して問題無さそうなリポジトリ)/

移動しきれなかった一部は手で動かすなどしましたが、手元に転がしていたリポジトリの大半がghq管理下に移行できたため、安心して今日もrepoと一発打って作業ディレクトリへと移動しています。

まとめ

ということで、自分で書いたシェルスクリプトによって手元のリポジトリghq管理下に移行させることに成功しました。リポジトリの移行が面倒でghqを躊躇っていた方はこれを機会に引っ越ししてみてもよいのではないでしょうか。

ghq-migrator の動作に関して作者(かつ筆者)は一切の責任を取りません。お手元で動作を確認の上でご利用ください。

明日の担当はid:sharataniさんです。