git-svn: `svn switch --relocate`と同等のものは何ですか?


88

git-svnを介してミラーリングしているsvnリポジトリのURLが変更されました。

バニラsvnではあなたはただするでしょうsvn switch --relocate old_url_base new_url_base

git-svnを使用してこれを行うにはどうすればよいですか?

設定ファイルのsvnurlを変更するだけでは失敗します。


あなたはこの答えを試して、おそらく受け入れるべきです:stackoverflow.com/a/4061493/1221661
フリッツ

最新の回答:stackoverflow.com/a/40523789/537554。同じ質問ですが、Gitユーザーの観点から質問されています。
ryenus

回答:


61

これは私の状況をかなりうまく処理します:

https://git.wiki.kernel.org/index.php/GitSvnSwitch

file://プロトコルを使用してクローンを作成し、プロトコルに切り替えたいと思いましたhttp://

url[svn-remote "svn"]セクションで設定を編集したくなります.git/configが、それだけでは機能しません。一般に、次の手順に従う必要があります。

  1. svn-remoteurl設定を新しい名前に切り替えます。
  2. 実行しますgit svn fetch。これはsvnから少なくとも1つの新しいリビジョンをフェッチする必要があります!
  3. svn-remoteurl設定を元のURLに戻します。
  4. git svn rebase -lローカルリベースを実行するために実行します(最後のフェッチ操作で発生した変更を使用)。
  5. svn-remoteurl設定を新しいURLに戻します。
  6. 今、git svn rebase再び動作するはずです。

冒険心のある人は試してみたいかもしれません--rewrite-root


2
公平を期すために、これは実際には失敗し、リポジトリを再クローン化することになりました。svnディレクトリの名前が変更されたときにgitに処理させるのは困難です。
グレッグリンド

もっと詳細な記事を受け入れたいと思いますが、十分に公平で、新しい答えが来るまで受け入れます。
kch 2010年

2
その手順の別の説明は次のとおり
articles

受け入れられた回答で提供されたリンクは古く、現在の新しいリンクは次のとおりです。git.wiki.kernel.org / articles / g / i / t / GitSvnSwitch_8828.html「一般的なケース」に従いましたが、シンプルで本当にうまくいきました。
tcMaster 2011年

2
@TcMaster:私にも役立ちました...しかし、回答にリンクだけを含めるべきではないのはそのためです。リンクは古くなり、役に立たなくなります...コミュニティウィキの回答を追加します。
UncleZeiv 2011年

37

以下が正常に機能するかどうかを確認できます。

  1. svn-remote.svn.rewriteRoot設定ファイルに存在しない場合(.git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. svn-remote.svn.rewriteUUID設定ファイルに存在しない場合:

    git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
    

    currentRepositoryUUIDから入手することができます.git/svn/.metadata

  3. git config svn-remote.svn.url <newRepositoryURL>


素晴らしい-ありがとう、これは私にとってはうまくいきました(経由file://で複製、に切り替えsvn+ssh); この手順では、「svnから少なくとも1つの新しいリビジョンをフェッチする」必要はありません。また、./.git/svn/.metadata後の最初のsvn rebase含まれている<newRepository>としてreposRoot-しかし、これは除去するのに十分ではないrewrite*から鍵を.git/config、したがって、私が理解している限り、これらのキーは永続的にそこに保持する必要があります。
sdaau 2013

1
それは私にも魅力のように働きました。OPはこれを試して、正解として取得する必要があります。
Rafareino 2015年

完璧です。私は歴史に何千ものコミットがある大きなプロジェクトを持っていたので、新しいクローンは歴史を破壊したでしょう(またはチェックアウトするのに本当に長い時間がかかりました)。私が使用svn+ssh://しているのですが、svn-serverがドメインをから.seに変更し.comて内部の名前をサニタイズしました。
ulfR 2016年

私のために御馳走を働いた。数千のコミットがある2年前のリポジトリがあった場合、リポジトリは新しいホストに移動されたため、(恐ろしい)完全なsvnクローンが回避されました。
デビッドビクター

21

残念ながら、これらの回答のほとんどのリンクは機能していないため、今後の参考のためにgitwikiから少し情報を複製します。

この解決策は私のために働いた:

  • svn-remote url(またはfetchパス)を編集し.git/configて、新しいドメイン/ URL /パスを指すようにします

  • gitを実行しますgit svn fetchこれはsvnから少なくとも1つの新しいリビジョンをフェッチする必要があります!

  • git svn rebase今すぐ試行すると、次のようなエラーメッセージが表示されます。

    Unable to determine upstream SVN information from working tree history
    

    これはgit svn、フェッチ前の最新のコミットが、でgit-svn-id見つかったパスと一致しない古いパスを指しているという事実によって混乱しているためだと思います.git/config

  • 回避策として、元のドメイン/ URL /パスに変更svn-remote url(またはfetchパス)してください

  • ここでgit svn rebase -l再度実行して、最後のフェッチ操作で発生した変更を使用してローカルリベースを実行します。今回は、新しいヘッドのがで見つかったものと一致しないという事実によって混乱しないため、これ機能します。git svngit-svn-id.git/config

  • 最後に、svn-remote url(またはfetchパスを)新しいドメイン/ URL /パスに戻します

  • この時点git svn rebaseで再び機能するはずです!

元の情報はここにあります


3

GitsvnはsvnURLに大きく依存しています。svnからインポートされるすべてのコミットにgit-svn-idは、svnURLを含むがあります。

有効な再配置戦略はgit-svn clone、新しいリポジトリを呼び出し、変更をその新しいクローズにマージすることです。より詳細な手順については、次の記事を参照してください。

http://www.sanityinc.com/articles/relocating-git-svn-repositories


2

git filter-branch

ブログエントリから取られこのスクリプトは、私のために機能しました。の場合と同様に、新旧のリポジトリURLをパラメータとして指定しますsvn switch --relocate

スクリプトは、コミットメッセージ内のgit filter-branchSubversion URLを置き換えるために呼び出しgit-svn-id、を更新し.git/config、をgit-svn使用してメタデータを再作成することによってメタデータを更新しますgit svn rebase。一方でgit svn clone、より堅牢なソリューションかもしれないが、filter-branchアプローチは巨大なリポジトリ(日対時間)のためにはるかに高速に動作します。

#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]
then
  echo "Please invoke this script with two command-line arguments (old and new SVN URLs)."
  exit $E_NO_ARGS
fi

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub("[\\\.]", "\\\\\\\&");print}'`
newUrl=`echo $2 | awk '{gsub("[\\\&]", "\\\\\\\&");print}'`

filter="sed \"s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\""
git filter-branch --msg-filter "$filter" -- --all

sed -i.backup -e "s|$oldUrl|$newUrl|g" .git/config

rm -rf .git/svn
git svn rebase

1

git_fast_filter

それでもgit-filter-branch(つまり、数時間ではなく数分)より高速ですが、精神的には似ていますが、を使用することgit_fast_filterです。ただし、これにはもう少しコーディングが必要であり、きちんとした既製のソリューションは存在しません。とは対照的にgit-filter-branch、これは古いリポジトリから新しいリポジトリを作成します。最後のSVNコミットを指していると想定されます。master

  1. git_fast_filterGitoriousレポからクローンを作成します。
  2. この要点git_fast_filter基づいてクローンを作成したのと同じディレクトリにPythonスクリプトを作成し、を使用して実行可能ビットを設定します。古いリポジトリパスと新しいリポジトリパスを適応させます。(スクリプトの内容も下に貼り付けられています。)chmod +x
  3. を使用して新しいターゲットリポジトリを初期化し、git init作業ディレクトリをこの新しいリポジトリに変更します。
  4. 次のパイプを実行します。

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. .git/config、およびおそらく他の関連ファイルを.git/info古いリポジトリから新しいリポジトリにコピーします。

  6. を削除し.git/svnます。
  7. git-svn新しいリビジョン番号のマッピングに注意してください

    1. 実行する git branch refs/remotes/git-svn master

      • git-svnリモコンは、セクションとは異なる名前で呼ばれるrefs/remotes/git-svn場合が.git/configありsvn-remoteます。
    2. 実行しgit svn infoます。このコマンドがフリーズする場合は、何か問題があります。リビジョン番号のマッピングを再構築する必要があります。

    3. 偽のブランチを削除すると、refs/remotes/git-svnによって再作成されますgit-svn

  8. を呼び出して同期しgit svn rebaseます。

下記の内容ですcommit_filter.pyの値置き換え、IN_REPOそしてOUT_REPO適切には:

#!/usr/bin/python

from git_fast_filter import Commit, FastExportFilter
import re
import sys

IN_REPO = "https://svn.code.sf.net/p/matsim/code"
OUT_REPO = "https://svn.code.sf.net/p/matsim/source"

IN_REPO_RE = re.compile("^git-svn-id: %s" % re.escape(IN_REPO), re.M)
OUT_REPO_RE = "git-svn-id: %s" % OUT_REPO

def my_commit_callback(commit):
  commit.message = IN_REPO_RE.sub(OUT_REPO_RE, commit.message)
  sys.stderr.write(".")

filter = FastExportFilter(commit_callback = my_commit_callback)
filter.run()

0

上記のgit svn rebase -l解決策は私にはうまくいきませんでした。私はそれについて別の方法で取り組むことにしました:

  1. 古いSVNリポジトリをgitリポジトリに複製しold、新しいSVNをgitリポジトリに複製しますnew
  2. フェッチoldnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. 上にリベースnewしますold(の根元newと先端の木oldが同じであるため、成功するはずです)
    • git checkout mastermasterブランチがSVNヘッドを指していると想定します。これは、クリーンクローンの場合です。それ以外の場合は、開始する前にdcommitします。)
    • git rebase --root --onto old
  4. newリベースを説明するためにのgit-svnメタデータを再構築します
    • git update-ref --no-deref refs/remotes/git-svn master(クローンの方法に応じてリモート参照を調整します。たとえば、次のようになりますrefs/remotes/svn/trunk
    • rm -r .git/svn
    • git svn info

1.新しい場所から新しい場所への新しいクローンから始めますか?はいの場合、なぜその時点で完了していないのですか?2.古いものに基づいて新しいものをリベースする場合、古いコミットはすべて、svn-idコミットログエントリに古いURLを記載していますか?3. .git / svnを削除するために保存されているドキュメントはありますか?(3b:どのコマンドがgit-svnメタデータ、git svn infoを再構築していますか?)
Micha Wiedenmann 2016

0

この質問に対する他のいくつかの回答に基づいて、git-svnの再配置を処理するRubyスクリプトを考え出しました。https://gist.github.com/henderea/6e779b66be3580c9a584で見つけることができます

別のコピーをチェックアウトせずに再配置を処理し、1つ以上のブランチにプッシュされていない変更がある場合も処理します(通常のロジックが壊れているため)。git filter-branch回答(メインロジック用)と、リポジトリの1つのインスタンスから別のインスタンスへのブランチのコピー(プッシュされていない変更を含むブランチのコピー用)に関する回答を使用します。

私はこれを使用して、仕事用に持っているgit-svnリポジトリの束を再配置してきましたが、このバージョンのスクリプト(数え切れないほどの反復を経てきました)は私にとってはうまくいくようです。超高速ではありませんが、私が遭遇したすべてのケースを処理し、完全に再配置されたリポジトリをもたらすようです。

スクリプトには、変更を加える前にリポジトリのコピーを作成するオプションが用意されているため、このオプションを使用してバックアップを作成できます。ブランチにプッシュされていない変更がある場合は、コピーを作成する必要があります。

スクリプトは、通常のMRIRubyインストールに含まれていないgemやその他のライブラリを使用しません。MRIに含まれているreadlineおよびfileutilsライブラリを使用します。

うまくいけば、私のスクリプトが他の誰かに役立つことがわかるでしょう。スクリプトに自由に変更を加えてください。

注:このスクリプトは、OS X 10.10Yosemiteでgit2.3.0 /2.3.1とRuby2.2.0でのみテストしましたが(これは私が使用している環境であるため)、他の環境でも機能することを期待しています。ただし、Windowsについての保証はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.