hg コマンドで、複数のコミットをまとめて実行か中断ができる仕組みはありませんでしょうか?

169 views
Skip to first unread message

ohira

unread,
Oct 28, 2016, 3:34:05 AM10/28/16
to mercurial-ja
おおひらです。

hg コマンドの複数の処理をまとめてロールバックする方法はありませんでしょうか?

SQLのDBMSのトランザクションのようなことがやりたいのです。


=====

どうして、そんなことがやりたいのかというと

hg のコマンドであれば hg rollback が使えるけど、 
hg flow では一回のhg flow コマンドで複数の処理とcommitが行われるので
hg rollbakc で戻せるのは最後のものだけで中途半端になってしまいます。

hg strip <番号>で hg flow で処理した部分の最初を指定すれば目的を達成できると思うのですが
hgのコマンドで処理して、hg rollback の場合は<番号>の指定が不要で、間違った番号を指定するリスクが少ないという意見がありまして。

(hg rollback にしてもまとめてhg strip にしてもローカルPCのリポジトリでドラフト状態の話なので
多少多めに hg strip して hg pull すれば問題ないように思えるのですが、間違っていますでしょうか)


hg flow rollback とか有ったら便利そうなのですが。。。

Katsunori FUJIWARA

unread,
Oct 28, 2016, 9:00:22 AM10/28/16
to mercurial-ja
藤原です。

2016年10月28日 16:34 ohira <shin....@gmail.com>:

> おおひらです。
>
> hg コマンドの複数の処理をまとめてロールバックする方法はありませんでしょうか?
>
> SQLのDBMSのトランザクションのようなことがやりたいのです。
> https://www.postgresql.jp/document/7.2/tutorial/tutorial-transactions.html
>
> =====
>
> どうして、そんなことがやりたいのかというと
>
> hg のコマンドであれば hg rollback が使えるけど、
> hg flow では一回のhg flow コマンドで複数の処理とcommitが行われるので
> hg rollbakc で戻せるのは最後のものだけで中途半端になってしまいます。
>
> hg strip <番号>で hg flow で処理した部分の最初を指定すれば目的を
> 達成できると思うのですが
> hgのコマンドで処理して、hg rollback の場合は<番号>の指定が不要で、
> 間違った番号を指定するリスクが少ないという意見がありまして。

一度の hg flow 実行に起因する複数の内部的 commit の成果を、hg
rollback で一括破棄すること自体は可能です。

※ 以下、動作確認等無しで書いてますので、細部の間違いには目をつぶっ
てください(笑)

例えば、以下のような感じで、flow コマンド処理自体を、transaction
スコープとして囲むラッパー処理を用意しておいて:

def flowwrap(orig, ui, repo, cmd=None, *arg, **kwarg):
with repo.transaction('flow'):
return orig(ui, repo, cmd, *arg, **kwargs)

hgflow エクステンションの cmdtable 中の "flow" エントリの関数を、
上記のラッパーでラップしてやります。

from mercurial import error, extensions

def extsetup(ui):
try:
flowmod = extensions.find('hgflow')
extensions.wrapcommand(flowmod.cmdtable 'flow', flowwrap)
except KeyError:
raise error.Abort('hgflow is not enabled!')

以上の処理を自前のエクステンションにおいて実施することで、
"hg flow" コマンド処理全体がトランザクション対象になります。

但し、hg flow コマンド全体がトランザクション対象となることで、コマ
ンドの終了は、以下の2つに明確に分類されます。

- 成功: すべてのコミット成果の記録
- 失敗: すべてのコミット成果の破棄

例えば、マージ処理で衝突が発生した場合、 hgflow は例外終了するため、
途中までの成果が全て破棄されてしまいます。

現状の hgflow は、merge を tag や commit といった他の処理と同列に
扱っていて、エラー復帰の場合は問答無用で例外終了、という定型的な流
れなのですが、update 処理みたいな特別扱いにした上で:

https://bitbucket.org/yujiewu/hgflow/src/eef72dda34c5baffa4a629123bbafc3904a8c6a4/src/hgflow.py?#hgflow.py-1079

衝突検出時には識別可能な例外を raise するようにすれば、同梱エクス
テンションの shelve での対処と同じ要領で、途中成果を残したままにで
きるんですけどねぇ。

https://www.mercurial-scm.org/repo/hg/file/438173c41587/hgext/shelve.py#l769

とは言え、現状の hgflow の実装は、finish 等による上流へのマージの
前に、予め feature ブランチ側で衝突解消済みと仮定しているみたいで
すから、そもそもこの辺の心配は無用なのかな?

と思ったら、再開機能の要望が issue であがってますね。

https://bitbucket.org/yujiewu/hgflow/issues/53/resume-running-scenario-after-error


なお、Mercurial はコマンド実行横断のトランザクションはサポートして
いません。ですので、仮に再開機能が実装されたとしても、衝突解消を含
んだ一連の操作を rollback の機能で一括破棄することはできません。

この場合は strip の利用が必須になります。


また、先述したラッパー関数を使用する場合、flow の pull アクション
が作業領域更新段階で失敗した時も、履歴情報取り込み成果が破棄されて
しまいます。

余計な通信の抑止を考えた場合、アクションに応じてトランザクション適
用を切り替えた方が妥当でしょうね。

finish, promote あたりに適用すれば十分かな?

> (hg rollback にしてもまとめてhg strip にしてもローカルPCのリポジトリでドラフト状態の話なので
> 多少多めに hg strip して hg pull すれば問題ないように思えるのですが、間違っていますでしょうか)
>
> hg flow rollback とか有ったら便利そうなのですが。。。



--
----------------------------------------------------------------------
FUJIWARA Katsunori(flying...@gmail.com)

ohira

unread,
Nov 1, 2016, 4:22:33 AM11/1/16
to mercurial-ja
おおひらです。

回答ありがとうございます。

やっぱり現実的には hg strip でしょうかね。

> 一度の hg flow 実行に起因する複数の内部的 commit の成果を、hg 
> rollback で一括破棄すること自体は可能です。 
それ用にエクステンションを作るとできるようになるのですね。


> なお、Mercurial はコマンド実行横断のトランザクションはサポートして 
> いません。ですので、仮に再開機能が実装されたとしても、衝突解消を含 
> んだ一連の操作を rollback の機能で一括破棄することはできません。 
>
> この場合は strip の利用が必須になります。 
finish時に定型的に複数行のhg flow を実行することになるので
複数行のhg flowが無かったことにできると嬉しいです。


hg strip <リビジョン番号> で可能ですが、
リビジョン番号を指定しないで済むようにしたいので
ドラフト状態のものをまとめてhg stripできないものかなあという感じです。


> finish, promote あたりに適用すれば十分かな? 
自分の場合は、そうです。

finish, promote だけでも hg flow rollback できると
便利そうで hgflowの機能拡張要望だそうかとも思うのですが、
hg strip でやるのが筋なのかなあと。。

やっぱり現実的には hg strip でしょうか。

> とは言え、現状の hgflow の実装は、finish 等による上流へのマージの 
> 前に、予め feature ブランチ側で衝突解消済みと仮定しているみたいで 
> すから、そもそもこの辺の心配は無用なのかな? 
単純な使用例では、そのように見える例が使われることが多いと思いますが、
featureブランチ側で衝突解消済みという仮定はしていないはずです。

hg flow が絶大な効果を発揮するのは、複数グループによる並行開発の
場合と考えます。
そのような並行開発の場合、featureブランチ以外で
衝突解消済することがよくあると思います。

Katsunori FUJIWARA

unread,
Nov 1, 2016, 7:02:10 AM11/1/16
to mercurial-ja
藤原です。

2016年11月1日 17:22 ohira <shin....@gmail.com>:

> おおひらです。
>
> 回答ありがとうございます。
>
> やっぱり現実的には hg strip でしょうかね。
>
>> 一度の hg flow 実行に起因する複数の内部的 commit の成果を、hg
>> rollback で一括破棄すること自体は可能です。
> それ用にエクステンションを作るとできるようになるのですね。
>
>
>> なお、Mercurial はコマンド実行横断のトランザクションはサポートして
>> いません。ですので、仮に再開機能が実装されたとしても、衝突解消を含
>> んだ一連の操作を rollback の機能で一括破棄することはできません。
>>
>> この場合は strip の利用が必須になります。
> finish時に定型的に複数行のhg flow を実行することになるので
> 複数行のhg flowが無かったことにできると嬉しいです。
>
>
> hg strip <リビジョン番号> で可能ですが、
> リビジョン番号を指定しないで済むようにしたいので
> ドラフト状態のものをまとめてhg stripできないものかなあという感じです。

「ドラフト状態のものをまとめてhg strip」だけの機能であれば:

$ hg strip "roots(draft())"

という手もありますが、「ドラフト状態」は通常だと「未 push なローカ
ルコミット」が全て含まれますから、運用上本当に安全か?と言うと、個
人的にはかなり懐疑的かなぁ……

まぁ、strip 対象自体はバックアップが残るようになってますから、最悪
でも何とかなると言えば何とかなりますが (^ ^ ;;;)


>> finish, promote あたりに適用すれば十分かな?
> 自分の場合は、そうです。
>
> finish, promote だけでも hg flow rollback できると
> 便利そうで hgflowの機能拡張要望だそうかとも思うのですが、

要望を出してみるのは大事だと思いますよ!


> hg strip でやるのが筋なのかなあと。。
>
> やっぱり現実的には hg strip でしょうか。

あるいは:

- finish/promote 前に local tag (例: "FLOWBASE") を作成

既に作成済みの場合は、前回の finish/promote のものなの
で、--force 付きで強制上書き

- flow rollback の際に FLOWBASE + 1 なリビジョン番号と、その子孫
を strip

みたいな手順をエイリアス等で実現すれば、当該リビジョンの指定を省略
できそうではあります。


>> とは言え、現状の hgflow の実装は、finish 等による上流へのマージの
>> 前に、予め feature ブランチ側で衝突解消済みと仮定しているみたいで
>> すから、そもそもこの辺の心配は無用なのかな?
> 単純な使用例では、そのように見える例が使われることが多いと思いますが、
> featureブランチ側で衝突解消済みという仮定はしていないはずです。
>
> hg flow が絶大な効果を発揮するのは、複数グループによる並行開発の
> 場合と考えます。
> そのような並行開発の場合、featureブランチ以外で
> 衝突解消済することがよくあると思います。

--
----------------------------------------------------------------------
FUJIWARA Katsunori(flying...@gmail.com)
Reply all
Reply to author
Forward
0 new messages