regexps.com
前章では、hello-world
プロジェクトからの例題を拡張しました.
このプロジェクトの主要なプログラマであるアリスとボブは、一つのアーカイブから始めて, いくつかのリビジョンを作成しました。
キャンディスは、プロジェクトのユーザであり, 自身のアーカイブを作って, hello-world
プロジェクトのブランチを開始し, 自身のローカルな変更を保守し始めました.
この章では、自由ソフトウェアプロジェクトの, 現実世界での, より典型的な状況を考え始めます.
ここでは、アリスとボブが公的なプロジェクトのメンテナであり, キャンディスはプロジェクト外の重要な貢献者であるとします.
このような設定から出てくる, 新しいリビジョン制御の要求を, ここでは明らかにします.
そして, arch
のコマンド群がそれらの要求を満たすことを助けることを確認します.
ここまでの例では、キャンディスは基本ブランチを持っています。 彼女はメインラインからブランチを作り、いくつかのローカルの変更を行い、アリスおよびボブのメインラインの最新版に追随してました.
ここでは, アリスとボブが, キャンディスの変更をメインラインにマージしたい場合を考えます.
実は, そのマージ作業は既に終ってます。 キャンディスの最新のリビジョンはアリスとボブが望むツリーそのものです。 それは非常に簡潔な方法でそれをメインラインへマージすることができます. そのためにキャンディスの最新のリビジョンを彼らのメインラインにコミットします:
% tla get -A candice@candice.net--2003-candice \ hello-world--candice--0.1 \ hw-C [...] % cd hw-C % tla set-tree-version -A lord@emf.net--2003-example \ hello-world--mainline--0.1 % tla make-log ++log.hello-world--mainline--0.1--lord@emf.net--2003-example [... ログファイルの編集 (`tla log-for-merge' が使えます) ... ] % cat ++log.hello-world--mainline--0.1--lord@emf.net--2003-example Summary: merge from Candice's Branch Keywords: Patches applied: * candice@candice.net--2003-candice/hello-world--candice--0.1--patch-2 merge from mainline sources * candice@candice.net--2003-candice/hello-world--candice--0.1--patch-1 Punctuated the output correctly * candice@candice.net--2003-candice/hello-world--candice--0.1--base-0 tag of lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1 % tla commit [....]
慎重に読むべき注意: いま使った
トリック
によく注意してください.
キャンディスの最新のリビジョンはアリスとボブが求めるものそのものでした.
彼らは get
と set-tree-version
を組み合わせ,
キャンディスのツリーを, 彼らのメインラインに簡単にコミットできるものにしました.
両方のブランチで開発が進むにつれて何が起こるのか考えましょう。 このため, ちょっと新しいことを導入します: 複数のブランチと両者のマージを図示する方法です.
ここまでの事例の後では, 次の状況になってます;
mainline--0.1 candice--0.1 ------------- ------------ base-0 -----------> base-0 (a tag) patch-1 ---------' patch-1 patch-2 ----------> patch-2 patch-3 ----------' --------' patch-4 <-----------'
これの意味することは candice
ブランチはメインラインの patch-1
タグであることです;
そして, candice
ブランチの patch-2
で, mainline
の patch-3
までの全てのマージがありました;
さらに, mainlineの patch-4
が, candice
ブランチの patch-2
までの全てをマージしました.
マージ行が全く交差しない図である場合はいつも 単純な開発ブランチ です.
単純な開発ブランチの意義は、いかにして 2つの開発作業が 1つのプロジェクトにおいて非同期的に働きうるかについての手本であることです. それぞれのブランチの, それぞれの作業において, プログラマは "update/commit" 様式で協力します (共同作業における更新/コミットの方式を参照). しかしながら, 一方のブランチの変更は二つのブランチがマージされるまでは影響を及ぼしません.
mainline
と candice
ブランチの両方でさらに作業があったとしましょう. こんな具合にです:
mainline--0.1 candice--0.1 ------------- ------------ base-0 -----------> base-0 (a tag) patch-1 ---------' patch-1 patch-2 ----------> patch-2 patch-3 ----------' --------' patch-3 patch-4 <-----------' patch-4 patch-5 patch-6 % tla revisions --summary -A candice@candice.net--2003-candice \ hello-world--candice--0.1 base-0 tag of lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1 patch-1 Punctuated the output correctly patch-2 merge from mainline sources patch-3 added a period to output string patch-4 capitalized the output string % tla revisions --summary -A lord@emf.net--2003-example \ hello-world--mainline--0.1 base-0 initial import patch-1 Fix bugs in the "hello world" string patch-2 commented return from main patch-3 added copywrong statements patch-4 merge from Candice's Branch patch-5 fixed the copyrwrong for hw.c patch-6 fixed the copyrwrong for main.c
mainline
ブランチの新しい作業を candice
ブランチにマージすることを目的とした筋書を考えましょう.
つまり, 次のように話をもっていきたいです:
mainline--0.1 candice--0.1 ------------- ------------ base-0 -----------> base-0 (a tag) patch-1 ---------' patch-1 patch-2 ----------> patch-2 patch-3 ----------' --------' patch-3 patch-4 <-----------' patch-4 patch-5 --------> patch-5 patch-6 ------------'
どうすれば, このようにマージできるでしょうか?
出発点はマージ直前の candice のリビジョン (patch-4
) としましょう:
% tla get -A candice@candice.net--2003-candice \ hello-world--candice--0.1--patch-4 \ hw-C-4 [....] % cd hw-C-4
ここでは, うまくいかない 2つのやり方があります:
replay
は、mainline
からの "見当たらない" 変更すべてを
candice
ツリーへ適用を試みるでしょう.
それが適用するチェンジセットのリストは次のものです:
% tla missing --summary \ -A candice@candice.net--2003-example \ hello-world--mainline--0.1 patch-4 merge from Candice's Branch patch-5 fixed the copyrwrong for hw.c patch-6 fixed the copyrwrong for main.c
リスト中で問題なのは patch-4
です。
それは candice
ブランチからの patch-2
レベルまで
全ての変更を含むマージです.
しかし、それらの変更は、candice
ブランチの
patch-4
リビジョンに既にあります.
-- だから, replay
はそれらを余分に適用するでしょう
(そしてパッチの衝突 (conflict) を起こします).
警告の註: replay
コマンドは、
さらなる replay を妨げません. たとえ, ソースツリーが
一貫した状態に無くてさえもです.
現在の実装の TLA は, リジェクトするファイルをマージしません.
このため, 一回目の replay でのリジェクトを解決する前に
二回目の replay
が実行された場合,
パッチのリジェクトが失なわれる可能性があります.
(いつの日にか, TLA が複数のリジェクトを一つの組み合わせたリジェクトに統合できるようになるかもしれません.)
上級者への注意: replay
コマンドには、
mainline から patch-4
リビジョンを飛びこすことを許す
オプションがあります.
それはまあその問題を解決しますが, 欠点もあります.
まず, これが意味するところは, patch-4
が
candice
ブランチの missing
の
出力に現われつづけることです.
次に, patch-4
チェンジセットが candice
ブランチからの
マージのみを含むとは限りません.
もし, アリスとボブが patch-4
で他の変更を加えて, かつ,
そのチェンジセットを飛びこせば, それらの変更は失なわれることになります.
mainline
ブランチから, update
を試みるとします.
次のことを思いだしてください:
update
は, プロジェクトツリーの最も若い
mainline
の先祖から, ツリー自身のチェンジセットを求め,
これを, 最も最近の mainline
のリビジョンに適用します.
このための記法があります.
X
から Y
へのチェンジセットを次のように記します:
delta(X, Y)
この場合、update
が最初にするのは, mainline
の
patch-3
リビジョンから私たちのプロジェクトツリーまでの
チェンジセットを計算することです:
delta(mainline--0.1--patch-3, hw-C-4)
X
から Y
へのチェンジセットを
ツリー Z
に適用したためにできるツリーを以下のように記します:
delta(X, Y) [ Z ]
言いかえれば、私たちのサンプルでの update
の結果は
次のように書けます:
delta(mainline--0.1--patch-3, hw-C-4) [mainline--0.1--patch-6]
しかし, ここが問題です.
mainline
の patch-3
リビジョンは,
以前は candice
ブランチとはマージされませんでした。
したがって, チェンジセット
delta(mainline--0.1--patch-3, hw-C-4)
は, 変更のなかでも特に, キャンディスブランチの
patch-1
と patch-2
からの変更を含むでしょう.
不運にも、私たちがそのチェンジセットを適用するツリーの
mainline--0.1--patch-6
は、
既に candice
ブランチの base-0...patch-2
が
マージされてます.
replay
同様, update
は余分な変更を
起こすためにマージが衝突を起します.
delta
記法とマージの図だけを使って, このマージの問題を
きれいに解決することを示します.
現状を思いだすと,
mainline--0.1 candice--0.1 ------------- ------------ base-0 -----------> base-0 (a tag) patch-1 ---------' patch-1 patch-2 ----------> patch-2 patch-3 ----------' --------' patch-3 patch-4 <-----------' patch-4 patch-5 patch-6
で, 目的は新しいマージを, Candice のブランチの patch-5 に対して 作ることです:
--------> patch-5 patch-6 ------------'
mainline
ブランチから出発して,
candice
の変更点でまだ無い部分をマージしても良いですし,
candice
ツリーから出発して, mainline
の
変更点でまだ無い部分をマージしても良いです.
後者で行きましょう (candice
ツリーへマージ).
ここで, mainline-0.1
リビジョンの
patch-6
は candice-0.1
リビジョン
patch-2
まで "追随してます".
そこからの変更を candice
の最新版へ適用したいです:
ここで: ancestor := candice--0.1--patch-2 merge_in := mainline--0.1--patch-6 target := canidice--0.1--patch-4
answer := delta(ancestor, merge_in)[target]
マージ図中の矢印は正解を探すために重要です。
例えば、キャンディスの patch-2
から
mainline
リビジョン patch-4
への矢印が
無かったとします. このときは答は以下のとおりです:
ここで: ancestor := mainline--0.1--patch-3 merge_in := mainline--0.1--patch-6 target := canidice--0.1--patch-4
answer := delta(ancestor, merge_in)[target]
マージに対応する矢印を追うのは退屈な作業です.
これの自動化は, star-merge
コマンドでなされます:
開発ブランチのマージ問題を, 一般的に, 完全に解決する方法を説明することは, 本書の範囲をちょっと越えます. 上で示した二つの解決策は二つの場合を説明します, しかし、少しだけ異なる解決策が必要なこともあります.
あなたが知るべきことは, 単純な開発ブランチ
(単純な開発ブランチを参照)を持つ場合,
star-merge
コマンドは両者をマージする方法を知っていて,
偽のマージの衝突を起こさずに済むことです.
通常の使用では、情報をマージしたいツリーで
star-merge
を起動し, 引数としてマージしたいツリーを渡します:
% tla get -A candice@candice.net--2003-candice \ hello-world--candice--0.1--patch-4 \ merge-temp % tla star-merge lord@emf.net--2003/hello-world-mainline--0.1arch Meets hello-world: A Tutorial Introduction to The arch Revision Control System
regexps.com