mercuiralを使いながらgithubのpull requestを取り込む方法

http://partake.in/events/95ab571f-c477-43dd-8d96-396d3b670b6f:title=の成果発表です。
先日あるmercurialリポジトリのミラーリポジトリをgithubに作成したところ、開発がgithubに移ってしまうという(mercurial使い的には)ショッキングな出来事がありました。mercurial使いはいろいろ肩身が狭いですね。

それもこれも、「mercuiralを使いながらgithubのpull requestを取り込む方法」についてのノウハウが共有されていないことに問題があります。今後、二度と悲劇を繰り返さないために考察してみました。

想定する構成

考察した結果です。
f:id:troter:20120226224310p:image

urlは次の通り

central repository
https://bitbucket.org/troter/killer-app
mirror repository
https://github.com/troter/killer-app
fork repository
https://github.com/fork/killer-app

それでは、順番に想定する構成について説明していきます。

同期用リポジトリを利用してgithubにミラーリポジトリを作成する

まず、gitユーザにforkしてもらえるようgithubにミラーリポジトリを作成します。

hg-git

mercurialにはgitのリポジトリを扱うためのhg-gitというMercuiral拡張が存在します。

pipを利用する場合は次のコマンドでmercurialとhg-gitをインストールして

pip install mercurial hg-git

~/.hgrcに次の行を追加すれば完了です。

[extensions]
hggit =
同期用リポジトリ

次に、hg-gitを利用して実際にミラーリポジトリを作成します。同期用リポジトリを作成し、同期用リポジトリからhg-gitを使ってミラーリポジトリにpushします。

$ hg clone https://bitbucket.org/troter/killer-app killer-app-bitbucket-github-sync # 同期用
$ cd killer-app-bitbucket-github-sync
$ hg push git+ssh://git@github.com/troter/killer-app.git

同期用のリポジトリのpathsは次のように設定すると便利です。

$ hg paths
default = https://bitbucket.org/troter/killer-app
default-push = git+ssh://git@github.com/troter/killer-app.git

定期的にbitbucketのリポジトリとgithubのリポジトリの同期が必要です。何らかの方法で定期的にpull&pushを行いましょう。また、githubにはsshをつかってpushしますので、ssh-agentを利用しパスフレーズなしでpushできるように工夫しましょう。

# 何らかの方法の例
$ screen ruby -e 'loop { system("hg pull"); system("hg push"); sleep(3600)}'

githubのpull requestを取り込む

ミラーリポジトリを用意して数日後、うれしいことにpull requestされました。取り込んでみましょう。

まず、githubのミラーリポジトリと、pull requestしてきたリポジトリをhg-gitを使ってクローンします。githubのミラーリポジトリのクローンはpull request取り込み用リポジトリとして利用します。

$ hg clone git://github.com/troter/killer-app.git killer-app-github-pull-request # pull request取り込み用
$ hg clone git://github.com/fork/killer-app.git killer-app-github-pull-request-N

両方ともmercurialのリポジトリになりました。pull request取り込み用リポジトリでpull requestを取り込んでみましょう。

$ cd killer-app-github-pull-request
$ hg incoming ../killer-app-github-pull-request-N # 取り込む変更を確認しましょう
$ hg pull ../killer-app-github-pull-request-N
# もしくは
$ hg transplant --source ../killer-app-github-pull-request-N REV1 REV2 REV3

pull request取り込み用リポジトリで内容が問題なければ変更をセントラルリポジトリに反映します。セントラルリポジトリに反映すれば、同期用リポジトリによってミラーリポジトリに反映されます。

$ hg outgoing https://bitbucket.org/troter/killer-app # pull requestの内容を確認
$ hg push https://bitbucket.org/troter/killer-app

最後にgithubのpull requestに「取り込みました」と返信してイシューをクローズしましょう。

普段の作業について

普段の作業を行うリポジトリについては、同期用リポジトリ、pull request取り込み用とは別のリポジトリで作業します。同じリポジトリで行う場合、更新の方向が双方向になりカオスになってしまします。

まとめ

「mercuiralを使いながらgithubのpull requestを取り込む方法」を考察しました。

  • 利点
    • 極力gitを利用しない方法なので、gitの知識が不要
    • リポジトリの更新が一方向になっているので、見通しがよい
    • git使いのパワハラを受けなくて済む
  • 欠点
    • 同期用リポジトリを使って定期的に同期する必要がある
    • 登場するリポジトリがちょっと多い、毎回cloneするので、大きいリポジトリでは不利
    • 僕が実際に運用していないので落とし穴があるかも、、