衝突を解決する

この章では、チーム開発環境での作業方法を説明します。チーム開発環境では、同一のファイルを複数のユーザが操作するため、各ユーザによる変更の調整が必要な場合があります。

複数のユーザが同一のファイル群を操作するように設定されていると、衝突が発生することがあります。Perforceでは、同じファイルのチーム内での同時操作が可能であり、発生する衝突を解決することができます。例えば、2人のユーザが同じファイルを操作するか(チーム設定における大きな懸念事項)、またはファイルの最新リビジョンではなく古いリビジョンを編集する場合に衝突が発生します。

ディポ内の最新リビジョンと衝突するファイルをサブミットしようとすると、Perforceはその衝突を解決するよう要求します。変更を開発ブランチからリリースブランチにマージする作業も、ファイルの衝突解決が必要となる主なタスクの1つです。

衝突を防ぐため、Perforceではファイルを編集するときにファイルをロックできます。しかし、ロックするとチームでの開発作業が制限されるおそれがあります。チーム開発では、ファイルをなるべく利用可能な状態にすると同時に衝突を最小限にとどめる手段を選択する必要があります。詳細については、ファイルをロックするを参照してください。

P4V(Perforceビジュアルクライアント)および関連ビジュアルマージツールのP4MergeなどのGUIツールを使用してファイルの衝突解決を行うこともできます。

衝突が発生する状況

2人のユーザが同じファイルの2つのバージョンを編集してサブミットすると、ファイルの衝突が発生することがあります。例えば次のような場合、衝突が発生します。

  1. ブルーノが//depot/dev/main/jam/command.c#8を編集目的の作業状態にします。

  2. 次にゲイルが、同じファイルを自分のクライアントワークスペースで作業状態にします。

  3. ブルーノとゲイルはともに//depot/dev/main/jam/command.c#8を編集します。

  4. ブルーノが//depot/dev/main/jam/command.cを含むチェンジリストをサブミットし、そのサブミットが成功します。

  5. ゲイルは彼女のバージョンの//depot/dev/main/jam/command.cを含むチェンジリストをサブミットします。ゲイルのサブミットは失敗します。

Perforceがディポにゲイルのバージョンを受け入れると、彼女の変更によりブルーノの変更が上書きされてしまいます。Perforceは、ブルーノの変更が失われるのを防ぐため、チェンジリストを拒否して衝突するファイルの解決をスケジュールします。ファイルが衝突することが事前に分かっており、ファイルの衝突解決をスケジュールしたい場合は、そのファイルを同期させます。Perforceはファイルの衝突を検出し、その解決をスケジュールします。

衝突解決の方法

ファイルの衝突を解決するには、p4 resolveコマンドを発行してサブミットを行うファイルの内容を決定し、各ファイルに対して解決方法を選択します。衝突を解決したら、そのファイルを含むチェンジリストをサブミットします。

Note

ファイルを編集目的で作業状態にした後、それ以降にサブミットされたリビジョンをディポから同期させる場合、ユーザによる変更がディポファイルにより上書きされないよう、Perforceにより衝突解決が要求されます。

Perforceは、デフォルトでは比較プログラムを使用して衝突を検出します。サードパーティの比較プログラムを設定することもできます。詳細については、ファイル内容を比較するを参照してください。

衝突を解決して変更をサブミットするには、以下の手順を実行します。

  1. ファイル(例えば、p4 sync //depot/dev/main/jam/...)を同期させます。Perforceは衝突を検出し、衝突しているファイルの解決をスケジュールします。

  2. p4 resolveコマンドを発行して、衝突を解決します。解決オプションについて詳しくは、衝突解決のオプションを参照してください。

  3. 生成されたファイルを検査します(コードをコンパイルし、稼働を確認するなどして)。

  4. ファイルを含むチェンジリストをサブミットします。

Note

マージ対象の3つのファイルリビジョンのいずれかがテキストではなくバイナリである場合、3ウェイマージを行うことはできません。代わりに、p4 resolveにより2ウェイマージが実行されます。ファイルの衝突する2つのバージョンが表示されるので、どちらかを選択するか、いずれか1つをワークスペースで編集してからチェンジリストをサブミットします。

Your、theirs、base、mergeの各ファイル

p4 resolveコマンドではマージ処理において次の用語が使用されます。

ファイルリビジョン

解説

yours

クライアントワークスペースにある、変更を含むファイルのリビジョン。

theirs

他のユーザにより編集されyoursと衝突している、ディポ内のリビジョン。(通常は最新リビジョンですが、p4 syncを使って別のリビジョンによる衝突解決のスケジュールが可能です。)

base

yoursとtheirsを編集する元となったディポ内のファイルリビジョン(直近の共通祖先となるファイル)。

merge

Perforceによりtheirsyoursbaseから生成されるファイル。

result

衝突解決プロセスの最終結果となるファイル。

衝突解決のオプション

衝突を解決する方法を指定するには、p4 resolveコマンドを発行します。それにより衝突解決がスケジュールされたファイルごとに、ダイアログが表示されます。ダイアログには、変更したファイルと衝突するリビジョンとの相違点が記述されます。例:

p4 resolve //depot/dev/main/jam/command.c
c:\bruno_ws\dev\main\jam\command.c - merging //depot/dev/main/jam/command.c#9

Diff chunks: 4 yours + 2 theirs + 1 both + 1 conflicting
Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) e:

各ファイルの組の相違点がp4 resolveにより要約されます。行のまとまり(チャンク)はyourstheirsbaseファイルでそれぞれ異なる場合があります。チャンクの形態を以下に示します。

  • 差分: yourstheirsbaseの3つのファイルのうち2つが異なる場合

  • 衝突: 3つのファイルすべてが異なる場合

上記の例において、

  • 4つのチャンクがtheirsbaseとで同一であるが、yoursでは異なる。

  • 2つのチャンクがyoursbaseとで同一であるが、theirsでは異なる。

  • 1つのチャンクがyourstheirsで同様に変更されている。

  • 1つのチャンクがyourstheirsbaseで異なっている。

Perforceが推奨する選択がコマンドラインの終わりに表示されます。ENTERキーを押すか、Acceptを選択すると、推奨された選択が実行されます。

以下に示す3つの基本的な方法により衝突解決が可能です。

上記のオプションは対話式オプションです。受け入れたいファイルが分かっている場合は、p4 resolveコマンドラインで解決オプションを指定することもできます。詳細については、衝突解決のためのコマンドラインオプションを参照してください。解決済みであるがサブミットされていないファイルを再度解決するには、p4 resolveコマンドの発行時に-fオプションを指定します。ファイルのサブミット後は、再度解決を行うことはできません。次のセクションでは、解決オプションについてさらに詳しく説明します。

yours、theirs、またはmergeを承諾する

ファイルを変更せずに受け入れるには、以下のオプションの1つを指定します。

オプション

解説

意味

a

推奨されるファイルを承諾

  • theirsbaseと同じである場合、yoursを受け入れます。

  • yoursbaseと同じである場合、theirsを受け入れます。

  • yourstheirsbaseと異なり、yourstheirsに衝突がない場合、mergeを受け入れます。

  • それ以外の場合yourstheirsとの間で衝突があるため、このファイルをスキップします。

ae

編集結果(edit)を承諾

(p4 resolveダイアログからeを選択して)mergeファイルが選択されていれば、編集後のバージョンをクライアントワークスペースに受け入れます。クライアントワークスペース内のバージョンは上書きされます。

am

mergeを承諾

mergeを衝突解決後のリビジョンとしてクライアントワークスペースに受け入れます。クライアントワークスペース内のバージョンは上書きされます。

at

theirsを承諾

theirsを衝突解決後のリビジョンとしてクライアントワークスペースに受け入れます。クライアントワークスペース内のバージョンは上書きされます。

ay

yoursを承諾

yoursを衝突解決後のリビジョンとしてクライアントワークスペースに受け入れます。theirsに加えられた変更は無視されます。

yourstheirsedit、またはmergeを受け入れると変更が上書きされるため、生成されたマージファイルがディポにサブミットしたい内容と正確に一致しない場合があります。必要な変更のみを正しくサブミットするには、マージプログラムを使用するか、マージファイルを編集してください。

マージファイルを編集する

マージファイルを編集してファイルを解決するには、eオプションを選択します。Perforceはデフォルトのテキストエディタを起動し、マージファイルを表示します。マージファイルでは、差分および衝突が次のフォーマットで表示されます。

>>>> ORIGINAL file#n
(text from the original version)
==== THEIR file#m
(text from their file)
==== YOURS file
(text from your file)
<<<<

衝突と差分のある箇所を見つけるには、差分マーカ「>>>>」を探し、テキストの該当部分を編集します。theirsの変更箇所を調べ、自分が行った変更と矛盾しないことを確認します。保存する前に必ず、すべての衝突マーカを削除してください。必要な変更を行った後、ファイルを保存します。p4 resolveプロンプトにおいて、aeを選択します。

デフォルトでは、yoursファイルとtheirsファイルとの衝突のみがマークされます。差分マーカがすべての差分を生成するようにするには、p4 resolveコマンドの発行時に-vオプションを指定します。

衝突解決のためのマージ

マージプログラムによりyours、theirs、baseの各ファイル間の差分が表示されるため、そこから変更の選択や編集を行って必要な結果ファイルを作成することができます。マージプログラムを構成するには、P4MERGEに対象のプログラムを設定します。解決処理中にマージプログラムを使用するには、mオプションを選択します。特定のマージプログラムの使用に関して詳しくは、オンラインヘルプを参照してください。

マージを行ったら、結果を保存してマージプログラムを終了します。p4 resolveプロンプトにおいて、amを選択します。

解決オプションの全リスト

p4 resolveコマンドには、次のオプションがあります。

オプション

操作

説明

?

ヘルプ

p4 resolveのヘルプを表示します。

a

自動的に承諾

自動的に選択されたファイルを受け入れます。

  • theirsbaseと同じである場合、yoursを受け入れます。

  • yoursbaseと同じである場合、theirsを受け入れます。

  • yourstheirsbaseと異なり、yourstheirsに衝突がない場合、mergeを受け入れます。

  • それ以外の場合yourstheirsとの間で衝突があるため、このファイルをスキップします。

ae

編集結果(edit)を承諾

(p4 resolveダイアログからeを選択して)mergeファイルが選択されていれば、編集後のバージョンをクライアントワークスペースに受け入れます。クライアントワークスペース内のバージョンは上書きされます。

am

mergeを承諾

mergeを衝突解決後のリビジョンとしてクライアントワークスペースに受け入れます。クライアントワークスペース内のバージョンは上書きされます。

at

theirsを承諾

theirsを衝突解決後のリビジョンとしてクライアントワークスペースに受け入れます。クライアントワークスペース内のバージョンは上書きされます。

ay

yoursを承諾

yoursを衝突解決後のリビジョンとしてクライアントワークスペースに受け入れます。theirsに加えられた変更は無視されます。

d

Diff

mergeyoursとの差分を表示します。

dm

merge差分

mergebaseとの差分を表示します。

dt

theirs差分

theirsbaseとの差分を表示します。

dy

yours差分

yoursbaseとの差分を表示します。

e

merge編集

Perforceによって生成された予備マージファイルを編集します。

et

theirs編集

クライアントリビジョンが衝突するディポ内のリビジョン(通常は最新リビジョン)を編集します。この編集は読み取り専用です。

ey

yours編集

現在ワークスペースにあるファイルリビジョンを編集します。

m

マージ

コマンドP4MERGE base theirs yours mergeを実行します。このオプションを実行するには、P4MERGEにサードパーティのプログラムの名前を設定しなければなりません。このプログラムでは、最初の3つのファイルをマージし、その結果を4番目のファイルに書き込むものとします。

s

スキップ

このファイルをスキップし、衝突解決がスケジュールされたままにします。

Note

mergeファイルはPerforceサービスにより生成されますが、dydtdmdの各オプションで表示される差分は、ワークステーションの比較プログラムにより生成されます。衝突解決でdオプションを選択したときに他の比較プログラムが実行されるように設定するには、P4DIFFを設定します。詳細については、ファイル内容を比較するを参照してください。

Example 28. ファイルの衝突を解決する

Jam readmeファイルに対してブルーノが行った作業とアールが行った作業との衝突を解決するため、ブルーノがp4 resolve //depot/dev/main/jam/READMEと入力すると、以下のように表示されました。

Diff chunks: 0 yours + 0 theirs + 0 both + 1 conflicting
Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) e: e

ブルーノは、彼とアールがファイルに対して衝突する変更を加えたことを確認しました。そこで彼はマージファイルを編集するためにeを入力して、差分マーカ「>>>>」を探します。すると以下のテキストが表示されます。

Jam/MR (formerly "jam - make(1) redux")
/+\
>>>> ORIGINAL README#26
    +\ Copyright 1993, 1997 Christopher Seiwald.
==== THEIRS README#27
    +\ Copyright 1993, 1997, 2004 Christopher Seiwald.
==== YOURS README
    +\ Copyright 1993, 1997, 2005 Christopher Seiwald.
<<<<
    \+/

ブルーノとアールは異なる著作権登録年を記述して更新しました。ブルーノはマージファイルを編集してヘッダを正しく修正し、エディタを終了して、amと入力します。編集されたマージファイルがクライアントワークスペースに書き込まれたので、彼は次のファイルの衝突解決に進みます。

衝突解決においてファイルの1バージョンが受け入れられると、ワークスペース内のファイルは上書きされるので、新しいクライアントファイルをディポにサブミットする必要があります。ファイルの衝突解決が完了してからサブミットするまでの間に、そのファイルの新しいバージョンがサブミットされると、新しい衝突が発生する場合があります。衝突解決を行う前にファイルをロックすることにより、この問題を回避することができます。詳細については、ファイルをロックするを参照してください。

ブランチされたファイル、削除、移動、ファイルタイプ変更を解決する

反映実行後に関連ファイルの内容の変更を突き合わせる以外に、他の種類の変更をどのように処理するかを決めることができます。例:

  • あなたがメインラインでheader.ccを編集しているとき、同僚がそれをリリースブランチから削除しました(またはその逆)。あなたはリリース・ブランチでの修正をmainに反映して戻しました。衝突解決の間に、あなたはheader.ccをメインラインから削除するか、またはheader.ccをメインラインに保持し、リリースブランチでの操作を無視するかを決めることができます。

  • ある開発者が、開発ブランチのソースファイルにRCSキーワードを実装して、それらのPerforceファイルタイプをtextからtext+kに変更しました。リリース管理者は、新しい機能を開発ブランチからメインラインに反映させたいのですが、メインラインでのキーワード拡張を有効にしたくはありません。衝突解決の間に、リリース管理者はファイルタイプの変更を無視することを選択できます。

  • ファイルheader.ccは、mainからrelへとブランチされます。その後、このファイルはmainにおいてheaderx.ccにリネームされ、リリースブランチではheadersサブフォルダに移動されました。

以下に、関連ファイルへの内容以外の変更を衝突解決する方法を説明した簡単な事例を示します。反映元ファイルが反映先ファイルにブランチされ、以下に示すように変更が行われた後、反映元ファイルを反映先ファイルへと反映します。結果を選択するため、解決オプションにat (「Theirsを承諾」)またはay (「Yoursを承諾」)を以下のとおり指定します。

  • 反映元が編集され、反映先が削除されている場合: atオプションは反映元ファイルを反映先ブランチに再追加します。ayオプションでは、ファイルが反映先ブランチで削除されたままになります。

  • 反映元が削除され、反映先が編集されている場合: atオプションでは、ファイルが反映先ブランチで削除されます。ayオプションでは、編集された内容が反映先ブランチに保持されます。

  • 反映先ファイルがブランチ後に移動された場合: atオプションは反映先ファイルを反映元ファイルの名前と場所に移動させます。ayオプションは反映先ファイルの名前と場所を保持します。

  • 反映元ファイルのファイルタイプがブランチ後に変更された場合: atオプションは変更を反映先に伝播します。ayオプションでは、反映先のファイルタイプを未変更のままにします。別々のファイルタイプが競合しない場合は、それらを組み合わせることを選択できます。

  • 競合する方法でファイルが移動またはリネームされている場合: パスとファイル名を選択するよう要求されます。例:

    Resolving move to //depot/rel/headerx.cc
    Filename resolve:
    at: //depot/rel/headerx.cc
    ay: //depot/rel/headers/header.cc
    am: //depot/rel/headers/headerx.cc
    

デフォルトでは、p4 resolveコマンドはすべての種類の変更、内容、および内容以外を解決します。衝突解決する操作の種類を制限するには、-Aオプションを以下のとおり指定します。

オプション

解決される内容

-Aa

p4 attributeにより設定された属性を解決

-Ab

反映元が編集され、反映先が削除される反映

-Ac

ファイルコンテンツの変更と操作を解決

-Ad

反映元が削除され、反映先が編集される反映

-Am

リネームと移動

-At

ファイルタイプの変更

-AQ

文字セットの変更

複数の種類の衝突解決を実行するには、オプションを組み合わせます(例: -Abd)。デフォルトでは、衝突解決はファイルごとに対話形式で実行されます。特定の操作に対して同じ結果を指定して(例えばすべての移動を伝播するなど)、入力要求を抑止するには、目的のオプションをコマンドラインに含めてください。例: p4 resolve -Am -at

衝突解決のためのコマンドラインオプション

p4 resolveオプションに次のオプションを付けると、衝突解決を対話形式ではなく直接実行できます。p4 resolveコマンドでこれらのオプションの1つを指定すると、ファイルは以下の表に示すように解決されます。

オプション

解説

-a

自動的に選択されたファイルを受け入れます。

-ay

yoursを受け入れます。

-at

theirsを受け入れます。クライアントワークスペース内のファイルリビジョンがディポからの最新リビジョンで上書きされ、変更を元に戻すことができないため、このオプションを使用するときは注意が必要です。

-am

以下のロジックに従って、推奨されるファイルリビジョンを受け入れます。

  • theirsbaseと同じである場合、yoursを受け入れます。

  • yoursbaseと同じである場合、theirsを受け入れます。

  • yourstheirsbaseと異なり、yourstheirsに衝突がない場合、mergeを受け入れます。

  • それ以外の場合yourstheirsとの間で衝突があるので、このファイルは解決されずにスキップされます。

-af

衝突箇所が残っていても、推奨されるファイルリビジョンを受け入れます。このオプションを使用する場合、結果のファイルをワークスペースで編集し、すべての差分マーカを除去する必要があります。

-as

以下のロジックに従って、推奨されるファイルリビジョンを受け入れます。

  • theirsbaseと同じである場合、yoursを受け入れます。

  • yoursbaseと同じである場合、theirsを受け入れます。

  • それ以外の場合は、このファイルはスキップされます。

Example 29. 衝突するファイルの特定リビジョンを自動的に受け入れる

ブルーノは、/docにある文書ファイルを編集しており、そのいくつかが衝突解決を必要とすることを知っています。ブルーノは、p4 sync doc/*.guideと入力します。ディポ内のファイルと衝突するこれらのファイルすべての衝突解決がスケジュールされます。

ブルーノはさらにp4 resolve -amと入力します。スケジュールされた衝突解決に関するマージファイルがすべて生成され、そのうち行セット衝突を含まないマージファイルが彼のクライアントワークスペースに書き込まれます。ブルーノはなお、他の衝突するファイルについて手動で解決を行う必要がありますが、その作業量はかなり軽減されました。

衝突解決のレポートコマンド

次に示すレポートコマンドは、ファイルの衝突解決の際に役立ちます。

コマンド

意味

p4 diff [filenames]

ワークスペース内にあるファイルリビジョンと最後に同期したリビジョンとを比較し、加えられた変更を表示します。

p4 diff2 file1 file2

2つのディポファイルを比較します。指定ファイルには任意のファイルリビジョンを選択でき、異なるファイルのリビジョンであっても構いません。

ディポファイルを比較する場合、Perforceサービスは独自の比較プログラムを使用します。P4DIFFで設定された比較プログラムは使用されません。

p4 sync -n [filenames]

指定された同期の結果をプレビューし、衝突していて解決が必要なファイルをリスト表示します。

p4 resolved

衝突解決された後にまだサブミットされていないファイルをレポートします。

ファイルをロックする

ファイルを作業状態にした後、そのファイルをロックして、自分がサブミットする前に他のユーザがサブミットできないようにすることができます。ファイルをロックすると衝突を防止することができますが、ファイルのロックは他のチームメンバーがそのファイルを操作できない可能性があります。

ファイルをロックして、多重衝突解決を防止する

ファイルロックをしない限り、衝突解決プロセスが終了する保証はありません。次のシナリオは、この問題を具体的に表現しています。

  1. ブルーノがファイルを編集目的で作業状態にします。

  2. 次にゲイルが同じファイルを、自分のクライアントにおいて編集目的で作業状態にします。

  3. ブルーノとゲイルは、ファイルの各自のクライアントワークスペースバージョンを編集します。

  4. ブルーノは当該ファイルを含むチェンジリストをサブミットし、このサブミットが成功します。

  5. ゲイルも自分のファイルバージョンを含むチェンジリストをサブミットしますが、そのファイルがディポの新しいファイルと衝突するため、サブミットは失敗します。

  6. ゲイルが衝突解決を始めます。

  7. ブルーノが同じファイルの新しいバージョンを編集し、サブミットします。

  8. ゲイルが衝突解決を終え、サブミットしようとします。サブミットは失敗し、今度はブルーノの最新ファイルとマージしなければなりません。

    <等々>

このような問題を解決するため、ファイルをロックすることができます。手順は次のとおりです。

  1. 衝突解決をスケジュールする前に、ファイルをロックします。

  2. ファイルを同期させます(衝突解決をスケジュールするため)。

  3. ファイルの衝突を解決します。

  4. ファイルをサブミットします。

  5. チェンジリストのサブミットが成功すると、Perforceは自動的にファイルのロックを解除します。

UNIXにおいて作業状態にありロックされているファイルをリストするには、次のコマンドを発行します。

p4 opened | grep "*locked*"

多重チェックアウトを防止する

一度の1人のユーザだけがファイルを操作できるようにするには、ファイルタイプ修飾子+l (排他的作業状態)を使用します。例:

p4 reopen -t binary+l file

排他的ロックにより同時並行開発ができなくなりますが、マージや衝突解決をする意味がない一部のファイルタイプ(通常はバイナリファイル)については、複数のユーザが同時にファイルの操作を行わないようにすることで衝突を回避できます。

Perforce管理者は、p4 typemapコマンドを使用して、特定のタイプ(例えば、//depot/.../*.gifとしてすべての.gifファイルを指定)を持つすべてのファイルについて、一度に1人のユーザだけが作業状態にできるように設定することができます。詳細については、『P4コマンドリファレンス』を参照してください。

p4 lock+lとの違いは次のとおりです。p4 lockの場合は誰でもファイルを編集目的で作業状態にすることができますが、ファイルをロックした当人のみがそのファイルをサブミットできます。これに対し、ファイルタイプ+lのファイルは、一度に複数のユーザが作業状態にすることはできません。