git-svn:什么是等价于`svn switch --relocate`?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/268736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 16:06:04  来源:igfitidea点击:

git-svn: what's the equivalent to `svn switch --relocate`?

gitversion-controlgit-svn

提问by kch

An svn repository I'm mirroring through git-svn has changed URL.

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

In vanilla svn you'd just do svn switch --relocate old_url_base new_url_base.

在香草 svn 中,您只需执行svn switch --relocate old_url_base new_url_base.

How can I do this using git-svn?

我怎样才能使用 git-svn 做到这一点?

Simply changing the svn url in the config file fails.

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

采纳答案by kch

This handles my situation pretty well:

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

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

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

I cloned using the file://protocol, and wanted to switch to the http://protocol.

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

It is tempting to edit the urlsetting in the [svn-remote "svn"]section of .git/config, but on its own this does not work. In general you need to follow the following procedure:

编辑部分中的url设置很诱人,但就其本身而言,这是行不通的。一般来说,您需要遵循以下程序:[svn-remote "svn"].git/config

  1. Switch the svn-remote urlsetting to the new name.
  2. Run git svn fetch. This needs to fetch at least one new revision from svn!
  3. Change the svn-remote urlsetting back to the original URL.
  4. Run git svn rebase -lto do a local rebase (with the changes that came in with the last fetch operation).
  5. Change the svn-remote urlsetting back to the new URL.
  6. Now, git svn rebaseshould work again.
  1. 将 svn-remoteurl设置切换为新名称。
  2. 运行git svn fetch。这需要从 svn 获取至少一个新版本!
  3. 将 svn-remoteurl设置改回原始 URL。
  4. 运行git svn rebase -l以执行本地变基(使用上次获取操作带来的更改)。
  5. 将 svn-remoteurl设置改回新的 URL。
  6. 现在,git svn rebase应该再次工作。

Adventurous souls may want to try --rewrite-root.

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

回答by H Krishnan

You can see if the following works OK:

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

  1. If svn-remote.svn.rewriteRootdoes not exist in config file (.git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. If svn-remote.svn.rewriteUUIDdoes not exist in config file:

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

    The currentRepositoryUUIDcan be obtained from .git/svn/.metadata.

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

  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>

回答by UncleZeiv

Unfortunately most of the links in these answers aren't working, so I'm going to duplicate a bit of information from the git wikifor future reference.

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

This solution worked for me:

这个解决方案对我有用:

  • Edit the svn-remoteurl(or fetchpath) in .git/configto point to the new domain/url/path

  • Run git git svn fetch. This needs to fetch at least one new revision from svn!

  • If you attempt git svn rebasenow, you'll get an error message like this:

    Unable to determine upstream SVN information from working tree history
    

    I think this is because git svnis confused by the fact that your latest commit prior to the fetch will have a git-svn-idpointing to the old path, which doesn't match the one found in .git/config.

  • As a workaround, change svn-remoteurl(or fetchpath) back to the original domain/url/path

  • Now run git svn rebase -lagain to do a local rebase with the changes that came in with the last fetch operation. This time it willwork, apparently because git svnwon't be confused by the fact that the git-svn-idof the new head doesn't match with that found in .git/config.

  • Finally, change svn-remoteurl(or fetchpath) back to the new domain/url/path

  • At this point git svn rebaseshould work again!

  • 编辑svn-remoteurl(或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-remoteurl(或fetch路径)更改回原始域/url/路径

  • 现在git svn rebase -l再次运行以使用上次获取操作带来的更改进行本地变基。这次它起作用,显然是因为git svn不会被git-svn-id新头的 与.git/config.

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

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

The original information was found here.

原始信息是在这里找到的。

回答by Adam Alexander

Git svn relies heavily on the svn URL. Every commit that is imported from svn has a git-svn-idthat includes the svn URL.

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

A valid relocations strategy is to call git-svn cloneon the new repository and merge the changes onto that new close. For a more detailed procedure, see this article:

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

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

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

回答by krlmlr

git filter-branch

git filter-branch

This script, taken from a blog entry, has worked for me. Supply old and new repo URL as parameter, just like for svn switch --relocate.

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

The script calls git filter-branchto replace Subversion URLs in the git-svn-idin the commit messages, updates .git/config, and also updates git-svnmetadata by recreating it using git svn rebase. While git svn clonemight be the more robust solution, the filter-branchapproach works much faster for huge repositories (hours vs. days).

该脚本调用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  | awk '{gsub("[\\.]", "\\\\&");print}'`
newUrl=`echo  | 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

回答by krlmlr

git_fast_filter

git_fast_filter

Yet faster than git-filter-branch(i.e., minutes instead of hours), but similar in spirit, is to use git_fast_filter. However, this requires a bit more coding, and no neat ready-packed solution exists. In contrast to git-filter-branch, this will create a newrepo from an oldone. It is assumed that masterpoints to the last SVN commit.

然而git-filter-branch,使用git_fast_filter. 但是,这需要更多的编码,并且不存在整洁的现成解决方案。与 相比git-filter-branch,这将从旧的repo创建一个新的repo 。假设指向最后的 SVN 提交。master

  1. Clone git_fast_filterfrom the Gitorious repo.
  2. Create a Python script in the same directory where you cloned git_fast_filterbased on this Gist, set the executable bit using chmod +x. Adapt old and new repository paths. (Contents of the script are pasted below, too.)
  3. Initialize a new target repository using git init, change working directory to this new repo.
  4. Execute the following pipe:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Copy .git/config, and perhaps other relevant files in .git/infofrom the old repo to the new repo.

  6. Remove .git/svn.
  7. Make git-svnaware of the new revision number mapping

    1. Execute git branch refs/remotes/git-svn master

      • Your git-svn remotes might be called different than refs/remotes/git-svn, consult .git/config, svn-remotesections
    2. Execute git svn info. If this command freezes, something's wrong. It should rebuild the revision number mapping.

    3. Remove the fake branch refs/remotes/git-svn, it will be recreated by git-svn

  8. Synchronize by calling git svn rebase.
  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

Below are the contents of commit_filter.py, replace the values of IN_REPOand OUT_REPOas appropriate:

以下是内容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()

回答by Ben Challenor

The above git svn rebase -lsolution didn't work for me. I decided to go about it a different way:

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

  1. Clone old SVN repo into git repo oldand new SVN into git repo new
  2. Fetch oldinto new
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newon top of old(should succeed because the trees in the root of newand the tip of oldare identical)
    • git checkout master(Assumes that the masterbranch is pointing at the SVN head. This will be the case with a clean clone; otherwise dcommit before you start.)
    • git rebase --root --onto old
  4. Rebuild the git-svn metadata of newto account for the rebase
    • git update-ref --no-deref refs/remotes/git-svn master(adjust the remote ref depending on how you cloned, e.g. it could be refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info
  1. 将旧的 SVN repo 克隆到 git repo old,将新的 SVN克隆到 git reponew
  2. oldnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newon top old(应该成功,因为根部new和尖端的树old是相同的)
    • git checkout master(假设master分支指向 SVN 头。干净的克隆就是这种情况;否则在开始之前 dcommit。)
    • git rebase --root --onto old
  4. 重建 git-svn 元数据new以说明 rebase
    • git update-ref --no-deref refs/remotes/git-svn master(根据您的克隆方式调整远程参考,例如它可能是refs/remotes/svn/trunk
    • rm -r .git/svn
    • git svn info

回答by Eric Henderson

Based off of some of the other responses to this question, I have come up with a Ruby script that handles the git-svn relocating. You can find it at https://gist.github.com/henderea/6e779b66be3580c9a584.

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

It handles the relocate without checking out another copy, and it even handles the case where there are un-pushed changes in one or more branches (since that breaks the regular logic). It uses stuff from the git filter-branch answer (for the main logic) and the answer about copying branches from one instance of the repo to another (for copying branches with un-pushed changes).

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

I've been using this to relocate a bunch of git-svn repos that I have for work, and this version of the script (I've been through countless iterations) seems to work for me. It isn't super-fast, but it does seem to handle all of the cases I've encountered and result in a fully-relocated repo.

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

The script gives you the option to create a copy of the repo before making any changes, so you can use this option to create a backup. Creating a copy is required if you have un-pushed changes in any branches.

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

The script does not use any gems or other libraries not included in the normal MRI Ruby installation. It does use the readline and fileutils libraries included in MRI.

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

Hopefully my script will prove useful to someone else. Feel free to make changes to the script.

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

NOTE:I've only tested this script with git 2.3.0/2.3.1 and Ruby 2.2.0 on OS X 10.10 Yosemite (since that's the environment I use), but I would expect it to work on other environments as well. No guarantees about Windows, though.

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