#language ja #pragma section-numbers 2 = Mercurial を理解する = 新規ユーザは Mercurial の分散開発モデルに混乱するかもしれません。このページでは、いくつかの基本概念を解説しようと思います。 順を追った説明は [[JapaneseTutorial|チュートリアル]] を参照してください。 <> == リポジトリにあるもの == Mercurial の [[Repository|リポジトリ]] には store と連動した [[WorkingDirectory|作業ディレクトリ]] があります: {{{#!dot digraph G { rankdir = LR; compound=true; background="#999999"; subgraph cluster_0 { label="working directory"; style=filled; color=lightgrey; node [style=filled,color=white]; edge [style=invis]; "main.c" -> "main.h" -> ".hgignore" -> ".hgtags"; } subgraph cluster_1 { label = "store"; labelloc = b; style=filled; color="#eeeeee"; node [shape=box, style=filled, color=lightgray]; "rev 0" -> "rev 1" -> "rev 2" -> "rev 3" [dir=back, label="parent"]; } "main.c" -> "rev 2" [ltail=cluster_0, label="parent", labeldistance=5, minlen=2]; } }}} store は、プロジェクトの'''完全な'''履歴を格納しています。唯一中央にのみ履歴のコピーを持つ旧来の SCM 類と異なり、全ての作業領域ディレクトリは、履歴のプライベートなコピーを持っています。これにより、開発を並列に行うことが出来ます。 作業領域ディレクトリは、指定された時点 (例えば rev 2) におけるプロジェクトファイルのコピーを持っており、それらを編集することが出来ます。[[Tag|タグ]] や [[.hgignore|無視するファイル]] に関する設定もリビジョン管理されているので、それらの情報も含まれています。 == 変更のコミット == [[Cmd:commit|コミット]] の際には、 parent (親) に対する作業ディレクトリの状態が、新しい [[ChangeSet|チェンジセット]] として記録されます。(新しい "[[Revision|リビジョン]]" とも言います): {{{#!dot digraph G { compound=true; rankdir = LR background="#999999"; subgraph cluster_0 { label="working directory"; style=filled; color=lightgrey; node [style=filled,color=white]; edge [style=invis]; "main.c"-> "main.h" -> ".hgignore" -> ".hgtags" } subgraph cluster_1 { label = "store"; labelloc = b; style=filled; color="#eeeeee"; node [shape=box,style=filled,color=lightgray]; "rev 0" -> "rev 1" -> "rev 2" -> "rev 3" [dir=back]; "rev 2" -> "rev 4" [dir=back]; } "rev 2" -> ".hgtags" [dir=back, style=dotted, lhead=cluster_0, label="parent before commit"] "rev 4" -> ".hgtags" [dir=back, color=red, lhead=cluster_0, headlabel="commit", labelfontcolor=red ] } }}} rev 4 は、作業領域ディレクトリの (parent) リビジョンであった rev 2 に対する'''[[Branch|ブランチ]]'''である点に注意してください。'''コミット'''により、rev 4 がその時点での作業領域ディレクトリの '''parent''' リビジョンになります。 == リビジョン、チェンジセット、head および tip == Mercurial は、複数のファイルに対する関連する変更を、単一不可分な'''[[ChangeSet|チェンジセット]]'''に分類し、これらがプロジェクト全体における'''リビジョン'''となります。これらはそれぞれ一連の[[RevisionNumber|リビジョン番号]]を持ちます。Mercurial は分散並行開発を許容しているので、ユーザー間でこれらの番号が食い違う可能性があります。そのため、Mercurial は各リビジョンにグローバルな'''[[ChangeSetID|チェンジセット ID]]'''を割り当てます。チェンジセット ID は 40 桁の 16 進数ですが、"e38487" のように、紛らわしさのない長さまで省略可能です。 {{{#!dot digraph { rankdir = LR node [shape=record] rev0 [label="{{ p1 | p2} | rev 0:838e}"]; rev1 [label="{{ p1 | p2} | rev 1:34ef}"]; rev2 [label="{{ p1 | p2} | rev 2:4563}"]; rev3 [label="{{ p1 | p2} | rev 3:fe56}"]; rev4 [label="{{ p1 | p2} | rev 4:ac98}"]; rev5 [label="{{ p1 | p2} | rev 5:0345}"]; rev6 [label="{{ p1 | p2} | rev 6:19e3 (tip)}"]; workingdir [label="{{ p1 | p2} | working directory}"]; rev0 -> rev1:p1 [dir=back] rev1 -> rev2:p1 [dir=back] rev1 -> rev3:p1 [dir=back] rev2 -> rev4:p1 [dir=back] rev3 -> rev4:p2 [dir=back] rev4 -> rev5:p1 [dir=back] rev4 -> rev6:p1 [dir=back] rev6 -> workingdir:p1 [dir=back] label="example repository" } }}} 履歴中のブランチの分岐や[[Merge|マージ]]は、任意の時点で発生し得ます。マージされない個々のブランチは、履歴中に新規の[[Head|head]]を形成します。 この例では rev 5 および rev 6 が head です。Mercurial は、最もリビジョン番号の大きい head として、rev 6 をリポジトリの [[Tip|tip]] とみなします。 リビジョン 4 は [[MergeChangeset|マージ チェンジセット]] で、 parent チェンジセットが ''2 つ'' あります。(リビジョン 2 と 3) == 複製、変更、マージ pull および更新 == Alice に以下のようなリポジトリがあるとしましょう: {{{#!dot digraph { label="Alice's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> "working dir" [dir=back] } }}} Bob がこのリポジトリを複製 (clone)すると、 Alice の store の完全なコピーを得ることが出来、作業コピーには最も新しいリビジョン d がそのままチェックアウトされます: {{{#!dot digraph { label="Bob's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> "working dir" [dir=back] } }}} Bob は Alice と無関係に作業を進められるようになり、 e と f の変更をコミットしました: {{{#!dot digraph { label="Bob's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> e -> f -> "working dir" [dir=back] e [color=blue] f [color=blue] } }}} 一方 Alice は独自に g という変更を加えました。 これで Alice のリポジトリ store は Bob から枝分かれし、 [[Branch|ブランチ]] ができたことになります: {{{#!dot digraph { label="Alice's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> g -> "working dir" [dir=back] g [color=red] } }}} ここで Bob は Alice のリポジトリを pull し、同期を取ります。 Alice の変更点が全て Bob のリポジトリ store へコピーされます。(ここでは、 g の変更だけです。) Bob の作業ディレクトリは pull によって変更 '''されない''' ことに注意しましょう: {{{#!dot digraph { label="Bob's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> e -> f -> "working dir" [dir=back] e [color=blue] f [color=blue] d -> g [dir=back] g [color=red, label="g (tip)"] } }}} Alice の '''g''' が Bob のリポジトリにおける最新の head なので、この時点で '''g''' が '''tip''' となります。 ここで Bob が [[Merge|マージ]] すると、 Bob が作業していた最新の変更 (f) とリポジトリの tip が結合されます。 作業コピーには 2 つの parent リビジョン (f と g) ができました: {{{#!dot digraph { label="Bob's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> e -> f [dir=back] e [color=blue] f [color=blue] d -> g [dir=back] g [color=red] f -> "working dir" [dir=back, weight=3.0] g -> "working dir" [dir=back, weight=3.0] } }}} 作業コピーのマージ結果を調べて、マージが完璧だと確認したら、Bob は結果をコミットし、 [[MergeChangeset|マージ チェンジセット]] h が Bob の store にできます: {{{#!dot digraph { label="Bob's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> e -> f [dir=back] e [color=blue] f [color=blue] d -> g [dir=back] g [color=red] f -> h [dir=back, weight=3.0] g -> h [dir=back, weight=3.0] h -> "working dir" [dir=back] h [color=green, label="h (tip)"] } }}} ここで Alice が Bob から '''pull''' したら、 Bob の e, f, h の変更が Alice の store へ取り込まれます: {{{#!dot digraph { label="Alice's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> e -> f [dir=back] e [color=blue] f [color=blue] d -> g [dir=back] g [color=red] f -> h [dir=back, weight=3.0] g -> h [dir=back, weight=3.0] g -> "working dir" [dir=back] h [color=green;label="h (tip)"] } }}} Alice の作業ディレクトリは pull によって変化しないことに注意しましょう。 作業ディレクトリをマージチェンジセット h へ同期するには、 [[Update|更新 (update)]] する必要があります。 これで、作業ディレクトリの parent チェンジセットが h へ変わり、リビジョン h の内容へ作業ディレクトリのファイルが更新されます。 {{{#!dot digraph { label="Alice's repo" rankdir = LR node [shape=box] a -> b -> c -> d -> e -> f [dir=back] e [color=blue] f [color=blue] d -> g [dir=back] g [color=red] f -> h [dir=back, weight=3.0] g -> h [dir=back, weight=3.0] h -> "working dir" [dir=back] h [color=green, label="h (tip)"] } }}} さぁ、再び Alice と Bob はすっかり同期が取れました。 == 分散型システム == Mercurial は完全な非集中型のシステムですので、中央リポジトリといった内部概念がありません。そのため、変更を共有するための伝播経路を、ユーザが自由に定めることができます。 (CommunicatingChanges 参照): {{{#!dot digraph { Alice -> Central Central -> Alice Bob -> Central Alice -> Bob Alice -> Carl Carl -> Central Bob -> Carl Carl -> Bob "Carl's Laptop" -> Carl Carl -> "Carl's Laptop" "Carl's Laptop" -> Central Central [style=fill;color=blue;label="Main Public Repo"] label="A Mercurial Network" } }}} 集中バージョン管理システムでは実験が面倒なことになりがちですが、 Mercurial のような DVCS では、 clone して試してみるだけです。 結果が気に入れば逆に pull し直し、そうでなければ clone したリポジトリをきれいさっぱり忘れて別のことを試せばよいのです。 == Mercurial ができること == SVN や CVS ユーザーは、関連するプロジェクトをひとつのリポジトリへまとめがちです。 これは Mercurial には全くそぐわないため、別の方法でやってみなければなりません。 具体的に言うと、リポジトリのディレクトリひとつだけをチェックアウトできないということです。 どうしても複数のプロジェクトをメタリポジトリのような形で提供する必要があるなら、 [[Subrepository|サブリポジトリ]] 機能を使ってみると良いでしょう。 Mercurial 1.3 より古い場合は、 ForestExtension を検討してください。 Mercurial 利用に関する実践的な入門は、 [[JapaneseTutorial|チュートリアル]] を参照してください。 ## 訳注: ## ## 履歴情報を格納する store は、単なる「格納領域」以上のニュアンスがあるため、 ## 原文の表記をそのまま残しました。 ## ## CVS や Subversion といった他の SCM ツールによって、 既に一般化したと思われる語 ##(e.g.: branch、commit、merge 等)に関してはカタカナ表記としましたが、 ## Mercurial 固有の(あるいはコマンド名を意識した)ものに関しては、 ## 原文の表記をそのまま残しました(e.g.: parent、head、tip 等)。 ---- [[BrazilianPortugueseUnderstandingMercurial|Brazilian Portuguese]], [[CzechUnderstandingMercurial|Czech]], [[GermanUnderstandingMercurial|Deutsch]], [[UnderstandingMercurial|English]], [[FrenchUnderstandingMercurial|Français]], [[ItalianUnderstandingMercurial|Italiano]], [[RussianUnderstandingMercurial|Russian]], [[SpanishUnderstandingMercurial|Spanish]], [[ThaiUnderstandingMercurial|Thai]], [[ChineseUnderstandingMercurial|中文]], [[KoreanUnderstandingMercurial|한국어]]