web-dev-qa-db-ja.com

git-svn: `svn switch --relocate`に相当するものは何ですか?

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

バニラsvnではsvn switch --relocate old_url_base new_url_base

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

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

87
kch

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

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

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

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

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

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

61
kch

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

  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>

35
H Krishnan

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

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

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

3
Adam Alexander

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
2
krlmlr

git_fast_filter

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

  1. Gitoriousリポジトリからgit_fast_filterをクローンします。
  2. this Gist に基づいて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/configsvn-remoteセクションを参照してください
    2. git svn infoを実行します。このコマンドがフリーズする場合は、何か問題があります。リビジョン番号マッピングを再構築する必要があります。

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

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

以下はcommit_filter.pyの内容です。IN_REPOOUT_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()
1
krlmlr

この質問への他のいくつかの回答に基づいて、私は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については保証されていません。

0
Eric Henderson

上記 git svn rebase -l解決策がうまくいきませんでした。私はそれを別の方法で行うことにしました:

  1. 古いSVNリポジトリをgit repo oldにクローンし、新しいSVNをgit repo 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
0
Ben Challenor