このページは FAQ の翻訳です。まだ不完全ですので適当に修正してください。

Mercurialよくある質問

便利なワザも参照してください)

Contents

  1. 全般的な質問
    1. プロジェクトのライセンスは?
  2. 用語
    1. リビジョンナンバー、ChangeSetID、タグとは何か?
    2. clone、pull、pushとは何?
    3. branches、heads、tip とは何?
  3. 基本的な使い方
    1. マージはどのようにするの?
    2. Mercurialで分散開発をするためのベストプラクティスは?
    3. 他のSCMで作ったリポジトリからインポートするにはどうすれば良いですか?
    4. Windowsでのサポートは?
    5. GUI フロントエンドはありますか?
  4. タグについて
    1. タグはMercurial上ではどう使うの?
    2. ローカルなタグを作りたいんだけど
    3. headが複数ある場合tagはどうなるの?
    4. ブランチタグはどうやれば使える?
  5. 一般的な問題
    1. 自分がチェックアウトしたリビジョンが分からなくなりました
    2. Mercurialで設定を変えられるのはどこですか?
    3. ユーザ名を変更するには?
    4. ssh経由でリモートリポジトリをcloneしようとしたらエラーが出ます
    5. 変更をpushしようとしたら、"ssl required"というエラーメッセージが出ます
    6. hg pullとしたのにワーキングディレクトリはからっぽのままです
    7. 古いバージョンに戻したいのですが、どうすればよいですか?
    8. hg statusで見ると変更有りなのに、hg diffだと変更無しです!
    9. hg exportやlog -pが、私が行ったマージについておかしなdiffを出力します!
    10. revertでワーキングディレクトリを戻したのですが完全には戻りません
    11. からっぽのきれいなワーキングディレクトリが欲しい
    12. 核攻撃を行うコードを含んだ変更をコミットしてしまいました。それを恒久的に削除するにはどうしたらいいですか?
    13. デカいバイナリファイルをコミットしてしまいました。どうすれば完全に消せますか?
    14. からっぽのディレクトリをaddしようとしたがうまくいきません
    15. コミット時にメールして欲しい
    16. 多くのファイルのあるディレクトリのなかで少数のファイルだけをMercurialの管理下に置きたい(例えば ~/ )が、diffやcommitに時間がかかる
    17. 何故ファイルのmtimeがチェックアウト時に元に(訳注:コミット時のものに?)戻さないの?
    18. どうにかして、リモートサーバにhg pushすると自動的にhg updateされるようになりませんか?
    19. HTTPのログイン情報を一度設定すれば毎回適用されるように出来ませんか?
    20. リモートリポジトリに対してhg logするには、どうやればいいの?
    21. リモートリポジトリに新しいチェンジセットが来ているかどうかは、どうやって調べるの?
    22. 要らなくなったheadはどうしたらいいんでしょうか?
    23. cloneコマンドが誤ったバージョンを返します!
    24. ファイルの所有者やパーミッションをバージョン管理する方法は?
    25. push実行時に、"no space left"とか"disk quota exceeded"とか出てきます
  6. バグや新機能
    1. バグを見つけたけど、どうすれば良い?
    2. バグ報告には何を書けばよい?
    3. Mercurial は <x> できますか?
  7. ウェブインターフェース
    1. あるファイルの最新リビジョンへリンクしたい
    2. ウェブインターフェースのスタイルをより見た目の良いgitwebに変更するにはどうすれば良いですか?
  8. 技術的詳細
    1. Mercurialの限界は?
    2. Mercurialはデータをどのように格納するの?
    3. バイナリファイルの取り扱いはどうなっているの?
    4. Windows式改行とUnix式の改行の違いはどう?
    5. キーワード置き換え(例: $Id$)については?
    6. Mercurialはどのようにして差分を計算している?
    7. manifestやチェンジセットをどのように格納している?
    8. ハッシュ値はどのように計算している?
    9. リポジトリの完全性をどのように調べている?
    10. Mercurialにおける署名はどうなっている?
    11. ハッシュ値は衝突しない? SHA1の脆弱性はどうなの?
    12. How does "hg commit" determine which files have changed?
    13. What is the difference between rollback and strip?

1. 全般的な質問

1.1. プロジェクトのライセンスは?

ライセンス を見てください。

2. 用語

2.1. リビジョンナンバー、ChangeSetID、タグとは何か?

Mercurialでは基本的に特定のリビジョンを指定するための方法が3つあります。リビジョンナンバー、チェンジセットIDタグとです。

リビジョンナンバーは単なる10進数で、ローカルのリポジトリに何番目にコミットしたかという番号です。この順番はマシンごとに異なるということに十分注意してください。Mercurialは分散型で非集中的な設計になっているからです。

そのためチェンジセットIDが必要になります。チェンジセットIDはチェンジセットおよびチェンジセットの履歴における位置を一意に特定するための160ビットの識別子です。この値はどのマシンでも同じになります。Mercurialユーザに対してはこの値を40文字の16進数の数字として扱います。この形式では扱いずらいため、あいまいでなければ部分文字列を使ってリビジョンを特定することができます。またChangeSetIDを表示する場合、Mercurialは大抵短縮形式と呼ばれるChangeSetIDの先頭12文字を表示します。

他のMercurialユーザとあるリビジョンについて論議する場合、リビジョンナンバーではなくchangeset IDを使うべきです。人のリポジトリとはリビジョンナンバーが異なる可能性があるからです。

最後に、タグとはあるchangeset IDに関連付けられた文字列です。任意に決めることができ、あるリビジョンに名前を付けることができます。

2.2. clone、pull、pushとは何?

他の多くのバージョン管理システムでは、全ての開発者が単一の中央リポジトリにチェンジセットをコミットします。Mercurialでは、それぞれの開発者が典型的には個人リポジトリで作業を行います。Mercurialの基本コンセプトは、リポジトリ間でチェンジセットを授受する事にあります。 これは、clonepushpullといった操作を通じて実現されます(CommunicatingChangesも見てください)。

既存のプロジェクトについて事を始める場合、開発者は通常、hg cloneコマンドを使ってリポジトリのローカルコピーを作ります。この操作は、全ファイルの全履歴を含んだ新しいリポジトリを作成します。

別の開発者が各自の個人リポジトリに変更を加えたら、あなたはhg pullコマンドでその変更を自分のリポジトリに引っ張ってくる事が出来ます。逆に、あなたが自分の個人リポジトリに変更を加えて、それを他のリポジトリ(例えば共有リポジトリ)に受け渡したいなら、hg pushコマンドを使ってそれを実行出来るでしょう。

2.3. branches、heads、tip とは何?

最も単純な状況では、履歴とは一連なりのチェンジセットで成り立っています。この場合、(先頭と末尾を除外して)どのチェンジセットも一つのと一つの子を持ちます。しかし様々な理由によって、履歴のグラフ構造は2つ、またはそれ以上の独立した開発ラインに枝分かれする事が有ります。枝分かれが起こった時、その履歴グラフにはブランチが有る、と表現されるのです。ブランチが発生した箇所では、チェンジセットは2つ、またはそれ以上の子を持ちます。

2つの開発ラインが一つに結合された時は、マージが発生した、と表現されます。マージが発生した箇所では、チェンジセットは2つの親を持ちます。或る開発ラインが未だ他のラインとマージされていない時、そのラインの最新チェンジセットをブランチのheadと呼びます。あらゆるリポジトリは常に一つ、またはそれ以上のheadを包含しています。headは子を持ちません。作業中のリポジトリについてheadを列挙するには、hg headsコマンドを使ってください。

tipとは、リポジトリに加えられた直近のチェンジセットの事です。今コミットを行ったばかりなら、そのコミット内容がtipという事になるでしょう。逆に、他のリポジトリからpullしたばかりであれば、そのリポジトリのtipが作業中のリポジトリの新しいtipになります。リポジトリのtipを表示するには、hg tipコマンドを使ってください。

tipは常にheadでもあります。リポジトリ内に複数のheadが存在する場合、そのうちの一つだけがtipになるのです。リポジトリ内部でチェンジセットは連番をふられているので、tipが最大の連番値を持ちます。"tip"という語は、tipチェンジセットを示す特殊なタグとして機能し、チェンジセットIDやタグが使用可能な全ての場所で使用出来ます。

次のダイアグラムで、紹介してきた概念を図解します。

この履歴では、リビジョン 1:34ef と 4:ac98 でブランチが発生していて、リビジョン 4:ac98 でマージが発生しています。リビジョン 5:0345, 6:19e3, 7:8e92 はheadで、その中で 7:8e92 がtipにあたります。

hg tipがtipを表示し、hg headsがheadを表示するにも拘わらず、hg branchesで表示されるブランチのチェンジセットが、先程の説明でブランチの発生したチェンジセットとして示したものと異なる事に注意してください。代わりにこのコマンドは、名前付きの各ブランチそれぞれの最新のチェンジセットを表示します。詳しくは、名前付ブランチを参照してください。

"branch"という用語には、他の意味も有ります。詳細はブランチを参照してください。


  • 訳注: 以下はこの項目の旧版の内容ですが、参考になるので残しておきます。

ブランチはMercruialの中心的な概念です。ブランチとは独立した開発ラインのことです。他のほとんどのバージョン管理システムでは、すべての開発者が 'trunk'や 'メインブランチ' と呼ばれるものにコミットするのが一般的です。Mercurialでは各開発者が私的なブランチ上で作業するのでMercurial自身は'メインブランチ'という概念を持っていません。

そのためMercurialはブランチ間のマージの繰り返しをを簡単にできるようにしています。hg pullhg update -mを走らせてから結果をコミットするだけでマージができます。

'heads' とはあるブランチの上での最も最近のコミットです。技術的に言えば子をまったく持たないチェンジセットのことです。マージとは2つのheadsを一つにまとめる操作であると言えます。hg headsとすると現在のリポジトリ内のheadsを見ることができます。

'tip'とは最も最近に変更されたheadのことであり、最も大きなリビジョンナンバーを持つチェンジセットのことです。何も指定せずにコミットをすると、それは'tip'に対してなされます。一方、他のリポジトリからpullをすると、そのリポジトリのtipが現在のtipになります。

'tip'はupdateのような多くのコマンドのデフォルトのリビジョンとなりますし、また特別なタグとしても機能します。


3. 基本的な使い方

3.1. マージはどのようにするの?

マージ を参照してください。

3.2. Mercurialで分散開発をするためのベストプラクティスは?

WorkingPractices を参照してください。

まず、マージは頻繁にしましょう。そうすればマージは簡単になりますし、衝突(衝突が起きるのは設計上の非互換な決断が原因であることが多いです)の解決も簡単になります。

次に、ローカルに新しいツリーを作るのを躊躇しないようにしましょう。Mercurialではこの操作は高速で低コストです。良くあるやりかたとしては、income treeとoutgoint treeを作り、異なる作業ごとに作業用ツリーを作るというものです。

以下この項目は翻訳されていません。

3.3. 他のSCMで作ったリポジトリからインポートするにはどうすれば良いですか?

ConvertingRepositories を参照してください。

3.4. Windowsでのサポートは?

WindowsInstall を参照してください。

3.5. GUI フロントエンドはありますか?

グラフィカルなマージツールやその他フロントエンドについては、 OtherTools を参照してください。

4. タグについて

4.1. タグはMercurial上ではどう使うの?

タグはMercurialと他のSCMではちょっと違いがあります。Mercurialでは以下の目標があります。

  • ファイルのようにタグをバージョン管理したい
  • マージもしたい
  • タグに署名をしたい
  • すでにコミットしたチェンジセットにタグを付けたい
  • タグを後で変更できるようにしたい

そのためMercurialではタグをワーキングディレクトリの.hgtagsというファイルに格納します。.hgtagsにはチェンジセットIDとそれに対応付けられたタグのリストが書かれています。タグを追加すると、Mercurialは.hgtagsに一行追加してコミットします。hg tagはこのような動作をします。hg tagsは現在有効なタグを表示します。

タグはチェンジセットIDを参照し、チェンジセットIDは事実上対応する変更に関するリポジトリ内の内容すべてを指しているわけですから、コミットとタグ付けを同時に行うことはできません。コミットしてからタグを付ける必要があります。

4.2. ローカルなタグを作りたいんだけど

hg tagコマンドで-lもしくは--localオプションを付けましょう。こうするとタグは.hg/localtagsに収められ、バージョン管理下に入らず、他のリポジトリに影響を与えることもなくなります。このファイルの形式は.hgtagsとまったく同じであり、ローカルタグも普通のタグと同じように扱えます。

4.3. headが複数ある場合tagはどうなるの?

まだ翻訳されていません。

4.4. ブランチタグはどうやれば使える?

CVS式のブランチタグはMercurialのような分散SCMでは意味がありません。すべてがブランチだからです。というわけで大抵のMercurialユーザはブランチごとに異なるリポジトリを持ちます。しかし複数のブランチを1つのリポジトリで使いたいのであれば、うまく工夫することで普通のタグをブランチタグのように使えます。

タグは直接的にはある特定のリビジョンのみを指しますが、そのリビジョンがあるブランチのheadを特定するのにも使えます。それぞれのheadに関連付けられたタグを見るためには、hg heads -hとしてください。あるタグに関連付けられたブランチのheadをチェックアウトしたい場合は、hg update -b tagnameが使えます。

あるタグが示すリビジョンから分岐して、そこからもう一度マージをする前であれば、複数のブランチのheadがその同じタグで参照されることになる可能性があることに注意してください。この場合Mercurialは文句を言うので、指定したいリビジョンを直接指定してください。

ある一つのヘッドが異なるブランチ上の互いに関係ない複数のタグに関連付けられる場合もありえますが、通常問題にはなりません。

5. 一般的な問題

5.1. 自分がチェックアウトしたリビジョンが分からなくなりました

parent コマンドを使いましょう。 (JapaneseTutorialClone に使用例があります。)

5.2. Mercurialで設定を変えられるのはどこですか?

MercurialIni を見てください。

5.3. ユーザ名を変更するには?

コミット時にhgがNo username found, using 'user@hostname instead'と出力するようなら、ユーザ名設定を行う必要があります。詳細は クィックスタート を参照してください。

5.4. ssh経由でリモートリポジトリをcloneしようとしたらエラーが出ます

もし、こんな風にしてリモートリポジトリをcloneしたとして、

  hg clone ssh://USER@REMOTE/path/to/repo

そして、sshの認証に成功した後でremote: abort: There is no Mercurial repository here (.hg not found)!というエラーメッセージが出てきたのなら、あなたは次の項目を知っておくべきでしょう。

  • Mercurialのリモート リポジトリ 指定文法は、rsync, cvsといった他のよく知られたプログラムとは異なります。それらはどちらとも、 USER@REMOTE とパス指定部分との区切りに:文字を使います。

  • リモートリポジトリのパスは USER$HOME からの相対パスとして扱われます。即ち、上の例では  ~USER/path/to/repo  です。

    • 訳注: もし絶対パスで指定するのを意図していたのなら、この例は  hg clone ssh://USER@REMOTE//path/to/repo  となります。

  • hg -v clone ssh://USER@REMOTE/path/to/repo を使って、sshチャネル経由で実行されるリモート側のコマンドを監視する事も忘れないでください。

一方、もしエラーメッセージがremote: bash: line 1: hg: command not foundなら、問題はsshによって使用される環境でPATHhgコマンドが無い事です。この問題に対処するには次の2つの方法があります。

  • ~/.hgrc[ui]セクションで、remotecmdhgコマンドへの正確なパスを設定します。

  • サーバ上で、適切なPATHを定義する~/.ssh/environmentファイルを作成し、/etc/sshd_configPermitUserEnvironment yesを加えます。

5.5. 変更をpushしようとしたら、"ssl required"というエラーメッセージが出ます

ネットワーク経路が信頼出来る場合は、次の内容を<リポジトリ名>/.hg/hgrcに加えて解決出来ます。

[web]
push_ssl = false

しかしながら、SSLが必要とされるのはそれなりの理由があります。使用しているネットワーク経路が信頼出来ないのなら、この変更を行わないでください。

5.6. hg pullとしたのにワーキングディレクトリはからっぽのままです

Mercurialというシステムにはリポジトリとワーキングディレクトリの2つの概念があります。hg pull はリモートリポジトリでの変更をローカルリポジトリに引っ張ってきますがワーキングディレクトリは変更しません。

そのおかげで引っ張ってきた変更をまだマージできずに作業中の状態がめちゃくちゃになるのを防げます。マージもやりやすくなります。

ワーキングディレクトリを更新するには、hg updateを実行してください。pullをするときにワーキングディレクトリも更新したい場合はhg pull -uとします。こうした場合はローカルでの変更をマージしたり上書きしたりはしません。

5.7. 古いバージョンに戻したいのですが、どうすればよいですか?

hg update -C <version>で最新版が上書きされ指定したバージョンに移動します。

hg revert <version>とするとワーキングディレクトの内容は指定したバージョンにまで戻ってしまいますが、次のコミットでのparentは変化しません。revertは現在のバージョンの変更をなかったことにするために使うもので、古いバージョン上で作業するためには使えません。

(訳注:hg update -Cではワーキングディレクトリの内容とparentの両方が変化しますが、hg revert <version>ではワーキングディレクトリの内容は変わりますがparentはもとのままです)

5.8. hg statusで見ると変更有りなのに、hg diffだと変更無しです!

hg status は、ファイルの 内容 または フラグが、いずれかの parentと比較して変更が有った時に出力を行います。hg diffは、内容が最初のparentと比較して変更が有った時のみ出力を行います。 hg diff--gitオプションを付けるとフラグ情報を見れますし、-rオプションで他のparentとの差分も見る事が出来ます。

5.9. hg exportやlog -pが、私が行ったマージについておかしなdiffを出力します!

hg diffhg exporthg logが出力するdiffは、一貫性を保つ為に、常に最初のparentに対しての差分を表示します。 また、両方のparentに対して変更の有ったファイルだけが列挙されます。

(マージのdiffは本当に常に最初のparentと比較されるのでしょうか? hg exportには--switch-parentオプションが有るのでは? hg diffhg logにそのオプションが無い論理的根拠がドキュメントに示されていれば良かったのですが。)

5.10. revertでワーキングディレクトリを戻したのですが完全には戻りません

多分hg update -mをしたのでしょう。つまりhg parentsで見られるparentが2つになっていませんか。hg revertではワーキングディレクトリをprimary parentに戻すので、2つの親の間で異なる部分は戻されません。hg update -Cで完全に戻ります。

リビジョン間を移動したい場合はきっとhg update -Cが有用でしょう。

5.11. からっぽのきれいなワーキングディレクトリが欲しい

一番簡単な方法はhg clone -Uを使うことです。こうすると新しい複製を作りますがワーキングディレクトリ上には何も置かれません。

: hgrcをもとのリポジトリからコピーしたほうが良いかもしれません。

5.12. 核攻撃を行うコードを含んだ変更をコミットしてしまいました。それを恒久的に削除するにはどうしたらいいですか?

もしコミットしたばかりで、その後まだ他のいかなるコミットやpullを実行していないのなら、最後のコミットトランザクションを取り消す為にrollbackコマンドを使う事が出来ます。

$ hg rollback
rolling back last transaction

もし他のコミット等の変更を加えてしまっていたとしても、まだ世間に公開していないなら、次のような手が有ります。

$ hg clone -r <まだ汚染されていないリビジョン> 汚染されたリポジトリ 汚染されていないリポジトリ

mq extensionの中のstripコマンドも、この場面での操作では有用でしょう。

この操作を行えば、汚染された変更とそれに続く変更を取り除いた新しいリポジトリが得られます。hg exporthg importを使うか、 TransplantExtension を使って、汚染された後にコミットされた変更を取り込む事も出来ます。あと何が出来るかは、 TrimmingHistory を見ましょう。

もし既に公開リポジトリに変更をpushしてしまっていて、みんながそこからcloneしてしまったのなら、魔物は瓶から解き放たれました。落とし前を付けられるといいですね。

“Judge Tries to Unring Bell Hanging Around Neck of Horse Already Out of Barn Being Carried on Ship That Has Sailed.” - William G. Childs

さらに詳細は EditingHistory を見てください。

5.13. デカいバイナリファイルをコミットしてしまいました。どうすれば完全に消せますか?

追加してはいけなかったファイルを削除したければ、 ConvertExtension--filemap オプションを用いて Mercurial リポジトリを別の Mercurial リポジトリへ変換 "convert" してください。 You'll want to make sure that you set convert.hg.saverev=False if you want to keep in common the history prior to your removed file(s). If convert.hg.saverev=True, the conversion embeds the source revision IDs into the new revisions under an extra header, visible if via hg log --debug.

別の方法については、一つ前の質問を参照ください。

5.14. からっぽのディレクトリをaddしようとしたがうまくいきません

Mercurialではディレクトリの履歴を管理しません。ファイルのみ管理します。普通は問題ないのですが、ファイルを1つも持たないディレクトリは取り扱えません。からっぽのディレクトリはそう便利というものでもなく、実装が複雑になりかねないのですぐに修正するつもりはありません。以下のような解決策を用いてください:

  • "this-dir-intentionally-left-blank" のようなファイルを追加する
  • Makefileなどのビルドプロセスでディレクトリを生成する

5.15. コミット時にメールして欲しい

NotifyExtension を使ってください。

5.16. 多くのファイルのあるディレクトリのなかで少数のファイルだけをMercurialの管理下に置きたい(例えば ~/ )が、diffやcommitに時間がかかる

printf "syntax: glob\n*\n" > .hgignore

とするか、もしくは 0.7 以降であれば

printf ".*\n" > .hgignore

としてもかまいません。

こうするとhgコマンドは明示的にファイルを追加しない限りすべてのファイルを無視します。

5.17. 何故ファイルのmtimeがチェックアウト時に元に(訳注:コミット時のものに?)戻さないの?

makeやdistutilsのようなビルドツールを使う場合、古いリビジョンにupdateするとそれらのツールによるファイルの更新がうまくいかないかもしれないという問題があるからです。さらに新しいほうのチェンジセットのほうがタイムスタンプが古い可能性もあります、というのは他のリポジトリからのpullや人からのパッチをimportした場合、リポジトリから取り出した 新しいチェンジセットのせいでタイムスタンプが 古く なってしまうかもしれないからです。

(訳注:以下の訳はかなり怪しい) hg archiveを使うと、別のディレクトリにチェックアウトするようなことができます。これでタイムスタンプを制御できます。このディレクトリは新しく作られるので、後から別のチェンジセットに切り替えられたりすることがなく、上で挙げたような問題は生じません。

5.18. どうにかして、リモートサーバにhg pushすると自動的にhg updateされるようになりませんか?

[hooks]
changegroup = hg update >&2

リモートリポジトリの.hg/hgrcにこう書くとうまくいきます。 出力は標準エラー出力(か/dev/null)にリダイレクトされなければいけません。標準出力はデータのストリームに使われますので。

5.19. HTTPのログイン情報を一度設定すれば毎回適用されるように出来ませんか?

URLの中でユーザ名とパスワードを指定する事が出来ます。

http://user:password@mydomain.org

これをhgrcファイルの中のpathsセクションに新しいエントリとして追加します。

5.20. リモートリポジトリに対してhg logするには、どうやればいいの?

出来ません。 Mercurialが-Rオプションで受け付けるのは、ローカルリポジトリだけです(hg help -v log参照)。

> hg log -R http://www.selenic.com/repo/hello
abort: repository 'http://www.selenic.com/repo/hello' is not local

正しいやり方は、リモートリポジトリを手元のマシンにcloneして、ローカルにhg logする事です。

これはプロジェクトリーダーのMatt Mackall (mpm)氏による深慮の上の明確な設計意思決定です。その背後にある根拠については、 http://www.selenic.com/mercurial/bts/issue1025 も見てください。

5.21. リモートリポジトリに新しいチェンジセットが来ているかどうかは、どうやって調べるの?

リモートリポジトリに有る 最先端チェンジセットチェンジセットidを取得するにはこうします。

> hg id -i -r tip http://www.selenic.com/repo/hello
82e55d328c8c

この値が変われば、リモートリポジトリに新しいチェンジセットが来た事になります。

5.22. 要らなくなったheadはどうしたらいいんでしょうか?

死にブランチの枝刈りを見ましょう。

5.23. cloneコマンドが誤ったバージョンを返します!

Clone コマンドはdefault(別名unnamed)ブランチのtipバージョンをチェックアウトします(NamedBranches 参照)。故に、あなたはきっとメインブランチをunnamedのままにしておきたいと思いますよね。

5.24. ファイルの所有者やパーミッションをバージョン管理する方法は?

もしMercurialを設定ファイルの管理に利用しているなら、ファイルのプロパティ(所有者やパーミッション)もバージョン管理したいと思うかもしれません。

これはプロパティをファイルと共に保存する方法の一例です(aclパッケージがインストールされていれば、Linux上で動作します)。

# cd /etc && getfacl -R . >/tmp/acl.$$ && mv /tmp/acl.$$ .acl
# hg commit

この方法は完璧からは程遠いですが、着想点にはなります。さらに洗練されたソリューションを求める場合は、etckeeperをチェックアウトしてください。

5.25. push実行時に、"no space left"とか"disk quota exceeded"とか出てきます

Q: push実行時に、"no space left"とか"disk quota exceeded"とかエラーメッセージが出てくるのですが、リモート側のhgリポジトリを置いている場所には十分な空き容量が有るし、クォータ制限も掛けていないのです。

A: この問題はおそらく、mercurialがネットワーク越しに受信したbundleデータを展開する為に/tmp(或いは $TMPDIR, $TEMP$TMP環境変数で定義されたディレクトリ)を使用する事に起因しています。おそらく、展開処理の中でデバイスの制限値に達するのでしょう。

もちろん、リモート側でデフォルトシェルの設定ファイルを書き換えて$TMPDIRを設定する事も出来ますが、それではmercurial以外のプロセスに影響を与える恐れが有ります。別解はリモート側のグローバル.hgrcでフックを設定する事です。push時にリモート側で テンポラリディレクトリを変更する為のフックを設定する方法の説明を見てください。

6. バグや新機能

6.1. バグを見つけたけど、どうすれば良い?

Mercurialのメーリングリスト ( mercurial@selenic.com ) か バグトラッカ( http://bz.selenic.com/ )に報告してください。

6.2. バグ報告には何を書けばよい?

バグを再現するか特定するのに十分な情報です。できれば、hg -v や hg -d switches を使ってMercurialが正確に何をしているのかを突き止めてください。

簡単なリポジトリでバグを再現できるのであれば、とてもありがいことです。一番良いのはこの過程を自動的に実行する簡単なシェルスクリプトを書くことです。そうすればMercurialのテストに追加できます。

6.3. Mercurial は <x> できますか?

ある機能が欲しいのであれば、メーリングリストに送ってください。Mercurialはまだ新しいため、間違いなく欠けている機能がありますし、どう実装すべきかフィードバックをください。

また、ToDoMissingFeatures を見れば今後の予定やどのような手助けが必要かわかります。

7. ウェブインターフェース

7.1. あるファイルの最新リビジョンへリンクしたい

そのファイルのURLを探して、チェンジセットの部分をtipに置き換えてください。

7.2. ウェブインターフェースのスタイルをより見た目の良いgitwebに変更するにはどうすれば良いですか?

hgrcを次のように設定してください。

[web]
style = gitweb

デフォルトのスタイルに戻す場合は、"style = default"を設定してください。(hgbook).

8. 技術的詳細

8.1. Mercurialの限界は?

Mercurialは現在ファイルやインデックスや マニフェスト は効率のためメモリ内で処理します。

その他、ファイル名の長さやファイルの大きさ、ファイルの内容、ファイル数、リビジョン数には制限はありません。 (see also RepoSamples for the sizes of some example repositories.)

ネットワークプロトコルはビッグエンディアンであると規定されています。

ファイル名は null 文字や改行を含んではいけません。コミッタのアドレスは改行を含むことはできません。

Mercurialは主にUNIX上で開発されているため、他への移植版にUnix的要素が表れることがあります。

Mercurial encodes filenames (see CaseFolding, CaseFoldingPlan, fncacheRepoFormat) when storing them in the repository. Most notably, uppercase characters in filenames are encoded as two characters in the filename in the repository ("FILE""_f_i_l_e").

8.2. Mercurialはデータをどのように格納するの?

The fundamental storage type in Mercurial is a revlog. A revlog is the set of all revisions of a named object. Each revision is either stored compressed in its entirety or as a compressed binary delta against the previous version. The decision of when to store a full version is made based on how much data would be needed to reconstruct the file. This lets us ensure that we never need to read huge amounts of data to reconstruct a object, regardless of how many revisions of it we store.

In fact, we should always be able to do it with a single read, provided we know when and where to read. This is where the index comes in. Each revlog has an index containing a special hash (nodeid) of the text, hashes for its parents, and where and how much of the revlog data we need to read to reconstruct it. Thus, with one read of the index and one read of the data, we can reconstruct any version in time proportional to the object size.

Similarly, revlogs and their indices are append-only. This means that adding a new version is also O(1) seeks.

Revlogs are used to represent all revisions of files, manifests, and changesets. Compression for typical objects with lots of revisions can range from 100 to 1 for things like project makefiles to over 2000 to 1 for objects like the manifest.

8.3. バイナリファイルの取り扱いはどうなっているの?

Core Mercurial tracks but never modifies file content, and it is thus binary safe. See BinaryFiles for more discussion of commands which interpret file content, e.g. merge, diff, export and annotate.

8.4. Windows式改行とUnix式の改行の違いはどう?

See Win32TextExtension for techniques which automatically convert Windows line endings into Unix line endings when committing files to the repository, and convert back again when updating the workspace. This is not default Mercurial behaviour, and requires users to edit their configuration files to turn it on. Adopting this policy on line endings probably implies enabling a hook to prevent non-compliant commits from getting into your repository, which in turn forces people contributing code to enable the extension.

8.5. キーワード置き換え(例: $Id$)については?

See KeywordPlan and KeywordExtension.

8.6. Mercurialはどのようにして差分を計算している?

Mercurial の diff は従来の diff アルゴリズムとは異なる方法で計算されます(もちろん出力は完全に互換です)。アルゴリズムは Python の difflib をベースにして C 言語に最適化されており、データサイズを最小化することよりも人が読みやすい diff を生成することに重点を置いています。このアルゴリズムは内部的なデルタ圧縮(delta compression)にも使用されています。

デルタ圧縮アルゴリズムについて詳しく調べた経緯は、ベンチマークによるとこの実装が他よりシンプルかつ高速で、従来の diff アルゴリズムの理論値より小さな差分を生成ことがわかったからです。 これは従来のアルゴリズムが挿入・削除・不変な要素に対して同じコストがかかると仮定しているためです。

8.7. manifestやチェンジセットをどのように格納している?

A manifest is simply a list of all files in a given revision of a project along with the nodeids of the corresponding file revisions. So grabbing a given version of the project means simply looking up its manifest and reconstructing all the file revisions pointed to by it.

A changeset is a list of all files changed in a check-in along with a change description and some metadata like user and date. It also contains a nodeid to the relevant revision of the manifest.

8.8. ハッシュ値はどのように計算している?

Mercurial hashes both the contents of an object and the hash of its parents to create an identifier that uniquely identifies an object's contents and history. This greatly simplifies merging of histories because it avoid graph cycles that can occur when a object is reverted to an earlier state.

All file revisions have an associated hash value (the nodeid). These are listed in the manifest of a given project revision, and the manifest hash is listed in the changeset. The changeset hash (the changeset ID) is again a hash of the changeset contents and its parents, so it uniquely identifies the entire history of the project to that point.

8.9. リポジトリの完全性をどのように調べている?

Every time a revlog object is retrieved, it is checked against its hash for integrity. It is also incidentally doublechecked by the Adler32 checksum used by the underlying zlib compression.

Running 'hg verify' decompresses and reconstitutes each revision of each object in the repository and cross-checks all of the index metadata with those contents.

But this alone is not enough to ensure that someone hasn't tampered with a repository. For that, you need cryptographic signing.

8.10. Mercurialにおける署名はどうなっている?

Take a look at the hgeditor script for an example. The basic idea is to use GPG to sign the manifest ID inside that changelog entry. The manifest ID is a recursive hash of all of the files in the system and their complete history, and thus signing the manifest hash signs the entire project contents.

8.11. ハッシュ値は衝突しない? SHA1の脆弱性はどうなの?

The SHA1 hashes are large enough that the odds of accidental hash collision are negligible for projects that could be handled by the human race. The known weaknesses in SHA1 are currently still not practical to attack, and Mercurial will switch to SHA256 hashing before that becomes a realistic concern.

Collisions with the "short hashes" are not a concern as they're always checked for ambiguity and are still long enough that they're not likely to happen for reasonably-sized projects (< 1M changes).

See also: http://selenic.com/pipermail/mercurial/2009-April/025526.html by Matt Mackall.

8.12. How does "hg commit" determine which files have changed?

If hg commit is called without file arguments, it commits all files that have "changed" (see Commit). Note however, that Mercurial doesn't detect changes that do not change the file time or size (This is by design. See also msg3438 in issue618 and DirState).

8.13. What is the difference between rollback and strip?

They overlap a bit, but are really quite different:

  • hg rollback will remove the last transaction.

    • Transactions are a concept often found in databases. In Mercurial we start a transaction when certain operations are run, such as commit, push, pull... When the operation finishes succesfully, the transaction is marked as complete. If an error occurs, the transaction is "rolled back" and the repository is left in the same state as before.

      You can manually trigger a rollback with hg rollback. This will undo the last transactional command. If a pull command brought 10 new changesets into the repository on different branches, then hg rollback will remove them all.

      Please note: there is no backup when you rollback a transaction!

  • hg strip will remove a changeset and all its descendants.

    • The changesets are saved as a bundle, which you can apply again if you need them back.


CategoryJapanese

JapaneseFAQ (last edited 2009-05-19 19:31:00 by localhost)