2010年2月7日日曜日

Mercurial の、 hg revert / hg rollback / hg backout の使い分け

以前からgitを使っていたのですが、最近は職場のバージョン管理システムがMercurial hg になっているので、もっぱらhgばかり使っています。ということで、いくつか覚えたhgネタ。

Mercurialやgitに限らず、いかなるバージョン管理システムを使用していても、人間が使う以上運用中にミスが発生することは避けられません。今回はMercurial使用中に間違ったコミットやプッシュを行ってしまった際の対処法を調べてみました。

参考文献はこちら。
4798021741入門Mercurial Linux/Windows対応
秀和システム 2009-01

by G-Tools


間違いを修正するためのコマンドは、大きく分けて以下の3つがあります。
  • hg revert
  • hg rollback
  • hg backout
またコマンドを用いて修正する意外にも、ローカル作業する際に作業用リポジトリを別に作って、問題に気づいたらリポジトリごと削除するという運用もありますが、今回は説明を省きます。


■hg revert
適用可能なのは「ローカルのリポジトリ上で、コミットをする前に問題に気づいたとき」。
作業中にちょっと間違った際など、ファイル単位でコミット前の状態(parentの状態)に戻すことができ大変便利です。コミットしてしまった場合は、次のhg rollbackを使用します。


■hg rollback
適用可能なのは「ローカルのリポジトリ上で、コミットをした直後に問題に気づいたとき」。
直前の1回分だけ、commitを取り消すことができます。マージ作業だろうがなんだろうが跡形もなく消してくれるため、後から見ても痕跡がなく綺麗です。操作も簡単で安全なため、これが使用可能なときはこちらを使用すると便利です。

一応、直前の1回だけならリモートの共有リポジトリへのpushも取り消すことができるのですが、これは後述の理由からお勧めしません。一度リモートにpushしてしまったら、次のhg backoutを使って取り消すことになります。


■hg backout
適用可能なのは「ローカルのリポジトリ上で、複数回コミットした後にに問題に気づいたとき」か、または「リモートの共有リポジトリにプッシュしてしまった後に問題に気づいたとき」。
どうしようもなくなってしまったときの最後の手段がこれ。指定したリビジョンのcommitの内容を完全に打ち消す新しいリビジョンを作ってくれます。あとは、手動でこの自動で作られたリビジョンを元のリビジョンにmergeしてcommitすることで、いかなる問題であろうとも無理矢理打ち消す事が可能になります。

もっぱら間違ってプッシュしてしまった際に使用します。
一応hg rollbackでも直前のpushを取り消すことが可能ですが、一度pushされてしまった内容はどこかの誰かのリポジトリにpullされてしまっている可能性があり、そうなると共有リポジトリだけをrollbackしても効果がありません。(このように、間違いも分散して広まってしまうのが分散バージョン管理の恐ろしいところ)

このようなときは、hg backoutで修正リビジョンを作りマージしたあと、再度共有リポジトリにpushすれば、他の誰かのリポジトリに問題が取り込まれてしまっていても次のpullで無事修正されます。