foozy@708: \chapter{Managing releases and branchy development} foozy@708: \label{chap:branch} foozy@708: foozy@708: Mercurial は、 foozy@708: 同時並行的に開発を進めるようなプロジェクトを管理できる仕組みを持っています。 foozy@708: これらの仕組みを理解するために、 foozy@708: まずは一般的なソフトウェア開発の仕組みを眺めてみましょう。 foozy@708: foozy@708: 多くのソフトウェアプロジェクトでは、 foozy@708: 重要な新規機能を含む``メジャー''リリースを間欠的に発行します。 foozy@708: それと平行して``マイナー''リリースも発行することがあります。 foozy@708: 多くの場合、 foozy@708: マイナーリリースは元にしたメジャーリリースと同一ですが、 foozy@708: バグの修正がなされています。 foozy@708: foozy@708: この章では、 foozy@708: 「リリース」のようなプロジェクトのマイルストーンの、 foozy@708: 記録を保持する方法から説明を始めたいと思います。 foozy@708: その後で、 foozy@708: プロジェクトにおけるフェーズ移行での作業の流れや、 foozy@708: その際の作業や成果物を foozy@708: Mercurial によって分離/管理する方法を説明します。 foozy@708: foozy@708: \section{Giving a persistent name to a revision} foozy@708: foozy@708: 特定のリビジョンを``リリース''と呼ぶことに決定したなら、 foozy@708: そのリビジョンの ID を記録するべきです。 foozy@708: リビジョンの ID を記録することで、 foozy@708: 後日何らかの理由(例えばバグの再現や、新規プラットフォームへの移植等) foozy@708: で必要になった際にリリースを再現することができます。 foozy@708: foozy@708: \interaction{tag.init} foozy@708: foozy@708: \hgcmd{tag} コマンドを利用することで、 foozy@708: Mercurial は任意のリビジョンに永続的な名前を付与します。 foozy@708: 読者の予想通り、この名前のことを``タグ''と呼びます。 foozy@708: foozy@708: \interaction{tag.tag} foozy@708: foozy@708: リビジョンにとって、 foozy@708: タグは``象徴的な名前''(symbolic name) 以外の何者でもありません。 foozy@708: タグは純粋に利便性のために存在するもので、 foozy@708: リビジョンを参照する際の手軽で永続的な手段となります。 foozy@708: Mercurial は、 foozy@708: 利用者の用いるタグ名の意味を解釈したりしません。 foozy@708: 曖昧さが無く解析できることを保証するために必要な少々の制約を除いては、 foozy@708: タグ名に何らかの制約をつけたりすることもありません。 foozy@708: 以下のいずれの文字もタグ名には使用できません。 foozy@708: foozy@708: \begin{itemize} foozy@708: \item コロン(ASCII 58, ``\texttt{:}'') foozy@708: \item 行頭移動\footnote{carriage return} (ASCII 13, ``\Verb+\r+'') foozy@708: \item 改行 (ASCII 10, ``\Verb+\n+'') foozy@708: \end{itemize} foozy@708: foozy@708: \hgcmd{tags} コマンドを使用することで、 foozy@708: リポジトリが保持しているタグを表示させることができます。 foozy@708: \hgcmd{tags} コマンドの出力において、 foozy@708: 個々のタグ付けされたリビジョンは、 foozy@708: 始めにタグ名で、次にリビジョン番号で、 foozy@708: 最後に一意のリビジョンハッシュ値で識別されます。 foozy@708: foozy@708: \interaction{tag.tags} foozy@708: foozy@708: \texttt{tip} タグが \hgcmd{tags} foozy@708: コマンドの出力に列挙されていることに注意してください。 foozy@708: \texttt{tip} は、常にリポジトリ中の最新のリビジョンを指す foozy@708: ``流動的な''特殊タグです。 foozy@708: foozy@708: \hgcmd{tags} コマンドの出力では、 foozy@708: タグはリビジョン番号の逆順(降順)で列挙されています。 foozy@708: これは最新のタグは古いタグよりも先に列挙されることを意味し、 foozy@708: それは同時に \hgcmd{tags} が出力するタグ一覧の最初に foozy@708: \texttt{tip} が表示されることも意味します。 foozy@708: foozy@708: \hgcmd{log} コマンドの実行時に、 foozy@708: タグと関連付けられたリビジョンを表示する場合、 foozy@708: \hgcmd{log} コマンドはタグを表示します。 foozy@708: foozy@708: \interaction{tag.log} foozy@708: foozy@708: Mercurial コマンドに対してリビジョン識別子を指定する必要がある場合、 foozy@708: リビジョン識別子を指定する位置では、 foozy@708: 常にタグ名を使用することができます。 foozy@708: Mercurial の内部では、 foozy@708: タグ名を対応するリビジョン識別子に変換してから使用しています。 foozy@708: foozy@708: \interaction{tag.log.v1.0} foozy@708: foozy@708: 単一のリポジトリが保持できるタグの数にも、 foozy@708: 単一のリビジョンに付与できるタグの数にも制限はありません。 foozy@708: 現実的な問題として、 foozy@708: タグは単にリビジョンの特定を補助するものですから、 foozy@708: ``過剰に''(具体的な数はプロジェクトに応じて異なりますが) foozy@708: タグを付与するのはよろしくありません。 foozy@708: 多くのタグがあると、リビジョンを特定する利便性が早々に減少してしまいます。 foozy@708: foozy@708: 例えば、 foozy@708: あるプロジェクトでは数日毎の頻度でマイルストーンを設定しているとすると、 foozy@708: それぞれのマイルストーンにタグを付与するのは極めて合理的です。 foozy@708: しかし、全てのリビジョンで確実に綺麗なビルドができる継続的 foozy@708: (continuous)なビルドシステムがある場合は、 foozy@708: 綺麗なビルド毎にタグを付与すると、大量のノイズを持ち込むことになります。 foozy@708: その代わりに、 foozy@708: ビルドが失敗するリビジョン(この事態が稀だと仮定しています!) foozy@708: にタグを付与するか、 foozy@708: ビルドの可否を追跡するタグの使用を止めるのが良いでしょう。 foozy@708: foozy@708: 必要の無くなったタグを削除したい場合は foozy@708: \hgcmdargs{tag}{--remove} コマンドを使用します。 foozy@708: foozy@708: \interaction{tag.remove} foozy@708: foozy@708: 任意の時点でタグの関連付けを変更することもできますので、 foozy@708: 新規の \hgcmd{tag} コマンド実行により、 foozy@708: 同一のタグが異なるリビジョンを識別するようになります。 foozy@708: \emph{本当に}タグを更新したいことを Mercurial に伝えるために、 foozy@708: \hgopt{tag}{-f} オプションを使用しなければなりません。 foozy@708: foozy@708: \interaction{tag.replace} foozy@708: foozy@708: タグの更新後も、 foozy@708: タグが以前に識別していたリビジョンに関する永続的な記録が残りますが、 foozy@708: Mercurial がそれを使用することはありません。 foozy@708: このように、 foozy@708: 間違ったリビジョンへのタグの付与には何の不利益もありませんので、 foozy@708: タグ付けを間違ったなら、正しいリビジョンにタグを付与し直せばよいのです。 foozy@708: foozy@708: Mercurial は、 foozy@708: リポジトリ中のリビジョン管理された通常ファイルにタグの情報を格納しています。 foozy@708: 何らかのタグを付与すると、 foozy@708: \sfilename{.hgtags} ファイル中にそのタグを見つけることができるでしょう。 foozy@708: \hgcmd{tag} コマンドを実行すると、 foozy@708: Mercurial はこのファイルを変更し、自動的に変更をコミットします。 foozy@708: このことは、 foozy@708: \hgcmd{tag} コマンドを実行した際には、 foozy@708: 常に対応するチェンジセットを \hgcmd{log} コマンドの出力で見ることができる、 foozy@708: ということを意味しています。 foozy@708: foozy@708: \interaction{tag.tip} foozy@708: foozy@708: \subsection{Handling tag conflicts during a merge} foozy@708: foozy@708: \sfilename{.hgtags} ファイルを気にする必要は殆どありませんが、 foozy@708: 時にはマージの際にその存在が意識されることがあります。 foozy@708: このファイルの形式は単純で、連続した行から構成されています。 foozy@708: 各行はチェンジセットのハッシュ値で始まり、空白とタグ名が続きます。 foozy@708: foozy@708: マージにおける foozy@708: \sfilename{.hgtags} ファイルの衝突を解消する際には、 foozy@708: \sfilename{.hgtags} ファイル修正にひねりが必要です。 foozy@708: リポジトリ中のタグを解析する場合、 foozy@708: Mercurial は\emph{決して} foozy@708: \sfilename{.hgtags} ファイルのワーキングコピーを参照することはありません。 foozy@708: その代わりに、Mercurial foozy@708: は\emph{最も最近コミットされた}ファイルのリビジョンを調べます。 foozy@708: foozy@708: このような設計の残念な結果として、 foozy@708: マージした \sfilename{.hgtags} ファイルが、 foozy@708: その変更をコミットした\emph{後も}正しい状態であることを、 foozy@708: 実際に検証することができません。 foozy@708: マージの際に \sfilename{.hgtags} ファイルの衝突を解消する際には、 foozy@708: コミット後に \hgcmd{tags} コマンドの実行を忘れずに行ってください。 foozy@708: \sfilename{.hgtags} ファイルに不正があった場合、 foozy@708: \hgcmd{tags} コマンドは不正の場所を報告しますので、 foozy@708: その箇所を修正してコミットすれば良いのです。 foozy@708: 変更内容の正しさを確認するために、 foozy@708: 変更の後で、再度 \hgcmd{tags} コマンドを実行してください。 foozy@708: foozy@708: \subsection{Tags and cloning} foozy@708: foozy@708: \hgcmd{clone} コマンドが foozy@708: 特定のチェンジセットを指定して厳密な複製を作成するための foozy@708: \hgopt{clone}{-r} オプションを持っていることに気付いているかもしれません。 foozy@708: 新しい複製は、 foozy@708: 指定したリビジョンよりも後に生じた履歴情報を一切持っていません。 foozy@708: このことがタグと相互作用した場合、、 foozy@708: 油断していると驚かされる事態になります。 foozy@708: foozy@708: タグの生成が、 foozy@708: \sfilename{.hgtags} ファイルへの格納の際に、 foozy@708: 一つのリビジョンとして扱われることを思い出せば、 foozy@708: タグが記録されたチェンジセットが、 foozy@708: タグの付与対象となる(古い)チェンジセットを参照するのは当然のことです。 foozy@708: タグ \texttt{foo} 時点のリポジトリを複製するために foozy@708: \hgcmdargs{clone}{-r foo} を実行した場合、 foozy@708: 複製されたリポジトリは、 foozy@708: 複製する際に使用された\emph{タグの作成に関する履歴を持っていません}。 foozy@708: 新しいリポジトリには、 foozy@708: プロジェクト履歴の完全なサブセットが含まれますが、 foozy@708: 唯一、指定に用いたタグの情報は\emph{含まれていません}。 foozy@708: foozy@708: \subsection{When permanent tags are too much} foozy@708: foozy@708: Mercurial のタグは構成管理されており、 foozy@708: プロジェクトの履歴と一体化しているため、 foozy@708: 誰かが作成したタグは、 foozy@708: 一緒に作業を行っている誰もが見ることができます。 foozy@708: しかし、リビジョンに名前を付けることは、 foozy@708: リビジョン \texttt{4237e45506ee} が実は \texttt{v2.0.2} である、 foozy@708: ということを書き留めておく以上の有用性があります。 foozy@708: 巧妙なバグを追跡する際に、 foozy@708: ``アンがこのリビジョンで症状を見かけた''といった類の備忘録として、 foozy@708: タグを付与したい場合もあるでしょう。 foozy@708: foozy@708: このような場合、 foozy@708: \emph{ローカル}なタグが最適です。 foozy@708: \hgopt{tag}{-l} オプション付きで foozy@708: \hgcmd{tag} コマンドを起動することで、 foozy@708: ローカルタグを作成することができます。 foozy@708: このコマンド実行の場合、 foozy@708: タグは \sfilename{.hg/localtags} ファイルに格納されます foozy@708: \sfilename{.hgtags} と異なり foozy@708: \sfilename{.hg/localtags} は構成管理されません。 foozy@708: \hgopt{tag}{-l} によって作成したタグは、 foozy@708: 現在作業をしているリポジトリに留まり続けます foozy@708: \footnote{訳注: \hgcmd{clone}、\hgcmd{pull} や foozy@708: \hgcmd{push} によって他のリポジトリにコピーされることがありません}。 foozy@708: foozy@708: \section{The flow of changes---big picture vs. little} foozy@708: foozy@708: ここで、本章の冒頭で述べた概略に戻り、 foozy@708: 複数の平行した開発が同時に行われているプロジェクトについて考えて見ましょう。 foozy@708: foozy@708: 新しい``主''リリースや、 foozy@708: 最新の主リリースに対する新たなマイナーバグ修正、 foozy@708: 現在は保守状態にあるような古いリリースに対する予期せぬ``hot fix'' foozy@708: のための push があるでしょう。 foozy@708: foozy@708: 開発における様々な平行した方向を参照するための一般的な方法は、 foozy@708: ``ブランチ''と呼ばれるものです。 foozy@708: しかし、 foozy@708: Mercurial が\emph{全ての履歴}を foozy@708: 「ブランチとマージの連続」として扱っていることを、 foozy@708: 既に何度も見てきました。 foozy@708: 実際には、 foozy@708: 表面的には関係しているようで、 foozy@708: その実、たまたま同じ名前であるだけの2つの概念を扱っているのです。 foozy@708: foozy@708: \begin{itemize} foozy@708: \item ``巨視的な''ブランチは、プロジェクト発展の広がりを表し、 foozy@708: 名前をつけたり、話題に上ったりします。 foozy@708: foozy@708: \item ``微視的な''ブランチは、日々の開発活動と、変更マージの成果です。 foozy@708: このブランチは、コードがどのように開発されていったのかを物語ります。 foozy@708: foozy@708: \end{itemize} foozy@708: foozy@708: \section{Managing big-picture branches in repositories} foozy@708: foozy@708: Mercurial において``巨視的な''ブランチを隔離する最も簡単な方法は、 foozy@708: 隔離用のリポジトリを用意することです。 foozy@708: 例えば、既にある共有リポジトリ---これを \texttt{myproject} と呼称します foozy@708: ---が ``1.0'' というマイルストーンに到達している場合、 foozy@708: 1.0 リリースのために使用したリビジョンにタグを付与することで、 foozy@708: 1.0 版に対する来るべき保守リリースの準備を行います。 foozy@708: foozy@708: \interaction{branch-repo.tag} foozy@708: foozy@708: タグ付けした時点と同じ内容の foozy@708: \texttt{myproject-1.0.1} foozy@708: という名の新しい共有リポジトリを複製します。 foozy@708: foozy@708: \interaction{branch-repo.clone} foozy@708: foozy@708: その後、 foozy@708: 来る 1.0.1 マイナーリリースに含めるべきバグ修正の作業が必要になったなら、 foozy@708: \texttt{myproject-1.0.1} リポジトリを複製し変更を行って、 foozy@708: その成果を反映します。 foozy@708: foozy@708: \interaction{branch-repo.bugfix} foozy@708: foozy@708: その間、次のメジャーリリースへ向けた開発作業は、 foozy@708: マイナーリリースに関する作業とは隔離された状態で、 foozy@708: \texttt{myproject} リポジトリにおいて活発に続けられます。 foozy@708: foozy@708: \interaction{branch-repo.new} foozy@708: foozy@708: \section{Don't repeat yourself: merging across branches} foozy@708: foozy@708: 保守用ブランチでバグ修正を行ったとすると、 foozy@708: 多くの場合、プロジェクトのメインブランチに foozy@708: (そしてそれ以外の保守ブランチにおいても) foozy@708: 同じバグが存在する可能性があります。 foozy@708: 同じバグを何度も直したいと思う開発者は稀ですから、 foozy@708: 同じ作業を繰り返すことなくバグ修正を管理するために foozy@708: Mercurial が提供する幾つかの方法を見てみましょう。 foozy@708: foozy@708: 最も単純な方法は、 foozy@708: 作業対象ブランチから複製したローカルリポジトリへ、 foozy@708: 保守ブランチから変更を pull することです。 foozy@708: foozy@708: \interaction{branch-repo.pull} foozy@708: foozy@708: その上で2つのブランチのそれぞれのヘッドをマージし、 foozy@708: その成果をメインブランチに反映します。 foozy@708: foozy@708: \interaction{branch-repo.merge} foozy@708: foozy@708: \section{Naming branches within one repository} foozy@708: foozy@708: 多くの場合は、 foozy@708: リポジトリの分離によってブランチを分離するのが適切な遣り方です。 foozy@708: 単純ですから理解も簡単ですし、それ故に間違えることがありません。 foozy@708: 作業しているブランチと、コンピュータ上の(リポジトリ)ディレクトリの間で、 foozy@708: 1対1の関係ができていますので、 foozy@708: ブランチ/リポジトリ中のファイルに対して、 foozy@708: (Mercurial を意識しない)通常のツールを使用することもできます。 foozy@708: foozy@708: あなたが(そして共同作業者も) foozy@708: ``パワーユーザー''よりも高いレベルにあるのであれば、 foozy@708: ブランチ(that you can consider XXXX)を扱う別な方法があります。 foozy@708: 前の節では、 foozy@708: ``微視的''ブランチと``巨視的''ブランチの、 foozy@708: 利用者レベルでの区別について言及しました。 foozy@708: 単一のリポジトリ中で、 foozy@708: 常に複数の``微視的な''ブランチ foozy@708: (例えば、変更の pull 後にマージしていない状態)を扱っている一方で、 foozy@708: Mercurial は複数の``巨視的な''ブランチを扱うこと\emph{も}できます。 foozy@708: foozy@708: Mercurial が``巨視的な''ブランチを扱う際の要点は、 foozy@708: ブランチに永続的な\emph{名前}を付けるところにあります。 foozy@708: 前述のように \texttt{default} という名前のブランチが常に存在しますので、 foozy@708: ブランチへの命名を行う前であっても、 foozy@708: 探せば \texttt{default} ブランチの跡を見つけることができます。 foozy@708: foozy@708: 例えば、 foozy@708: \hgcmd{commit} コマンドを実行すると、 foozy@708: エディタが起動されてコミットメッセージを入力できます foozy@708: \footnote{訳注: Emacs の hg-mode.el を使用している場合は見られません}が、 foozy@708: 末尾の ``\texttt{HG: branch default}'' を含む行を見てください。 foozy@708: これは、\texttt{default} という名前のブランチに対してコミットしている、 foozy@708: ということを表しています。 foozy@708: foozy@708: ブランチに名前をつけるには、 foozy@708: まずは \hgcmd{branches} を使用します。 foozy@708: このコマンドは、リポジトリ中に既に存在する名前付きブランチと、 foozy@708: 個々のブランチにおける先頭(tip)リビジョンがどれかを列挙します。 foozy@708: foozy@708: \interaction{branch-named.branches} foozy@708: foozy@708: 実行例では、 foozy@708: 名前付きブランチを生成する前ですから、 foozy@708: 唯一存在する \texttt{default} だけが表示されます。 foozy@708: foozy@708: どれが``現在の''ブランチかを知るには、 foozy@708: 引数無しで \hgcmd{branch} コマンドを実行します。 foozy@708: このコマンドは、 foozy@708: 現在のチェンジセットの親チェンジセットが、 foozy@708: どのブランチ上にあるものかを表示します。 foozy@708: foozy@708: \interaction{branch-named.branch} foozy@708: foozy@708: 新しいブランチを作成するには、 foozy@708: 再度 \hgcmd{branch} コマンドを実行しますが、 foozy@708: 今回は生成するブランチ名を引数として指定します。 foozy@708: foozy@708: \interaction{branch-named.create} foozy@708: foozy@708: ブランチ生成後、 foozy@708: \hgcmd{branch} コマンドによりどのような副作用を生じたのか、 foozy@708: 怪しむかもしれません。 foozy@708: \hgcmd{status} や \hgcmd{tip} の出力はどうなっているでしょうか? foozy@708: foozy@708: \interaction{branch-named.status} foozy@708: foozy@708: 作業領域に変更は加えられていませんし、 foozy@708: 履歴に変化もありません。 foozy@708: このことが示唆しているように、 foozy@708: \hgcmd{branch} コマンドの実行は何ら永続的な効果を持ちません。 foozy@708: このコマンドは、 foozy@708: \emph{次回の}チェンジセットのコミットの際に、 foozy@708: 何というブランチ名を使用するかを foozy@708: Mercurial に伝えるだけです。 foozy@708: foozy@708: 変更をコミットすると、 foozy@708: Mercurial はコミットされたチェンジセットにブランチ名を記録します。 foozy@708: 一旦 \texttt{default} ブランチから他のブランチに切り替えてコミットしたなら、 foozy@708: \hgcmd{log}、\hgcmd{tip} やそれに類する出力を持つコマンドの出力に、 foozy@708: 新たなブランチ名が表示されていることでしょう。 foozy@708: foozy@708: \interaction{branch-named.commit} foozy@708: foozy@708: \hgcmd{log} に類するコマンドは、 foozy@708: \texttt{default} ブランチ以外に属する全てのチェンジセットに対して、 foozy@708: ブランチ名を表示します。 foozy@708: そのため、名前付きブランチを使わない限り、 foozy@708: ブランチに関する情報を見ることはありません。 foozy@708: foozy@708: 名前付きブランチを作成し、そのブランチ名で変更をコミットしたならば、 foozy@708: その変更に連なるその後のコミットは、同じブランチ名を引き継ぎます。 foozy@708: \hgcmd{branch} コマンドにより、 foozy@708: 任意の時点でブランチ名を変更することができます。 foozy@708: foozy@708: \interaction{branch-named.rebranch} foozy@708: foozy@708: ブランチ名はかなり長い寿命を持つため、 foozy@708: 実際にはこのようなブランチ名の変更はそれほど頻繁に実行することは無いでしょう foozy@708: (このことは規約ではなく、あくまで感想です)。 foozy@708: foozy@708: \section{Dealing with multiple named branches in a repository} foozy@708: foozy@708: リポジトリに複数の名前付きブランチがある場合、 foozy@708: \hgcmd{update} や \hgcmdargs{pull}{-u} といったコマンド実行の際に、 foozy@708: Mercurial は作業領域ディレクトリが属するブランチを覚えていて、 foozy@708: ``リポジトリ全体''の tip リビジョンではなく、 foozy@708: そのブランチの tip リビジョンで作業領域ディレクトリを更新します。 foozy@708: 別な名前付きブランチのリビジョンで更新したい場合は、 foozy@708: \hgcmd{update} コマンドに foozy@708: \hgopt{update}{-C} オプションを指定しなければなりません。 foozy@708: foozy@708: この振る舞いは少々微妙ですから、実例で見てみましょう。 foozy@708: 始めに、 foozy@708: どのブランチ上で作業しているのかと、 foozy@708: どんなブランチがリポジトリ中に有るのかを確認します。 foozy@708: foozy@708: \interaction{branch-named.parents} foozy@708: foozy@708: 現在 \texttt{bar} ブランチ上にいますが、 foozy@708: 古い \hgcmd{foo} ブランチも存在します。 foozy@708: foozy@708: \texttt{foo} ブランチおよび \texttt{bar} ブランチの foozy@708: tip リビジョンへの移動は、 foozy@708: 変更履歴上を直線的に前後することしか必要としないため、 foozy@708: \hgcmd{update} コマンドに foozy@708: \hgopt{update}{-C} オプションを指定すること無しに、 foozy@708: それぞれの tip リビジョンへの更新を行うことができます。 foozy@708: foozy@708: \interaction{branch-named.update-switchy} foozy@708: foozy@708: \texttt{foo} ブランチに戻るために foozy@708: \hgcmd{update} コマンドを実行すると、 foozy@708: \texttt{foo} ブランチ上に留まったままで foozy@708: \texttt{bar} ブランチの tip リビジョンには移動しません。 foozy@708: foozy@708: \interaction{branch-named.update-nothing} foozy@708: foozy@708: \texttt{foo} ブランチでの変更のコミットにより、 foozy@708: 新たなヘッドが生成されます。 foozy@708: foozy@708: \interaction{branch-named.foo-commit} foozy@708: foozy@708: \texttt{foo} ブランチから \texttt{bar} ブランチへの更新は、 foozy@708: 履歴を``横っ飛び''しないとできませんから、 foozy@708: Mercurial は foozy@708: \hgcmd{update} コマンドへの \hgopt{update}{-C} foozy@708: オプションの指定を必要とします。 foozy@708: foozy@708: \interaction{branch-named.update-bar} foozy@708: foozy@708: \section{Branch names and merging} foozy@708: foozy@708: お気づきの事とは思いますが、 foozy@708: Mercurial におけるマージ処理は対称的ではありません。 foozy@708: リビジョン番号 17 のものと 23 のもの、 foozy@708: 2つのヘッドをリポジトリが持っているものとしましょう。 foozy@708: リビジョン 17 へと \hgcmd{update} foozy@708: してからリビジョン 23 と \hgcmd{merge} した場合、 foozy@708: Mercurial はリビジョン 17 をマージの第1親、 foozy@708: リビジョン 23 を第2親として記録します。 foozy@708: 一方で、 foozy@708: リビジョン 23 へと \hgcmd{update} foozy@708: してからリビジョン 17 と \hgcmd{merge} した場合、 foozy@708: リビジョン 23 がマージの第1親、 foozy@708: リビジョン 17 が第2親として記録されます。 foozy@708: foozy@708: この振る舞いが、マージを行った際の Mercurial のブランチ名選択に影響します。 foozy@708: マージ後にその結果をコミットすると、 foozy@708: Mercurial は第1親のブランチ名を維持しようとします。 foozy@708: 第1親のブランチ名が \texttt{foo} で、 foozy@708: \texttt{bar} ブランチのリビジョンとマージした場合、 foozy@708: マージ後のブランチ名は \texttt{foo} のままとなります。 foozy@708: foozy@708: リポジトリ中に同じブランチ名の複数のヘッドが存在することは、 foozy@708: それほど珍しいことではありません。 foozy@708: 例えば、私とあなたが \texttt{foo} ブランチで作業しているとします。 foozy@708: 二人がそれぞれ異なる変更をコミットし、 foozy@708: 私があなたの変更を pull しました。 foozy@708: この時点で私のリポジトリには、 foozy@708: \texttt{foo} ブランチ上に2つのヘッドが存在します。 foozy@708: マージの結果、 foozy@708: \texttt{foo} ブランチ上の2つのヘッドは期待通り1つになります。 foozy@708: foozy@708: しかし、私が \texttt{bar} ブランチで作業していて、 foozy@708: \texttt{foo} ブランチの成果をマージした場合、 foozy@708: マージの結果は \texttt{bar} ブランチ上に留まります。 foozy@708: foozy@708: \interaction{branch-named.merge} foozy@708: foozy@708: より具体的な例として、 foozy@708: \texttt{bleeding-edge} ブランチで作業していて、 foozy@708: 最新の成果を \texttt{stable} ブランチから持ち込みたいと思ったとします。 foozy@708: この場合、 foozy@708: \texttt{stable} ブランチの成果を pull してマージした段階で、 foozy@708: Mercurial は``適切な''ブランチ名(\texttt{bleeding-edge})を選択します。 foozy@708: foozy@708: \section{Branch naming is generally useful} foozy@708: foozy@708: 寿命の長い複数のブランチが単一リポジトリで共存している状況だけが、 foozy@708: 名前付きブランチの利用できる状況だとは考えないでください。 foozy@708: リポジトリ1つにブランチ1つの状況であっても、 foozy@708: 名前付きブランチは有用です。 foozy@708: foozy@708: 単純な例としては、 foozy@708: ブランチに名前を付与することで、 foozy@708: チェンジセットがどのブランチに由来するかの恒久的な記録を得ることができます。 foozy@708: この記録は、 foozy@708: 寿命の長いブランチを持つプロジェクトの履歴を辿る際に、 foozy@708: 多くの情報をもたらすことでしょう。 foozy@708: foozy@708: リポジトリを共有して作業している場合、 foozy@708: \hook{pretxnchangegroup} フックをそれぞれのリポジトリに対して設定することで、 foozy@708: ``不正な''ブランチ名を持つ変更が持ち込まれるのを防ぐことができます。 foozy@708: この手法は単純ですが、 foozy@708: ``血の滴る刃''とでも言うべき(不安定な)ブランチの成果を、 foozy@708: 誤って``安定した''ブランチへと持ち込むことを防ぐには効果的です。 foozy@708: このようなフックは、 foozy@708: 共有リポジトリの \hgrc ファイルに以下のように記述します。 foozy@708: foozy@708: \begin{codesample2} foozy@708: [hooks] foozy@708: pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch foozy@708: \end{codesample2} foozy@708: foozy@708: %%% Local Variables: foozy@708: %%% mode: latex foozy@708: %%% TeX-master: "00book" foozy@708: %%% End: