Differences between revisions 1 and 6 (spanning 5 versions)
Revision 1 as of 2008-11-08 13:57:28
Size: 5118
Editor: AkiraKitada
Comment:
Revision 6 as of 2009-05-19 19:31:01
Size: 15917
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
=== 自分がチェックアウトしたリビジョンが分からなくなりました ===

[[Parent|parent]] コマンドを使いましょう([[TutorialClone]] で使用例を見れます)。
  訳注: [[JapaneseTutorialClone|日本語版TutorialClone]]では未訳のようです。

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

MercurialIni を見てください。

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

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

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

もし、こんな風にしてリモートリポジトリをcloneしたとして、
{{{
  hg clone ssh://USER@REMOTE/path/to/repo
}}}

そして、sshの認証に成功した後で'''remote: abort: There is no Mercurial repository here (.hg not found)!'''というエラーメッセージが出てきたのなら、あなたは次の項目を知っておくべきでしょう。
 * Mercurialのリモート [[Repository|リポジトリ]] 指定文法は、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によって使用される環境で`PATH`に`hg`コマンドが無い事です。この問題に対処するには次の2つの方法があります。
 * `~/.hgrc`の`[ui]`セクションで、`remotecmd`に`hg`コマンドへの正確なパスを設定します。
 * サーバ上で、適切な`PATH`を定義する`~/.ssh/environment`ファイルを作成し、`/etc/sshd_config`に`PermitUserEnvironment yes`を加えます。

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

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

{{{
[web]
push_ssl = false
}}}

しかしながら、SSLが必要とされるのはそれなりの理由があります。使用しているネットワーク経路が信頼出来ないのなら、この変更を'''行わないで'''ください。
Line 19: Line 60:
=== hg statusで見ると変更有りなのに、hg diffだと変更無しです! ===

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

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

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

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

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

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

{{{
$ hg rollback
rolling back last transaction
}}}

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

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

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

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

もし既に公開[[Repository|リポジトリ]]に変更をpushしてしまっていて、みんながそこから[[Clone|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 を見てください。
Line 59: Line 137:

=== どうにかして、リモートサーバにhg pushすると自動的にhg updateされるようになりませんか? ===
{{{
[hooks]
changegroup = hg update >&2
}}}

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

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

URLの中でユーザ名とパスワードを指定する事が出来ます。
{{{
http://user:password@mydomain.org
}}}

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


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

出来ません。 Mercurialが-Rオプションで受け付けるのは、ローカル[[Repository|リポジトリ]]だけです({{{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|clone]]して、ローカルに{{{hg log}}}する事です。

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

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

リモート[[Repository|リポジトリ]]に有る [[Tip|最先端]]な[[ChangeSet|チェンジセット]]の[[ChangeSetID|チェンジセットid]]を取得するにはこうします。

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

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

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

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

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

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

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

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

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

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

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


=== 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|.hgrc]]でフックを設定する事です。push時にリモート側で [[Hook#tmpdirhook|テンポラリディレクトリを変更する為のフック]]を設定する方法の説明を見てください。

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

parent コマンドを使いましょう(TutorialClone で使用例を見れます)。

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

MercurialIni を見てください。

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

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

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を加えます。

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

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

[web]
push_ssl = false

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

もしコミットしたばかりで、その後まだ他のいかなるコミットや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 を見てください。

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

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

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

コミットしたときにメールを出したい

CommitHook を見てください。

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

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

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

printf ".*\n" > .hgignore

としてもかまいません。

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

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

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

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

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

[hooks]
changegroup = hg update >&2

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

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

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

http://user:password@mydomain.org

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

リモートリポジトリに対して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 も見てください。

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

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

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

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

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

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

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

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

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

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

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

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

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

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時にリモート側で テンポラリディレクトリを変更する為のフックを設定する方法の説明を見てください。

JapaneseFAQ/CommonProblems (last edited 2009-09-14 12:55:01 by YuyaNishihara)