SubversionとApacheを組み合わせたソースコードリポジトリの場合、URLエンコードが原因でおかしな動きをすることがあります。
現象
ローカルの作業エリアでは、差分やステータスを見るのは問題ないのですが、コミットしようとすると下記のようなエラーが出ます。
$ echo bbb >> test.txt $ svn st M test.txt $ svn diff Index: test.txt =================================================================== --- test.txt (リビジョン 5) +++ test.txt (作業コピー) @@ -1 +1,2 @@ aaa +bbb $ svn commit -m "update" 送信しています test.txt ファイルのデータを送信しています .svn: コミットに失敗しました (詳しい理由は以下のとおりです): svn: '/svn/sandbox/jp/%E3%83%86%E3%82%B9%E3%83%88/test.txt' の MERGE レスポンスはマージ先 ('/svn/sandbox/jp/%e3%83%86%e3%82%b9%e3%83%88') の子ノードではありません $
再度、コミットしようとするとリポジトリが更新されているのでupdateするように言われます。
$ svn commit -m "update" 送信しています test.txt svn: コミットに失敗しました (詳しい理由は以下のとおりです): svn: ファイルまたはディレクトリ 'test.txt' はリポジトリ側と比べて古くなっています。update を実行してみてください svn: resource out of date; try updating $
updateすると、なぜかマージされたGというステータスで更新されます。
$ svn update G test.txt リビジョン 6 に更新しました。 $
なぜでしょう?
原因
チェックアウトしたファイルは、”http://svn.local/svn/sandbox/jp/テスト/”という全角文字を含むURLでした。
$ svn ls http://svn.local/svn/sandbox/jp/テスト/ test.txt $
実は、この作業エリアをチェックアウトした人がURLを間違えないようにブラウザを使ってアクセスできることを確認し、ブラウザのアドレスバーからURLをコピペしてチェックアウトしていました。
ところが利用するブラウザによってアドレスバーのURLのコピーが異なります。
手元にあるブラウザで試してみると…
ブラウザ | コピーされる文字列 | 例 |
Safari 4.0.4 | 日本語文字列 | http://svn.local/svn/sandbox/jp/テスト/ |
firefox 3.5 | URLエンコードでアルファベット大文字 | http://svn.local/svn/sandbox/jp/%E3%83%86%E3%82%B9%E3%83%88/ |
IE 7 | URLエンコードでアルファベット小文字 | http://svn.local/svn/sandbox/jp/%e3%83%86%e3%82%b9%e3%83%88/ |
RFCでは、URLエンコードは、一文字毎に%XX(XXは、1文字の16進数文字列)となっておりA〜Fまでの大文字小文字の指定はなく、どちらかと言えば大文字を使うのが良いとされているようです。
そのためApacheは、どのURLでも同じコンテンツを表示します。
$ svn ls http://svn.local/svn/sandbox/jp/テスト test.txt $ svn ls http://svn.local/svn/sandbox/jp/%E3%83%86%E3%82%B9%E3%83%88/ test.txt $ svn ls http://svn.local/svn/sandbox/jp/%e3%83%86%e3%82%b9%e3%83%88/ test.txt $
サーバ側は、URLの違いを気にしないためコミットのリクエストを受け付けてコミット自体は成功します。
一方で、Subversionクライアントは、大文字小文字を区別し、かつコミット時にはURLエンコードは大文字が望ましいという慣例に従っているため小文字のURLエンコードでチェックアウトしていた場合、URLが違うと認識して今回のような現象となります。
判別方法
判別方法は、.svn/entriesに記録されているチェックアウトもとのURLで確認できます。
下記のように小文字を使ってURLエンコードされていたらアウトです。
$ grep http .svn/entrieshttp://svn.sa.local/svn/sandbox/jp/%e3%83%86%e3%82%b9%e3%83%88$http://svn.sa.local/svn/sandbox
対処方法
コミットでエラーが出ますが、コミット自体は正しく行われます。
なので、他のディレクトリに正しいURL(全角文字列か大文字のURLエンコード)でチェックアウトして、コミットが正しく反映されているかdiffします。
問題なければ、小文字のURLエンコードの作業ディレクトリは、削除すれば対処できます。