CVS/Subversionを使ったバージョン管理(後編:SVNを使ったバージョン管理) 4ページ

競合の解消

 もし自分がコミットしたファイルがすでに他人によって変更され、かつ先にコミットされていた場合、コミット時にメッセージが表示され、コミットに失敗する。この場合、まずアップデートを実行して他人による変更点を取り込み、競合を解消させた上で再度コミットを行う必要がある。

 下記は、コミット時に競合が明らかになり、コミットに失敗した例だ。この例では、「echo.pl」というファイルに競合が発生し、そのためにコミットに失敗した、というメッセージが表示されている。この場合、コミット時に入力したメッセージは「svn-commit.tmp」という一時ファイルに保存される。

$ svn ci
Sending        echo.pl
Transmitting file data .svn: Commit failed (details follow):
svn: Out of date: '/echoes/echo.pl' in transaction '2-1'
svn: Your commit message was left in a temporary file:
svn:    '/home/john/Dev/echoes/svn-commit.tmp'

 このように競合が発生したら、まずは「svn update」コマンドを実行し、アップデートを行う。すると、自動的に変更点がチェックされ、可能な限り自動でその変更点がマージされる。ただし、同一の個所に異なる変更が加えられた場合など、自動でのマージに失敗する場合も多数ある。その場合、競合を解決する方法を選択し、場合によっては手動で競合している個所を修正する必要がある。

 たとえば、下記の例は「echo.pl」というファイルに競合が発生している場合の例だ。

$ svn update
Conflict discovered in 'echo.pl'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (h) help for more options:

 ここでキーボードから「df」と入力してEnterキーを押すと変更点の差分が表示される。また、「p」と入力してEnterキーを押すと、競合したファイルがまずリポジトリ内の最新バージョンに更新され、さらに自分が変更を加えた個所をマークアップしてくれる。たとえば、ファイル内で下記のようなマークアップが行われていた場合、「<<<<<<< .mine」から「=======」までの行が自分が変更を加えた内容、「=======」から「>>>>>>> .r<リビジョン番号>」までが最新リビジョンの内容だ。この情報を元にファイルを編集して競合を解消した上で、再度コミットを行えばよい。

my $form_data = {
  'next_url' => '/home.pl',
<<<<<<< .mine
  'email' => '',
  'password' => '',
=======
  'email' => 'hogehoge@foobar.com',
  'password' => 'qwerty',
>>>>>>> .r2
  'stickey' => '1',
};

 なお、update時に競合が発生した場合、競合が発生したファイルごとに「<ファイル名>.mine」および「<ファイル名>.r<変更前リビジョン>」、「<ファイル名>.r<変更後リビジョン>」という3つのファイルが作成される。これらは、それぞれ下記のファイルを内容を含んでいる。

ファイル名 説明
<ファイル名>.mine 自分が変更を加えてコミットを行おうとしたファイル
<ファイル名>.r<変更前リビジョン> 変更を加える前のファイル
<ファイル名>.r<変更後リビジョン> リポジトリ内にある最新リビジョンのファイル
表2 競合発生時に作成されるファイル

 もし自分が加えた変更をすべて反映させたい場合は、「<ファイル名>.mine」を「<ファイル名>」にリネームすればよい。また、リポジトリにある最新版のファイルを優先し、競合する変更をすべて無かったことにするには「<ファイル名>.r<変更後リビジョン>」を「<ファイル名>」にリネームすればよい。

 競合を解消したら、「svn resolved <ファイル名>」コマンドを実行する。これにより、「<ファイル名>.mine」および「<ファイル名>.r<変更前リビジョン>」、「<ファイル名>.r<変更後リビジョン>」が削除され、コミットが実行できる状態になる。