Git-svnでミラーリングしているsvnリポジトリのURLが変更されました。
バニラsvnではsvn switch --relocate old_url_base new_url_base
。
Git-svnを使用してこれを行うにはどうすればよいですか?
設定ファイルのsvn urlを変更するだけでは失敗します。
これは私の状況をかなりうまく処理します:
https://git.wiki.kernel.org/index.php/GitSvnSwitch
file://
プロトコルを使用してクローンを作成し、http://
プロトコルに切り替えたいと考えました。
[svn-remote "svn"]
の.git/config
セクションのurl
設定を編集するのは魅力的ですが、それだけでは機能しません。一般に、次の手順に従う必要があります。
url
設定を新しい名前に切り替えます。git svn fetch
を実行します。これは、svnから少なくとも1つの新しいリビジョンをフェッチする必要があります!url
設定を元のURLに戻します。git svn rebase -l
を実行して、ローカルリベースを実行します(最後のフェッチ操作で行われた変更を使用)。url
設定を新しいURLに戻します。git svn rebase
が再び機能するようになります。冒険心のある人は試してみたいかもしれません --rewrite-root
。
以下が正常に機能するかどうかを確認できます。
svn-remote.svn.rewriteRoot
が構成ファイルに存在しない場合(.git/config
):
git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
svn-remote.svn.rewriteUUID
が構成ファイルに存在しない場合:
git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
currentRepositoryUUID
は.git/svn/.metadata
から取得できます。
git config svn-remote.svn.url <newRepositoryURL>
Git svnは、svn URLに大きく依存しています。 svnからインポートされるすべてのコミットには、svn URLを含むgit-svn-id
があります。
有効な再配置戦略は、新しいリポジトリでgit-svn clone
を呼び出し、変更を新しいクローズにマージすることです。詳細な手順については、次の記事を参照してください。
http://www.sanityinc.com/articles/relocating-git-svn-repositories
git filter-branch
このスクリプト は ブログエントリ から引用したもので、私にとってはうまくいきました。 svn switch --relocate
の場合と同様に、新旧のリポジトリURLをパラメータとして指定します。
スクリプトはgit filter-branch
を呼び出して、コミットメッセージのgit-svn-id
内のSubversion URLを置き換え、.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
git_fast_filter
git-filter-branch
(つまり、時間ではなく分)より高速ですが、精神的には似ていますが、 git_fast_filter
を使用します。ただし、これにはもう少しコーディングが必要で、きちんと準備されたソリューションはありません。 git-filter-branch
とは対照的に、これはoldリポジトリからnewリポジトリを作成します。 master
は最後のSVNコミットを指すと想定されています。
git_fast_filter
をクローンします。git_fast_filter
のクローンを作成した同じディレクトリにPythonスクリプトを作成し、chmod +x
を使用して実行可能ビットを設定します。および新しいリポジトリパス(スクリプトの内容も以下に貼り付けられます)。git init
を使用して新しいターゲットリポジトリを初期化し、作業ディレクトリをこの新しいリポジトリに変更します。次のパイプを実行します。
(cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
path/to/git_fast_filter/commit_filter.py | git-fast-import
.git/config
と、おそらく.git/info
内の他の関連ファイルを古いリポジトリから新しいリポジトリにコピーします。
.git/svn
を削除します。git-svn
に新しいリビジョン番号のマッピングを認識させる
実行git branch refs/remotes/git-svn master
refs/remotes/git-svn
とは異なる方法で呼び出されている可能性があります。.git/config
、svn-remote
セクションを参照してくださいgit svn info
を実行します。このコマンドがフリーズする場合は、何か問題があります。リビジョン番号マッピングを再構築する必要があります。
偽のブランチrefs/remotes/git-svn
を削除すると、git-svn
によって再作成されます
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()
この質問への他のいくつかの回答に基づいて、私はgit-svnの再配置を処理するRubyスクリプトを考え出しました。あなたはそれを https:// Gist.github.com/henderea/6e779b66be3580c9a584 。
別のコピーをチェックアウトせずに再配置を処理し、1つ以上のブランチにプッシュされていない変更がある場合も処理します(これにより、通常のロジックが壊れます)。これはgitフィルターブランチの回答(メインロジック用)と、リポジトリの1つのインスタンスから別のインスタンスへのブランチのコピーに関する回答(プッシュされていない変更を含むブランチのコピー用)を使用します。
私はこれを使用して、仕事のために持っているgit-svn reposの束を再配置しました。このバージョンのスクリプト(私は何度も繰り返してきました)は私にとってはうまくいくようです。それは超高速ではありませんが、私が遭遇したすべてのケースを処理し、完全に再配置されたリポジトリをもたらすようです。
スクリプトには、変更を行う前にリポジトリのコピーを作成するオプションが用意されているため、このオプションを使用してバックアップを作成できます。ブランチにプッシュされていない変更がある場合は、コピーを作成する必要があります。
このスクリプトは、通常のMRIに含まれていないgemまたはその他のライブラリを使用しませんRubyインストール。MRIに含まれているreadlineおよびfileutilsライブラリを使用します。
うまくいけば、私のスクリプトが他の誰かに役立つことがわかるでしょう。スクリプトを自由に変更してください。
注:私はgit 2.3.0/2.3.1とRuby 2.2.0でのみこのスクリプトをテストしましたOS X 10.10 Yosemite(それが私が使用する環境なので)でも、他の環境でも動作することを期待していますが、Windowsについては保証されていません。
上記 git svn rebase -l
解決策がうまくいきませんでした。私はそれを別の方法で行うことにしました:
old
にクローンし、新しいSVNをgit repo new
にクローンしますold
をnew
にフェッチします。cd new
git fetch ../old
git tag old FETCH_HEAD
new
の上にold
をリベースします(new
のルートとold
の先端にあるツリーは同一であるため、成功するはずです)git checkout master
(master
ブランチがSVNヘッドを指していると想定します。これはクリーンクローンの場合です。それ以外の場合は、開始する前にdcommitします。)git rebase --root --onto old
new
のgit-svnメタデータを再構築して、リベースを考慮しますgit update-ref --no-deref refs/remotes/git-svn master
(クローンの作成方法に応じてリモート参照を調整します。たとえば、refs/remotes/svn/trunk
)rm -r .git/svn
git svn info