29

moduleSubversion リポジトリのサブディレクトリ (ここで示す) を、完全な履歴を持つ 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が作成されてデータが入力されますが、最新のコミット以降の Subversion 履歴svn copyはインポートされません (作成された git リポジトリには、何百ものコミットがあると予想していたときに、最終的に 2 つのコミットしかありません)。

問題は、この状況で完全な Subversion 履歴をエクスポートする方法です。

考えられる原因

  1. エラーメッセージを検索すると、これが見つかりました: git-svn anonymous checkout fails with -s which linked to this Subversion issue: http://subversion.tigris.org/issues/show_bug.cgi?id=3242

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

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

  3. Dejay Clayton の回答によると、ブランチとタグ svn url の最も深いサブディレクトリ コンポーネントが同じ名前 (たとえば.../tags/release/1.0.0.../branches/release-candidates/1.0.0) の場合、このエラーが発生する可能性があります。

4

5 に答える 5

10

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

たとえば、タグcandidates/1.0.0とがあり、サブディレクトリが との両方に表示されるreleases/1.0.0ため、文書化されたエラーが発生しました。1.0.0candidatesreleases

git-svn ドキュメントごと:

複数の --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

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

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

# 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
于 2015-06-25T21:08:36.870 に答える
6

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

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

--no-minimize-url 

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

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

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

于 2013-02-26T14:12:21.800 に答える
2

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

彼 (および私) がパス内のスペースによって引き起こされた問題に対して、彼の解決策が有効であることを確認できます。心配するブランチやタグがまったくないことを除いて、同じ要件(履歴を持つSVNリポジトリから単一のモジュールを複製する)がありました。

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

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

以降のコマンドgitgit svnコマンドはエラーをまったくスローしていません。ありがとうジェフ!

于 2013-09-06T19:48:36.337 に答える
1

【これはオリジナルのポスター発言文です。以下は質問の更新でしたが、ケースが解決したので、私の好みには不十分でしたが、より良い解決策がない回答として投稿します.]

私はこれが好きではありませんが、最終的clone に分割initして ( 、)の間fetchを編集しました。.git/configrepopath=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/*

実際に必要なHEADURL は別の 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基本的にgitの意味を持っているように見えるので、おそらく「トランク」に言うことができたでしょうHEAD(トランク、ブランチ、タグのSubversionの概念には深い技術的根拠はなく、問題です社会的に合意された慣習の)。

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

注-3 : svn2gitを以前に読んだときは、ラッパーのようにgit-svn見えましたが、動機がわかりませんでしたが、タグの乱雑なプレゼンテーションを見て、今ではそれを理解しています。svn2gitこれをもう一度やり直す必要がある場合は、次回も試します。

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

  1. Subversion ブランチには本質的な技術的意味はありません ( Subversion のブランチタグは、バージョン管理されたファイル システム コピーの社会的に合意されたラベルにすぎず、「標準」またはその他の方法でコピーが行われる社会的に合意された規則と一緒になっています。トランクにも技術的な意味はありません) 。 、 と
  2. git svn実装は、Subversion の社会的慣習にある程度従うことを厳密に前提としています (Subversion リポジトリ全体ではなくサブディレクトリのみを移行する場合は、これは不可能です)。

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

于 2014-03-05T04:36:17.367 に答える