web-dev-qa-db-ja.com

「git svn clone」が失敗した場合の回避策(完全な履歴が必要)

Subversionリポジトリのサブディレクトリ(ここではmoduleと表記)を完全な履歴を持つgitリポジトリに変換したいと思います。私のSubversionリポジトリの履歴には、多くのsvn copy操作(Subversionではブランチと呼びます)があります。リリースポリシーでは、各リリースまたは他のブランチが作成された後、古いURLは未使用のままにされ、新しいURLが作業を含むために古いURLを置き換えます。

最適には、私の読書では、これでうまくいくようです:

$ git svn clone --username=mysvnusername --authors-file=authors.txt \
    --follow-parent \
    http://svnserver/svn/src/branches/x/y/apps/module module

branches/x/y/は最新のブランチを表します)。しかし、次のようなエラーが発生しました。

W: Ignoring error from SVN, path probably does not exist: (160013): Filesystem has no item: '/svn/src/!svn/bc/100/branches/x/y/apps/module' path not found
W: Do not be alarmed at the above message git-svn is just searching aggressively for old history.

更新:上記にオプション--no-minimize-urlを追加しても、エラーメッセージは削除されません。)

ディレクトリmoduleが作成されて入力されますが、最新のsvn copyコミットを過ぎたSubversionの履歴はインポートされません(作成されたgitリポジトリは、何百もの期待どおりに2つのコミットしかありません)。

問題は、この状況が存在する場合に、完全なSubversion履歴をエクスポートする方法ですか?

考えられる原因

  1. エラーメッセージを検索したところ、次のことがわかりました: git-svn anonymous checkout failed with -s これは、このSubversionの問題にリンクしています: http://Subversion.tigris.org/issues/show_bug .cgi?id = 3242

    私が読んで理解したことですが、Subversion 1.5では、クライアントがリポジトリにアクセスする方法が変わっています。新しいSubversionでは、URLパスのスーパーディレクトリへの読み取りアクセスがない場合(私にとってはsvn ls http://svnserver/svn403 Forbiddenで失敗します)、いくつかのSubversion操作で失敗します。

  2. ジェフフェアリーは彼の回答で、Subversion URLのスペースもこのエラーメッセージを引き起こす可能性があると指摘しています(ユーザーOwenによって確認されました)。彼の解決策を見て、あなたのgit svn cloneが同じ理由で失敗した場合に、彼がどのようにケースを解決したかを確認してください。

  3. Dejay Claytonは彼の回答で、ブランチとタグのsvn URLの最も深いサブディレクトリコンポーネントの名前が同じ場合(例:.../tags/release/1.0.0.../branches/release-candidates/1.0.0)、このエラーが発生する可能性があることを明らかにしています。

26
FooF

ブランチまたはタグ内に同じ名前のサブディレクトリがあると、この問題に遭遇しました。

たとえば、candidates/1.0.0およびreleases/1.0.0、そしてサブディレクトリ1.0.0candidatesreleasesの両方に含まれます。

git-svn docs ごと:

複数の--branchesまたは--tagsを使用する場合、git svnは名前の衝突を自動的に処理しません(たとえば、異なるパスからの2つのブランチが同じ名前である場合、またはブランチとタグが同じ名前である場合)。このような場合は、initを使用してGitリポジトリーをセットアップしてから、最初のフェッチの前に、$ GIT_DIR/configファイルを編集して、ブランチとタグが異なる名前空間に関連付けられるようにします。

したがって、同様の名前のcandidatesおよびreleasesタグが原因で、次のコマンドは失敗しました。

git svn clone --authors-file=../authors.txt --no-metadata \
    --trunk=/trunk --branches=/branches --tags=/candidates \
    --tags=/releases --tags=/tags -r 100:HEAD \
    --prefix=Origin/ \
    svn://example.com:3692/my-repos/path/to/project/

次の一連のコマンドが機能しました。

git svn init --no-metadata \
    --trunk=/trunk --branches=/branches --tags=/tags \
    --prefix=Origin/ \
    'svn://example.com:3692/my-repos/path/to/project/'

git config --add svn-remote.svn.tags \
    'path/to/project/candidates/*:refs/remotes/Origin/tags/Candidates/*'

git config --add svn-remote.svn.tags \
    'path/to/project/releases/*:refs/remotes/Origin/tags/Releases/*'

git svn fetch --authors-file=../authors.txt -r100:HEAD

branchestags内で他の競合がなかったため、これが機能したことに注意してください。もしあったなら、私は同様にそれらを解決しなければならなかっただろう。

SVNリポジトリのクローンを作成した後、次の手順を実行して、SVNタグをGITタグに変換しました。 trunkmasterに変換します。他の参照をブランチに変換します。リモートパスを再配置します。

# Make tags into true tags
cp -Rf .git/refs/remotes/Origin/tags/* .git/refs/tags/
rm -Rf .git/refs/remotes/Origin/tags

# Make other references into branches
cp -Rf .git/refs/remotes/Origin/* .git/refs/heads/
rm -Rf .git/refs/remotes/Origin
cp -Rf .git/refs/remotes/* .git/refs/heads/ # May be missing; that's okay
rm -Rf .git/refs/remotes

# Change 'trunk' to 'master'
git checkout trunk
git branch -d master
git branch -m trunk master
7
Dejay Clayton

完全な答えではありませんが、おそらく欠けているスニペットです(私も移行に興味があるので、パズルのその部分を見つけました)。

git-svnのドキュメント を見ると、次のオプションがあります。

--no-minimize-url 

複数のディレクトリを追跡する場合(--stdlayout、-branches、または--tagsオプションを使用)、git svnはSubversionリポジトリのルート(または許可されている最高レベル)に接続しようとします。このデフォルトでは、プロジェクト全体がリポジトリ内で移動された場合に履歴の追跡が改善されますが、読み取りアクセス制限が設定されているリポジトリで問題が発生する可能性があります。 --no-minimize-urlを渡すと、git svnが上位レベルのディレクトリに接続することなく、URLをそのまま受け入れることができます。このオプションは、追跡されるURL /ブランチが1つだけの場合、デフォルトではオフになっています(ほとんど役に立ちません)。

これはあなたが持っている状況に合うので、git svnは、ディレクトリツリーの上位レベル(ブロックされます)を読み取ろうとしません。

少なくともあなたはそれを試すことができます...

6
mliebelt

私は最近、SVNリポジトリの長いリストをGitに移行しましたが、最後にこの問題が発生しました。私たちのSVN構造はかなりだらしないので、--no-minimize-urlをかなり使わなければなりませんでした。通常、私は次のようなコマンドを実行します。

$ git svn clone http://[url]/svn/[repo]/[path-to-code] \
            -s --no-minimize-url \
            -A authors.txt

私が実行した最後のいくつかの移行では、URLにスペースが含まれていました。それがスペースなのか他の何かなのかはわかりませんが、同じエラーが表示されていました。必要がない場合は、構成ファイルを変更したくありませんでした。幸い、解決策を見つけることになりました。 -s --no-minimize-urlオプションをスキップして、パスを異なる方法で明示的に宣言することにしました。

$ git svn clone http://[url]/svn/[repo]/ \
            --trunk="/[path-to-code]/trunk" \
            --branches="/[path-to-code]/branches" \
            --tags="/[path-to-code]/tags" \
            -A authors.txt \
            --follow-parent
  • 例から--follow-parentを追加しましたが、違いがあったかどうかもわかりません。
  • これらのリポジトリにはスペースがあり、トランク/ブランチ/タグパスの周囲の""に注意してください。
2
Jeff Fairley

[これはジェフフェアリーの回答に対するコメントであるべきだと思いますが、それを投稿するという評判はありません。元の投稿者がアプローチが機能したことの確認を求めていたので、回答として提供しています。]

彼の解決策は、パス内のスペースが原因で発生した問題を解決できることを確認できます。私は同じ要件を持っていました(履歴付きのSVNリポジトリから単一のモジュールを複製します)。ただし、ブランチやタグをまったく気にする必要がありませんでした。

URLでモジュールへのフルパスを提供するいくつかの順列を試しました(たとえば、--no-minimise-urlを使用し、--trunkまたは--stdlayoutを指定して)成功しませんでした。私にとっての結果は通常、完全な履歴ログを含むgitリポジトリでしたが、ファイルはまったくありませんでした。これは、FooFで発生したのと同じ問題である場合とそうでない場合がありますが(SVNでの読み取りアクセスがない)、モジュールへのパスにスペースが含まれていることが原因でした。

URLとしてSVNリポジトリベースのみを使用して再試行すると、--trunkのモジュールへのパスは問題なく動作しました。その後、私の.git/configは次のようになります。

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        loggallrefupdates = true
        symlinks = false
        ignorecase = true
        hideDotFiles = dotGitOnly
[svn-remote "svn"]
        url = https://[url]/svn/[repo]
        fetch = trunk/[path-to-code]:refs/remotes/trunk
[svn]
        authorsfile = ~/working/authors-transform.txt

後続のgitおよびgit svnコマンドはエラーをまったくスローしません。ジェフありがとう!

1
Owen

[これはオリジナルのポスターです 話し中 書き込み。以下は以前は質問に対する更新でしたが、それはケースを解決したので-私の好みには不十分ですが-より良い解決策がない回答として投稿します。]

私はこれが好きではありませんが、_cloneinitfetchに分割して、.git/configを(repopath=apps/modulegitreponame=module)の間で編集すると、

$ git svn init--username=mysvnusername \
            --branches=/src/branches/ \
            --trunk=/src/trunk/${repopath} \
            --tags=/src/tags/ \
            http://svnserver/svn/src ${gitreponame}
$ cd ${gitreponame}
$ sed -i.bak "s|*:|*/${repopath}:|" .git/config
$ git svn fetch --authors-file=../authors.txt --follow-parent

git svnを使用してサブディレクトリを移行するためのブランチを指定する方法が見つからなかったため、.git/configファイルを編集しました。次の統一されたdiffは、sedを使用した編集の効果を示しています。

 [svn-remote "svn"]
        url = http://svnserver/svn/src
        fetch = trunk/apps/module:refs/remotes/trunk
-       branches = branches/*:refs/remotes/*
-       tags = tags/*:refs/remotes/tags/*
+       branches = branches/*/apps/module:refs/remotes/*
+       tags = tags/*/apps/module:refs/remotes/tags/*

実際に必要なHEADが別のURLにあったため、[svn-remote]に別の.git/configセクションを追加するだけで終了しました。

+ [svn-remote "svn-newest"]
+       url = http://svnserver/svn/src
+       fetch = branches/x/y/apps/module:refs/remotes/trunk
+       branches = branches/*/apps/module:refs/remotes/*
+       tags = tags/*/apps/module:refs/remotes/tags/*

(実際の実験では、最初のフェッチで取得されなかったブランチもここに追加しました)、再度フェッチします。

$ git svn fetch --authors-file=../authors.txt --follow-parent svn-newest

このようにして、Subversionの完全な履歴を新しく生成されたgitリポジトリに移行する作業を終了しました。

注1branches/x/y/apps/moduleの「トランク」の意味は基本的には意味があるように見えるので、おそらく「トランク」にgit-svnと指示しただけかもしれませんof git HEAD(トランク、ブランチ、タグのSubversionの概念には深い技術的根拠がなく、社会的に合意された慣例の問題です).

注2:おそらく--follow-parentgit svn fetchには必要ありませんが、私は知る方法も実験する方法もありません。

注3:以前の svn2git の読み取り中、git-svnのラッパーのようですが、モチベーションを確認できませんでしたが、乱雑なタグのプレゼンテーションを見ると、ちょっとわかりました。もう一度やり直さなければならなかった場合は、svn2gitを次に試します。

P.S。これは、操作を行うにはやや扱いにくい方法です。ここでの二次的な問題(なぜ外部による.git/configの編集が必要だったのか)は

  1. Subversionブランチには、本質的な技術的な意味はありません(ブランチおよびタグSubversionのタグは、単にバージョン化されたファイルシステムコピーの合意されたラベルコピーが行われる「標準」またはその他の社会的に合意された規約-trunkにも技術的な意味はありません)、および
  2. git svnの実装では、ソーシャルSubversionの慣例がある程度遵守されていることを厳密に想定しています(Subversionリポジトリ全体ではなく、サブディレクトリを移行するだけの場合は不可能です)。

TODO:.git/configに関連するため、ここでgit svnファイルのフォーマットを説明しておくと役立ちます。元の回答を書いた年)上記の[svn-remote "svn-newest"]の意味がわかりません。また、スクリプトを作成することでアプローチを自動化することもできますが、これは現在の問題への関心を超えており、元のSubversionリポジトリや問題の複製にアクセスできません。

1
FooF