hgsubversionではhg mergeしてできたmerge済みrevisionをpushすることはできないのでrebaseする

hgsubversionではhg mergeしてできたmerge済みrevisionをpushすることはできない。 - wyukawa’s blogの続きですが、前回はhgsubversionではhg mergeしてできたmerge済みrevisionをpushすることはできないので、updateしてrevertしてcommitしました。

本家のページによると

If there are new revisions, and you have new revisions in your local hg repository, this will create a new head. The important point to note is that hgsubversion cannot push merge changesets to a svn repository. This means you should not try to merge this new head -- if you do so, hg push to svn will fail. Instead, you should rebase the changesets that you want to push to the Subversion repository (see Rebasing changes below).

HgSubversion - Mercurial

ふーむ。rebaseしろと。ちなみにMercurialの場合はGitとは異なり、rebaseは標準機能には無く、拡張機能です。RebaseExtension - Mercurial

具体例を示します。まずsvnリポジトリを作ります。

c:\svn-work\sample>svnadmin create c:\repos\example

c:\svn-work\sample>cd ..

c:\svn-work>svn co file:///c:/repos/example example
リビジョン 0 をチェックアウトしました。

c:\svn-work>cd example

c:\svn-work\example>echo a>a.txt

c:\svn-work\example>svn add a.txt

c:\svn-work\example>svn ci a.txt -m "first
"
追加しています              a.txt
ファイルのデータを送信しています .
リビジョン 1 をコミットしました。

c:\svn-work\example>echo a>>a.txt

c:\svn-work\example>svn ci a.txt -m "second"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 2 をコミットしました。

c:\svn-work\example>echo a>>a.txt

c:\svn-work\example>svn ci a.txt -m "third"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 3 をコミットしました。

c:\svn-work\example>echo a>>a.txt

c:\svn-work\example>svn ci a.txt -m "forth"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 4 をコミットしました。

c:\svn-work\example>echo a>>a.txt

c:\svn-work\example>svn ci a.txt -m "fifth"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 5 をコミットしました。

こいつをcloneします。

c:\hg-work>hg clone file:///c:/repos/example example

この時点でこんな感じ。

この状態でsvn側のファイルを更新してコミットします。

c:\svn-work\example>echo a>>a.txt

c:\svn-work\example>svn ci a.txt -m "sixth"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 6 をコミットしました。

hg側も更新してコミットします。

c:\hg-work\example>hg ci a.txt -m "add b"

この時点でこんな感じ。

incomingするとsvn側の変更でまだhg側に取り込んでいないものが見れます。

c:\hg-work\example>hg in
incoming changes from file:///c:/repos/example

revision:    6
user:        wyukawa
date:        2010-08-14T12:58:18.579042Z
message:     sixth

この状態でpullすると、こんな感じにmultiple headsになります。

これをmergeすると、前回エントリのようにupdateしてrevertしてcommitが必要になります。

なのでrebaseします。

c:\hg-work\example>hg rebase --svn
merging a.txt
saved backup bundle to c:\hg-work\example\.hg\strip-backup\5734a4fd6a72-backup.h
g

そうするとこんな感じになってpushできます。

pull時にhg pull --rebaseでもいいようです。

試しにやってみます。
svn側を更新して変更してコミットします。

c:\svn-work\example>svn up
U    a.txt
リビジョン 7 に更新しました。

c:\svn-work\example>echo a>>a.txt

c:\svn-work\example>svn ci a.txt -m "eight"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 8 をコミットしました。

incomingでこの変更が見れますね。

c:\hg-work\example>hg in
incoming changes from file:///c:/repos/example

revision:    8
user:        wyukawa
date:        2010-08-14T13:02:05.822042Z
message:     eight

hg側でも変更してコミットします。そしてhg pull --rebaseします。

c:\hg-work\example>echo c>>a.txt

c:\hg-work\example>hg ci a.txt -m "add c"

c:\hg-work\example>hg pull --rebase
pulling from file:///c:/repos/example
[r8] wyukawa: eight
pulled 1 revisions
merging a.txt
saved backup bundle to c:\hg-work\example\.hg\strip-backup\d20684b0c87b-backup.h
g

そうするとこんな感じになってpushできます。

ただbundleファイルをもらってunbundleする場合にrebaseするとチェンジセットが変わるため、svn側にうまくpushできないようです。
なので、ネットワークがつながらない状況での分散開発はどうやるのがいいのか - wyukawa’s blogのような状況の場合は、updateしてrevertしてcommitするしかないかも。

そうすると2回目のbundle取り込み時点でこんな感じにすでに複雑。bundle取り込むたびにheadが増えていくというオチ。まあドンマイなのかな。