90

我通过 git-svn 镜像的 svn 存储库已更改 URL。

在香草 svn 中,您只需要做svn switch --relocate old_url_base new_url_base.

如何使用 git-svn 做到这一点?

简单地更改配置文件中的 svn url 会失败。

4

8 回答 8

63

这很好地处理了我的情况:

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

我使用协议克隆file://,并想切换到http://协议。

编辑部分中的url设置很诱人,但它本身不起作用。一般来说,您需要遵循以下程序:[svn-remote "svn"].git/config

  1. 将 svn-remoteurl设置切换为新名称。
  2. 运行git svn fetch。这需要从 svn 中获取至少一个新版本!
  3. 将 svn-remoteurl设置改回原来的 URL。
  4. 运行git svn rebase -l以执行本地 rebase(使用最后一次 fetch 操作中的更改)。
  5. 将 svn-remoteurl设置改回新的 URL。
  6. 现在,git svn rebase应该再次工作。

喜欢冒险的人不妨一试--rewrite-root

于 2008-11-06T13:55:09.443 回答
39

您可以查看以下是否正常:

  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>

于 2010-10-31T01:45:16.273 回答
21

不幸的是,这些答案中的大多数链接都不起作用,所以我将从git wiki复制一些信息以供将来参考。

这个解决方案对我有用:

  • 编辑svn-remote url(或fetch路径).git/config以指向新的域/url/路径

  • 运行 git git svn fetch这需要从 svn 中获取至少一个新版本!

  • 如果您git svn rebase现在尝试,您将收到如下错误消息:

    Unable to determine upstream SVN information from working tree history
    

    我认为这是因为您在获取之前的最新提交将指向旧路径git svn这一事实感到困惑,该路径与.git-svn-id.git/config

  • 作为一种解决方法,将svn-remote url(或fetch路径)更改回原始域/url/路径

  • 现在git svn rebase -l再次运行以使用最后一次 fetch 操作中的更改进行本地 rebase。这一次它起作用,显然是因为git svn不会被git-svn-id新头的 与 中找到的不匹配的事实混淆.git/config

  • 最后,将svn-remote url(或fetch路径)更改回新的域/url/路径

  • 此时git svn rebase应该再次工作!

原始信息可在此处找到。

于 2011-11-15T12:28:26.493 回答
3

Git svn 严重依赖 svn URL。从 svn 导入的每个提交都有一个git-svn-id包含 svn URL。

一个有效的重定位策略是调用git-svn clone新的存储库并将更改合并到新的关闭上。有关更详细的过程,请参阅这篇文章:

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

于 2008-11-06T13:46:03.377 回答
2

git filter-branch

该脚本取自博客条目,对我有用。提供新旧 repo URL 作为参数,就像 for 一样svn switch --relocate

该脚本调用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
于 2013-08-22T13:22:51.553 回答
1

git_fast_filter

然而比git-filter-branch(即,分钟而不是小时)更快,但在精神上相似,是使用git_fast_filter. 但是,这需要更多的编码,并且不存在整洁的现成解决方案。相比之下,这将从git-filter-branch的 repo创建一个的repo 。假设指向最后的 SVN 提交。master

  1. git_fast_filter从 Gitorious 仓库克隆。
  2. git_fast_filter根据此 Gist在克隆的同一目录中创建一个 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()
于 2013-08-22T16:00:22.937 回答
0

上述git svn rebase -l解决方案对我不起作用。我决定换一种方式:

  1. 将旧的 SVN 存储库克隆到 git 存储库中old,将新的 SVN 克隆到 git 存储库中new
  2. 进入old_new
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebasenew在顶部old(应该成功,因为根部new和尖端的树old是相同的)
    • git checkout master(假设master分支指向 SVN 头部。干净的克隆就是这种情况;否则在开始之前 dcommit。)
    • git rebase --root --onto old
  4. 重建 git-svn 元数据new以考虑变基
    • git update-ref --no-deref refs/remotes/git-svn master(根据您的克隆方式调整远程参考,例如可以refs/remotes/svn/trunk
    • rm -r .git/svn
    • git svn info
于 2014-01-02T09:42:16.627 回答
0

基于对这个问题的其他一些回答,我想出了一个处理 git-svn 重定位的 Ruby 脚本。你可以在https://gist.github.com/henderea/6e779b66be3580c9a584找到它。

它在不检查另一个副本的情况下处理重定位,甚至可以处理一个或多个分支中存在未推送更改的情况(因为这破坏了常规逻辑)。它使用来自 git filter-branch 答案(用于主要逻辑)和关于将分支从一个 repo 实例复制到另一个实例的答案(用于复制具有未推送更改的分支)中的内容。

我一直在使用它来重新定位我工作的一堆 git-svn 存储库,而这个版本的脚本(我已经经历了无数次迭代)似乎对我有用。它不是超快的,但它似乎可以处理我遇到的所有情况并导致完全重新定位的存储库。

该脚本为您提供了在进行任何更改之前创建存储库副本的选项,因此您可以使用此选项创建备份。如果您在任何分支中有未推送的更改,则需要创建副本。

该脚本不使用正常 MRI Ruby 安装中未包含的任何 gem 或其他库。它确实使用了 MRI 中包含的 readline 和 fileutils 库。

希望我的脚本对其他人有用。随意更改脚本。

注意:我只在 OS X 10.10 Yosemite 上使用 git 2.3.0/2.3.1 和 Ruby 2.2.0 测试了这个脚本(因为这是我使用的环境),但我希望它也能在其他环境中工作。但是,不能保证关于 Windows。

于 2015-02-26T17:03:51.637 回答