先述した『言語設定』が実施されていれば、
日本語でヘルプを参照可能です:
トップページ左側の "help" を選択。
----@
>>> 一人での作業
ファイルに対する操作
----@
>>> 一人での作業
>>> ファイルに対する操作
- 作業領域の全てのファイルの状態表示:
hg status -A
- 管理対象からの除外(ファイルの削除無し):
hg forget
- 管理対象からの除外(ファイルの削除有り):
hg remove
- ファイルの複製:
hg copy
- ファイルの改名:
hg rename
- コミット実施前における、除外/複製/改名の取り消し
ヒント: Mercurial の改名は、
『複製』+『除外(ファイル削除有り)』で実現されています
- 複製/改名元の履歴の参照:
hg log --follow
----@
>>> 一人での作業
直前のコミットの取り消し/やり直し
----@
>>> 一人での作業
>>> 直前のコミットの取り消し
【宿題】
変更内容を一旦コミットした上で、
ロールバック (rollback) 機能を使用して、
直前のコミットを取り消せ。
また、コミットの取り消し前後における、
『親リビジョン』『作業領域状態』を比較せよ。
----@
>>> 一人での作業
>>> 直前のコミットの取り消し/やり直し
【宿題】
変更内容を一旦コミットした上で、
直前のコミットログを変更せよ。
----@
>>> 一人での作業
親リビジョン以外との比較/リビジョン間の比較
----@
>>> 一人での作業
>>> 親リビジョン以外との比較/リビジョン間の比較
【宿題】
離れた2つのリビジョン間における状態の変化を確認せよ。
※ TortoiseHg では、
"hg status --rev REV [--rev REV2]"
に相当する機能はありません。
----@
>>> 一人での作業
>>> 親リビジョン以外との比較/リビジョン間の比較
【宿題】
離れた2つのリビジョン間における変更内容を参照せよ。
----@
複数リポジトリの利用
----@
>>> 複数リポジトリの利用
リポジトリの複製
----@
>>> 複数リポジトリの利用
>>> リポジトリの複製
Mercurial では、
既存のリポジトリから、
同じ履歴管理情報を持つリポジトリを複製できます。
複製先のリポジトリは、
複製元リポジトリが無くなっても、
単独で機能します。
----@
>>> 複数リポジトリの利用
>>> リポジトリの複製
【演習】
これまで使用してきたリポジトリを元に、
リポジトリを複製せよ
----@
>>> 複数リポジトリの利用
履歴の反映
----@
>>> 複数リポジトリの利用
>>> 履歴の反映
複製先リポジトリでは、
複製元リポジトリとは独立して、
新たな履歴を追加することが可能です。
----@
>>> 複数リポジトリの利用
>>> 履歴の反映
【演習】
複製先リポジトリにおいて、
管理対象ファイルに対する変更を行い、
新たなリビジョンをコミットせよ。
また、複製元リポジトリには、
新規のリビジョンが反映されていないことも確認せよ。
----@
>>> 複数リポジトリの利用
>>> 履歴の反映
新たに追加されたリビジョンは、
明示的な操作によって、
複製先リポジトリから複製元リポジトリへと反映させることが可能です。
----@
>>> 複数リポジトリの利用
>>> 履歴の反映
【演習】
複製先リポジトリから複製元リポジトリへと、
反映される予定のリビジョン群を確認せよ。
また、確認前後で、
複製元リポジトリの履歴が変化していないことも確認せよ。
----@
>>> 複数リポジトリの利用
>>> 履歴の反映
【演習】
複製先リポジトリから複製元リポジトリへと、
新たなリビジョンを反映させよ。
また、反映後には、
複製先リポジトリでの新規追加リビジョンが、
複製元リポジトリでも参照できることを確認せよ。
----@
>>> 複数リポジトリの利用
履歴の取り込み
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
先の演習では、
複製先で追加されたリビジョンを、
複製先が起点となって複製元へと反映させました。
同じ『複製先 ⇒ 複製元』方向のリビジョンの反映でも、
複製元側が起点になって、
『取り込み』を行うことも可能です。
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
【演習】
複製先リポジトリにおいて、
管理対象ファイルに対する変更を行い、
新たなリビジョンをコミットせよ。
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
【演習】
複製元リポジトリを起点として、
複製先リポジトリから複製元リポジトリへと、
取り込まれる予定のリビジョン群を確認せよ。
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
【演習】
複製元リポジトリを起点として、
複製先リポジトリから複製元リポジトリへと、
新たなリビジョンを取り込め。
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
ホスト間連携が発生する場合、
セキュリティ的な理由/ホスト環境設定上の理由などから、
『複製』(clone)、『反映』(push)、『取り込み』(pull)の全てが、
常に対象環境で実施できるとは限りません。
例えば、
手元のリポジトリで履歴管理中の成果を、
後から bitbucket で公開しようとした場合、
『bitbucket 上から、手元のリポジトリを clone』することはできません。
いずれかの実行が制約を受けるような状況でも、
他の機能を使用することで、
履歴情報を伝播させることが可能となるケースが多々有ります。
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
【宿題】
『初期化』(init)+『反映』(push) のみを使って、
リポジトリの複製を作成せよ。
----@
>>> 複数リポジトリの利用
>>> 履歴の取り込み
ロールバック (rollback) 機能は、
コミットの取り消し以外にも、
リポジトリ間での履歴の反映/取り込み実施も取り消すことができます。
但し、
TortoiseHg では、
履歴の反映/取り込みの取り消しは、
実装上できないようになっている模様です。
----@
>>> 複数リポジトリの利用
連携先リポジトリの指定
----@
>>> 複数リポジトリの利用
>>> 連携先リポジトリの指定
.hg 直下の
hgrc ファイルに [paths] 設定を記述することで、
連携先リポジトリの位置情報を、
名前付きで管理/参照することができます。
----@
>>> 複数リポジトリの利用
>>> 連携先リポジトリの指定
【宿題】
hgrc ファイルの
[paths] 設定を使って、
連携先リポジトリを追加せよ。
また、追加した連携先情報を使って、
履歴情報の伝播を実施せよ。
----@
複数人での作業
----@
>>> 複数人での作業
履歴の分岐
----@
>>> 複数人での作業
>>> 履歴の分岐
複数人で作業した際の典型的なケースは、
個々のリポジトリで追加されたリビジョンによって、
履歴が分岐するというものです。
----@
>>> 複数人での作業
>>> 履歴の分岐
【演習】
複製先リポジトリ
(以下 "REPO-A") において、
各行が2桁の行番号を持つファイルを2つ
(以下 "FILEA" "FILEB")
追加したリビジョンをコミットし、
複製元リポジトリ
(以下 "REPO-SHARED" )
にそのリビジョンを反映させよ。
追加する各ファイルは、最低でも20行以上のファイルとする事
01
02
03
.....
18
19
20
----@
>>> 複数人での作業
>>> 履歴の分岐
【演習】
REPO-SHARED を元に、
REPO-A の他に、
もう一つの複製リポジトリ
(以下 "REPO-B") を作成せよ。
----@
>>> 複数人での作業
>>> 履歴の分岐
【演習】
FILEA に対して、
REPO-A では 1 行目近辺を、
REPO-B では 20 行目近辺をそれぞれ改変し、
変更内容をコミットせよ (以下 "REV-A1" "REV-B1") 。
双方でのコミット実施後、
新規追加リビジョンの REPO-SHARED への反映を、
以下の手順で実施せよ。
- REPO-A ⇒ REPO-SHARED への REV-A1 の反映
- REV-A1 が REPO-SHARED に反映されていることを確認
- REPO-B ⇒ REPO-SHARED への REV-B1 の反映
(+ エラーの発生)
- REV-B1 が REPO-SHARED に反映されていないことを確認
----@
>>> 複数人での作業
>>> 履歴の分岐
直前の演習で、
REPO-B ⇒ REPO-SHARED への履歴反映が失敗したのは、
REPO-B での新規追加リビジョン REV-B1 を REPO-SHARED に反映した場合、
REPO-SHARED の履歴が分岐してしまうことが検出されたからです。
Mercurial では、
分岐した履歴をマージ (merge) する責務が先送りされることを防ぐために、
枝分かれが生じるような、リポジトリ間での履歴の反映は、
デフォルトでは禁止されています。
このようなケースでは、
履歴反映先 (= REPO-SHARED) から履歴を取り込み、
手元 (= REPO-B) で履歴のマージを行った後に、
改めて履歴の反映を行います。
----@
>>> 複数人での作業
>>> 履歴の分岐
【演習】
REPO-SHARED から REPO-B に履歴 (= REV-A1) の取り込みを行い、
履歴が枝分かれしていることを確認せよ。
----@
>>> 複数人での作業
>>> 履歴の分岐
Mercurial には、
対象リビジョン(群)を指定するための、
revsets と呼ばれる記述形式があり、
"head()" と記述することで、
枝分かれの先頭を指定できます。
----@
>>> 複数人での作業
>>> 履歴の分岐
【演習】
REPO-A および REPO-B において、
REV-A1 に対する
『リビジョン番号』『短縮ハッシュ値』を確認せよ。
----@
>>> 複数人での作業
>>> 履歴の分岐
Mercurial では、
枝分かれした (= 1つのリビジョンが複数の子リビジョンを持つ)
履歴ツリー構造のことを『ブランチ』(branch) と呼びます。
後述する『名前付きブランチ』(named branch) との対比から、
ここで示したような枝分かれは
『名前無しブランチ』(anonymous branch) と呼ばれます。
子リビジョンを持たないリビジョンは『ヘッド』 (head) と呼ばれます。
----@
>>> 複数人での作業
>>> 履歴の分岐
一旦履歴が枝分かれしたならば、
マージによって枝分かれが解消されるまでは、
リポジトリは『複数ヘッド』 (multiple heads)
状態となります。
無名ブランチは、
一旦作成されてしまえば、
その構造は永続的に記録されますが、
ヘッドの数は、
時間経過 (= 履歴マージの実施/新規リビジョンの追加) と共に増減します。
----@
>>> 複数人での作業
>>> 履歴の分岐
【注意】
Git の HEAD と、Mercurial の head(s) は全くの別物です。
Git での HEAD は、
何らかのリビジョンを指す唯一のポインタですが、
Mercurial の head(s) は、
単に『枝分かれしている』状態を表しているだけで、
『HEAD ポインタが複数ある』
というようなことを表しているわけではありません。
----@
>>> 複数人での作業
履歴のマージ
----@
>>> 複数人での作業
>>> 履歴のマージ
複数人/複数リポジトリにより、
並行作業が実施されている場合、
履歴の枝分かれ自体は珍しいことではありません。
しかし、
同一ファイルの近接部位を同時に改変するようなケースを除けば、
Mercurial における履歴のマージは非常に簡単です。
----@
>>> 複数人での作業
>>> 履歴のマージ
同一ファイルを並行して改変した場合であっても、
お互いが離れた場所の改変であれば、
マージの手間は増えません。
裏を返せば、
簡単にマージできても、
『成果物の内容の正しさが保証されている』訳ではない、
という点には注意が必要です。
Mercurial のような履歴管理ツールは、
元々成果物の内容の正しさを保証するものではありません
(※ 由来の正当性は保証しますが…)。
内容保証のためには、ビルド/テストの自動化といった手段を、
別途講じる必要があります。
----@
>>> 複数人での作業
>>> 履歴のマージ
同一ファイルの近傍が並行して改変された場合、
マージ作業では、
双方の改変が衝突 (conflict) することが検出されます。
マージ成果をコミットするためには、
衝突が検出された各ファイル毎に、
(1) 衝突した箇所を修正し、
(2) 衝突が解消された旨を Mercurial に通知することが必要です。
以上の手順を『衝突解消』(resolve conflict)と呼びます。
----@
>>> 複数人での作業
>>> 履歴のマージ
Mercurial における履歴のマージ (= 広義の『マージ』) は、
大きく以下の2つの手順から構成されます。
- "
hg merge" コマンド実行(相当の)操作 (= 狭義の『マージ』)
- 衝突の確認/解消を行った上で、作業成果をコミット
----@
>>> 複数人での作業
>>> 履歴のマージ
マージツールとして、
GUI ツール (例: kdiff3/WinMerge 等) を使用する場合、
狭義の『マージ』実施と、改変衝突の確認/解消は、
GUI ツール上で同時に実施できます。
但し本ハンズオンでは、
CUI/GUI 共通の手順として、
GUI ツールを使わない手順で進めます。
なお、
あらかじめ設定をしておくことで、
CUI からの "hg merge" 実行契機で
GUI のマージツールを起動することも可能です
(詳細は "hg help merge-tools" 参照)。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
マージツールとして、
internal:mergeを明示的に指定せよ。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
REPO-B の作業領域において、
以下の点を確認せよ。
- 親リビジョンが REV-B1
- 作業領域中に未コミットの変更が無い
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
REPO-B 上で、
REV-A1 と REV-B1 の狭義の『マージ』
(= "hg merge" 相当) を実施せよ。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
REPO-B 上で、
狭義の『マージ』による改変衝突が無い事を確認せよ。
----@
>>> 複数人での作業
>>> 履歴のマージ
『マージ』過程の、
『マージ』または『マージ結果をコミット』ダイアログで "Cancel" し、
一旦ワークベンチに戻ってから、
確認する方法も。
----@
>>> 複数人での作業
>>> 履歴のマージ
作業領域のファイル状態一覧での表示ベースでの確認:
----@
>>> 複数人での作業
>>> 履歴のマージ
『リポジトリ』メニュー ⇒ 『Resolve ...』 で表示される
『Resolve conflicts』ダイアログで確認する方法も。
----@
>>> 複数人での作業
>>> 履歴のマージ
マージ成果をコミットする際には、
ファイル名を指定することができません。
これは、
履歴のツリー自体はマージされているのに、
一部のファイルでは、
履歴のマージが反映されていない、
といった事態を回避するためです。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
REPO-B 上で、
狭義の『マージ』結果をコミットすることで、
(広義の)『マージ』実施リビジョンを作成せよ。
また、
コミット前後での、
作業領域の親リビジョンの変化を確認せよ。
なお、
マージ実施リビジョンは、
REPO-SHARED および REPO-A に伝播させること。
----@
>>> 複数人での作業
>>> 履歴のマージ
※ ここで "Cancel" した上で、
通常と同様に Workbench からコミットすることも可能。
----@
>>> 複数人での作業
>>> 履歴のマージ
(広義の) マージ操作を行っている最中に、
『マージを最初からやり直す』あるいは
『マージの実施自体を取りやめる』
といった必要が生じた場合は、
適当なリビジョン (※ 一般的には、マージ実施前の作業領域の親リビジョン)
を指定して、
強制的な (= 中途成果の破棄) 作業領域の更新を行います。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
FILEB に対して、
REPO-A および REPO-B の双方で、9 〜 11 行目を改変し、
変更内容をコミットせよ (以下 "REV-A2" "REV-B2") 。
その後、
REV-A1/REV-B1 の際と同じ手順で、
REV-A2 を REPO-B に取り込むところまで実施せよ。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
REPO-B 上で、
REV-A2 と REV-B2 の狭義の『マージ』
(= "hg merge" 相当) を実施せよ。
----@
>>> 複数人での作業
>>> 履歴のマージ
【演習】
REPO-B 上で、
狭義の『マージ』による改変衝突の確認、
解消 (ファイルの修正+解消の通知)、
および『マージ』実施リビジョンのコミットを行え。
(1) 衝突が検出されたファイルを確認。
----@
>>> 複数人での作業
>>> 履歴のマージ
(2) 衝突が検出されたファイルの、該当箇所の修正。
07
08
<<<<<<< local
09 REPO-B での REV-B2 による改変
10 REPO-B での REV-B2 による改変
11 REPO-B での REV-B2 による改変
=======
09 REPO-A での REV-A2 による改変
10 REPO-A での REV-A2 による改変
11 REPO-A での REV-A2 による改変
>>>>>>> other
12
13
----@
>>> 複数人での作業
>>> 履歴のマージ
----@
>>> 複数人での作業
>>> 履歴のマージ
【宿題】
衝突の発生する履歴のマージを、
TortoiseHg 経由で GUI マージツールを使用して実施せよ。
- 設定ダイアログからあらかじめマージツールを設定
- マージを実施
- 衝突検出 ⇒ 『解決する』リンクで『Resolve conflicts』ダイアログを表示
- 解消対象ファイルを選択
- "Tool Resolve" ボタン押下
- GUI ツールで衝突解消
----@
>>> 複数人での作業
未コミット成果ベースのマージ
----@
>>> 複数人での作業
>>> 未コミット成果ベースのマージ
Mercurial では、
第二世代 (CVS/Subversion) と同様な、
マージ実施リビジョンを作成しないマージ
(以下『未コミット成果ベースのマージ』)
も可能です。
しかし、
未コミット成果ベースのマージでは、
作業の途中でやり直ししたくなった場合や、
マージそのものを無かったことにする場合、
作業領域中の未コミット成果は、
破棄しなくてはならないため、
あまり安全ではありません。
----@
>>> 複数人での作業
枝分かれを横断する親リビジョンの変更
----@
>>> 複数人での作業
>>> 枝分かれを横断する親リビジョンの変更
リビジョン指定無しで "hg update" を実行した場合、
作業領域を一番最新のリビジョンで更新します。
しかし、
履歴が枝分かれしている状況において、
現在の作業領域の親リビジョンの枝と、
最新リビジョンの枝が異なる
(= 枝分かれを横断する) 場合、
"hg update" は中断されます:
"--check" オプション指定により処理中断を回避可能。
これは、
利用者が履歴が枝分かれしていることに気付かずに、
想定外のリビジョンで作業をしてしまうことを回避するための仕組みです。
作業領域更新の際に、
常に対象リビジョンを明示する TortoiseHg 経由で利用する場合は、
この挙動の影響を受けることは無いでしょう。
----@
>>> 複数人での作業
>>> 枝分かれを横断する親リビジョンの変更
【宿題】
作業領域に未コミット変更がある状況では、
明示的にリビジョンを指定した場合でも、
枝分かれの横断ができないことを確認せよ。
また、強制的に (= 未コミット変更を破棄しつつ)
枝分かれ横断での親リビジョンの変更を実施せよ。
----@
>>> 複数人での作業
名前付きブランチ
----@
>>> 複数人での作業
>>> 名前付きブランチ
----@
>>> 複数人での作業
コミット成果の打ち消し
----@
>>> 複数人での作業
>>> コミット成果の打ち消し
一旦共有リポジトリに反映してしまったリビジョンは、
既に他のリポジトリに取り込まれてしまった可能性があります。
そのため、
当該リビジョンを『なかったことにする』場合、
共有リポジトリからそのリビジョンを取り除くのではなく、
そのリビジョンによる変更を『打ち消す』効果を持つリビジョンを
(自動的に生成して) 新規に追加する、
という方法を用います。
Mercurial ではこの機能を『バックアウト』 (bakcout) と呼びます。
最新版の Mercurial における backout 挙動の詳細は、
『Mercurial 1.7 版以後の backout 挙動』を参照してください。
----@
>>> 複数人での作業
>>> コミット成果の打ち消し
【宿題】
バックアウト機能を使用して、
(1) 直前および (2) 直前以外のコミット成果の打消しを行え。
----@
更に詳しく知るために
----@
>>> 更に詳しく知るために
Mercurial はオンラインヘルプが充実しているので、
ヘルプ一覧で表示される各種トピックや、
同梱エクステンションについて、
オンラインヘルプベースで調べるだけで、
かなりの情報を得ることができます。
また、拙著『入門 Mercurial』を買って頂けるとありがたいです(笑)。
その上で質問/疑問等がありましたら、
日本語 ML 宛投函や、
#mercurialjp 付きツイート等でお寄せください。
----@
Mercurial 入門ハンズオン
with TortoiseHg
藤原 克則 <foozy@lares.dti.ne.jp>
〜 END 〜