中文 ▾ 主题 ▾ 最新版本 ▾ git-svn 上次更新于 2.47.0

名称

git-svn - Subversion 存储库和 Git 之间的双向操作

概要

git svn <command> [<options>] [<arguments>]

描述

git svn 是 Subversion 和 Git 之间变更集的简单通道。 它提供 Subversion 存储库和 Git 存储库之间的双向变更流。

git svn 可以跟踪标准的 Subversion 存储库,遵循常见的“trunk/branches/tags”布局,使用 --stdlayout 选项。 它还可以使用 -T/-t/-b 选项跟踪任何布局中的分支和标签(请参阅下面 init 的选项,以及 clone 命令)。

一旦跟踪 Subversion 存储库(使用上述任何方法),Git 存储库可以通过 fetch 命令从 Subversion 更新,Subversion 可以通过 dcommit 命令从 Git 更新。

命令

init

初始化一个空的 Git 存储库,其中包含用于 git svn 的附加元数据目录。 Subversion URL 可以指定为命令行参数,也可以指定为 -T/-t/-b 的完整 URL 参数。 或者,可以将要操作的目标目录指定为第二个参数。 通常,此命令初始化当前目录。

-T<trunk-subdir>
--trunk=<trunk-subdir>
-t<tags-subdir>
--tags=<tags-subdir>
-b<branches-subdir>
--branches=<branches-subdir>
-s
--stdlayout

这些是 init 的可选命令行选项。 这些标志中的每一个都可以指向一个相对存储库路径 (--tags=project/tags) 或一个完整的 url (--tags=https://foo.org/project/tags)。 您可以指定多个 --tags 和/或 --branches 选项,以防您的 Subversion 存储库将标签或分支放置在多个路径下。 选项 --stdlayout 是将 trunk、tags、branches 设置为相对路径的简写方式,这是 Subversion 默认值。 如果也给出了任何其他选项,则它们优先。

--no-metadata

在 [svn-remote] 配置中设置 noMetadata 选项。 不建议使用此选项,请在使用此选项之前阅读此手册页的 svn.noMetadata 部分。

--use-svm-props

在 [svn-remote] 配置中设置 useSvmProps 选项。

--use-svnsync-props

在 [svn-remote] 配置中设置 useSvnsyncProps 选项。

--rewrite-root=<URL>

在 [svn-remote] 配置中设置 rewriteRoot 选项。

--rewrite-uuid=<UUID>

在 [svn-remote] 配置中设置 rewriteUUID 选项。

--username=<user>

对于 SVN 处理身份验证的传输(http、https 和普通 svn),指定用户名。 对于其他传输(例如 svn+ssh://),您必须在 URL 中包含用户名,例如 svn+ssh://foo@svn.bar.com/project

--prefix=<prefix>

这允许人们指定一个前缀,如果指定了 trunk/branches/tags,则该前缀会添加到远程名称的前面。 前缀不会自动包含尾部斜杠,因此请确保在参数中包含您想要的内容。 如果指定了 --branches/-b,则前缀必须包含尾部斜杠。 在任何情况下都强烈建议设置前缀(带有尾部斜杠),因为您的 SVN 跟踪引用将位于 "refs/remotes/$prefix/**",这与 Git 自己的远程跟踪引用布局 (refs/remotes/$remote/**) 兼容。 如果您希望跟踪共享一个公共存储库的多个项目,设置前缀也很有用。 默认情况下,前缀设置为 origin/

注意
在 Git v2.0 之前,默认前缀为 ""(无前缀)。 这意味着 SVN 跟踪引用被放置在 "refs/remotes/*",这与 Git 自己的远程跟踪引用的组织方式不兼容。 如果您仍然想要旧的默认值,您可以通过在命令行上传递 --prefix "" 来获得它(如果您的 Perl 的 Getopt::Long 版本 < v2.37,--prefix="" 可能不起作用)。
--ignore-refs=<regex>

传递给 initclone 时,此正则表达式将保留为配置键。 有关 --ignore-refs 的说明,请参阅 fetch

--ignore-paths=<regex>

传递给 initclone 时,此正则表达式将保留为配置键。 有关 --ignore-paths 的说明,请参阅 fetch

--include-paths=<regex>

传递给 initclone 时,此正则表达式将保留为配置键。 有关 --include-paths 的说明,请参阅 fetch

--no-minimize-url

当跟踪多个目录(使用 --stdlayout、--branches 或 --tags 选项)时,git svn 将尝试连接到 Subversion 存储库的根目录(或允许的最高级别)。 如果整个项目在存储库中移动,此默认值允许更好地跟踪历史记录,但可能会导致对具有读取访问限制的存储库出现问题。 传递 --no-minimize-url 将允许 git svn 接受 URL 按原样,而无需尝试连接到更高级别的目录。 默认情况下,此选项在仅跟踪一个 URL/分支时处于关闭状态(它不会有太大作用)。

fetch

从我们正在跟踪的 Subversion 远程获取未获取的修订。 可以将 $GIT_DIR/config 文件中 [svn-remote "…​"] 部分的名称指定为可选的命令行参数。

如果需要,这会自动更新 rev_map(有关详细信息,请参阅下面的 FILES 部分中的 $GIT_DIR/svn/**/.rev_map.*)。

--localtime

将 Git 提交时间存储在本地时区而不是 UTC。 这使得 git log(即使没有 --date=local)显示与本地时区中 svn log 相同的时间。

这不会干扰与您从中克隆的 Subversion 存储库的互操作,但如果您希望您的本地 Git 存储库能够与他人的本地 Git 存储库互操作,请不要使用此选项,或者您都应该在相同的本地时区中使用它。

--parent

仅从当前 HEAD 的 SVN 父级获取。

--ignore-refs=<regex>

忽略与 Perl 正则表达式匹配的分支或标记的引用。 可以使用像 ^refs/remotes/origin/(?!tags/wanted-tag|wanted-branch).*$ 这样的“负向前断言”来仅允许某些引用。

config key: svn-remote.<name>.ignore-refs

如果设置了 ignore-refs 配置键,并且还给出了命令行选项,则将使用这两个正则表达式。

--ignore-paths=<regex>

这允许人们指定一个 Perl 正则表达式,该正则表达式会导致跳过 SVN 中检出的所有匹配路径。 --ignore-paths 选项应匹配给定存储库上的每个 fetch(包括由于 clonedcommitrebase 等引起的自动获取)。

config key: svn-remote.<name>.ignore-paths

如果设置了 ignore-paths 配置键,并且还给出了命令行选项,则将使用这两个正则表达式。

示例

为每个获取跳过“doc*”目录
--ignore-paths="^doc"
跳过第一级目录的“branches”和“tags”
--ignore-paths="^[^/]+/(?:branches|tags)"
--include-paths=<regex>

这允许人们指定一个 Perl 正则表达式,该正则表达式将导致仅包含 SVN 中检出的匹配路径。 --include-paths 选项应匹配给定存储库上的每个 fetch(包括由于 clonedcommitrebase 等引起的自动获取)。 --ignore-paths 优先于 --include-paths

config key: svn-remote.<name>.include-paths
--log-window-size=<n>

在扫描 Subversion 历史记录时,每次请求获取 <n> 个日志条目。 默认为 100。对于非常大的 Subversion 存储库,可能需要更大的值才能在合理的时间内完成 clone/fetch。 但是过大的值可能会导致更高的内存使用率和请求超时。

clone

运行 initfetch。它会自动基于传递给它的 URL 的 basename 创建一个目录;或者如果传递了第二个参数,它将创建一个目录并在其中工作。它接受 initfetch 命令接受的所有参数;但 --fetch-all--parent 除外。克隆仓库后,fetch 命令将能够更新修订版本而不影响工作树;并且 rebase 命令将能够使用最新的更改更新工作树。

--preserve-empty-dirs

为从 Subversion 获取的每个空目录在本地 Git 仓库中创建一个占位符文件。这包括通过删除 Subversion 仓库中的所有条目(但不包括目录本身)而变为空的目录。占位符文件也会被跟踪并在不再需要时被删除。

--placeholder-filename=<filename>

设置由 --preserve-empty-dirs 创建的占位符文件的名称。默认值:".gitignore"

rebase

此命令从当前 HEAD 的 SVN 父项获取修订版本,并将当前(未提交到 SVN)的工作基于它进行 rebase。

这类似于 svn updategit pull,但它使用 git rebase 而不是 git merge 来保留线性历史,以便于使用 git svn 进行 dcommit。

此命令接受 git svn fetchgit rebase 接受的所有选项。但是,--fetch-all 仅从当前 [svn-remote] 获取,而不是所有 [svn-remote] 定义。

git rebase 类似;这要求工作树是干净的,并且没有未提交的更改。

如果需要,这会自动更新 rev_map(有关详细信息,请参阅下面的 FILES 部分中的 $GIT_DIR/svn/**/.rev_map.*)。

-l
--local

不要从远程获取;只针对上次从上游 SVN 获取的提交运行 git rebase

dcommit

将当前分支的每个 diff 直接提交到 SVN 仓库,然后进行 rebase 或 reset(取决于 SVN 和 head 之间是否存在 diff)。这将为 Git 中的每个提交在 SVN 中创建一个修订版本。

当指定一个可选的 Git 分支名称(或 Git 提交对象名称)作为参数时,该子命令在指定的分支上工作,而不是在当前分支上工作。

建议使用 dcommit 而不是 set-tree (如下所示)。

--no-rebase

提交后,不要 rebase 或 reset。

--commit-url <URL>

提交到此 SVN URL(完整路径)。这旨在允许使用一种传输方法(例如,svn://http:// 用于匿名读取)创建的现有 git svn 仓库在用户稍后被授予访问备用传输方法(例如,svn+ssh://https://)以进行提交时可以重用。

config key: svn-remote.<name>.commiturl
config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)

请注意,commiturl 配置键的 SVN URL 包含 SVN 分支。如果您想为整个 SVN 仓库设置提交 URL,请改用 svn-remote.<name>.pushurl。

强烈建议不要将此选项用于任何其他目的(别问)。

--mergeinfo=<mergeinfo>

在 dcommit 期间添加给定的合并信息(例如,--mergeinfo="/branches/foo:1-10")。所有 svn 服务器版本都可以存储此信息(作为属性),并且从 1.5 版本开始的 svn 客户端可以使用它。要指定来自多个分支的合并信息,请在分支之间使用单个空格字符(--mergeinfo="/branches/foo:1-10 /branches/bar:3,5-6,8"

config key: svn.pushmergeinfo

此选项将导致 git-svn 尝试在可能的情况下自动填充 SVN 仓库中的 svn:mergeinfo 属性。目前,只有在 dcommit 非快进合并时才能这样做,其中除第一个父项之外的所有父项都已推送到 SVN 中。

--interactive

要求用户确认是否应将补丁集实际发送到 SVN。对于每个补丁,可以回答“yes”(接受此补丁)、“no”(放弃此补丁)、“all”(接受所有补丁)或“quit”。

如果答案是“no”或“quit”,git svn dcommit 会立即返回,而不会向 SVN 提交任何内容。

branch

在 SVN 仓库中创建一个分支。

-m
--message

允许指定提交消息。

-t
--tag

通过使用 tags_subdir 而不是在 git svn init 期间指定的 branches_subdir 来创建标签。

-d<path>
--destination=<path>

如果为 initclone 命令提供了多个 --branches(或 --tags)选项,则必须提供要在 SVN 仓库中创建的分支(或标签)的位置。 <path> 指定要用于创建分支或标签的路径,并且应与配置的分支或标签 refspec 之一的左侧模式匹配。您可以使用以下命令查看这些 refspec:

git config --get-all svn-remote.<name>.branches
git config --get-all svn-remote.<name>.tags

其中 <name> 是由 init 的 -R 选项指定的 SVN 仓库的名称(或默认情况下的“svn”)。

--username

指定要执行提交的 SVN 用户名。此选项会覆盖 username 配置属性。

--commit-url

使用指定的 URL 连接到目标 Subversion 仓库。这在源 SVN 仓库是只读的情况下非常有用。此选项会覆盖配置属性 commiturl

git config --get-all svn-remote.<name>.commiturl
--parents

创建父文件夹。此参数等效于 svn cp 命令上的参数 --parents,并且对于非标准仓库布局非常有用。

tag

在 SVN 仓库中创建一个标签。这是 branch -t 的简写形式。

log

当 svn 用户引用 -r/--revision 编号时,这应该可以轻松查找 svn 日志消息。

支持来自 'svn log' 的以下功能

-r <n>[:<n>]
--revision=<n>[:<n>]

受支持,非数字参数不受支持:HEAD、NEXT、BASE、PREV 等 …​

-v
--verbose

它与 svn log 中的 --verbose 输出不完全兼容,但相当接近。

--limit=<n>

与 --max-count 不同,不计算合并/排除的提交

--incremental

受支持

新功能

--show-commit

也显示 Git 提交 sha1

--oneline

我们的 --pretty=oneline 版本

注意
SVN 本身只存储 UTC 时间,没有其他。常规 svn 客户端将 UTC 时间转换为本地时间(或基于 TZ= 环境)。此命令具有相同的行为。

任何其他参数都直接传递给 git log

blame

显示什么修订版本和作者上次修改了文件的每一行。默认情况下,此模式的输出与“svn blame”的输出格式兼容。与 SVN blame 命令一样,会忽略工作树中的本地未提交更改;会注释 HEAD 修订版本中的文件版本。未知参数直接传递给 git blame

--git-format

生成与 git blame 格式相同的输出,但使用 SVN 修订版本号而不是 Git 提交哈希值。在此模式下,尚未提交到 SVN 的更改(包括本地工作副本编辑)显示为修订版本 0。

find-rev

当给定一个 rN 形式的 SVN 修订版本号时,返回相应的 Git 提交哈希值(可以选择后跟一个 tree-ish 来指定应该搜索哪个分支)。当给定一个 tree-ish 时,返回相应的 SVN 修订版本号。

-B
--before

如果给定 SVN 修订版本,则不需要完全匹配,而是查找与指定修订版本时 SVN 仓库状态(在当前分支上)对应的提交。

-A
--after

如果给定 SVN 修订版本,则不需要完全匹配;如果没有完全匹配,则返回在历史记录中向前搜索的最接近匹配项。

set-tree

您应该考虑使用 dcommit 而不是此命令。将指定的提交或树对象提交到 SVN。这依赖于您导入的 fetch 数据是最新的。这在提交到 SVN 时绝对不会尝试进行修补,它只是使用树或提交中指定的文件覆盖文件。所有合并都假定独立于 git svn 函数发生。

create-ignore

递归查找目录上的 svn:ignore 和 svn:global-ignores 属性,并创建匹配的 .gitignore 文件。生成的文件会被暂存以进行提交,但不会被提交。使用 -r/--revision 来引用特定的修订版本。

show-ignore

递归查找并列出目录上的 svn:ignore 和 svn:global-ignores 属性。输出适合附加到 $GIT_DIR/info/exclude 文件。

mkdirs

尝试根据 $GIT_DIR/svn/<refname>/unhandled.log 文件中的信息重新创建核心 Git 无法跟踪的空目录。使用 "git svn clone" 和 "git svn rebase" 时,会自动重新创建空目录,因此 "mkdirs" 旨在用于 "git checkout" 或 "git reset" 等命令之后。(有关更多信息,请参见 svn-remote.<name>.automkdirs 配置文件选项。)

commit-diff

提交来自命令行的两个 tree-ish 参数的差异。此命令不依赖于位于 git svn init 初始化后的仓库中。此命令接受三个参数,(a) 要进行差异比较的原始树,(b) 新的树结果,(c) 目标 Subversion 仓库的 URL。如果您从 git svn 感知仓库(已使用 git svn init 初始化)中工作,则可以省略最后一个参数(URL)。此命令需要 -r<revision> 选项。

提交消息可以直接通过 -m-F 选项提供,也可以从标签或提交间接提供(当第二个 tree-ish 表示这样的对象时),或者通过调用编辑器来请求(请参见下面的 --edit 选项)。

-m <msg>
--message=<msg>

使用给定的 msg 作为提交消息。此选项禁用 --edit 选项。

-F <filename>
--file=<filename>

从给定文件中获取提交消息。此选项禁用 --edit 选项。

info

显示关于文件或目录的信息,类似于 ‘svn info’ 提供的。当前不支持 -r/--revision 参数。使用 --url 选项仅输出 URL: 字段的值。

proplist

列出存储在 Subversion 仓库中,关于给定文件或目录的属性。使用 -r/--revision 来引用特定的 Subversion 版本。

propget

获取作为第一个参数给定的 Subversion 属性,用于文件。可以使用 -r/--revision 指定特定版本。

propset

将作为第一个参数给定的 Subversion 属性,设置为作为第二个参数给定的值,用于作为第三个参数给定的文件。

示例

git svn propset svn:keywords "FreeBSD=%H" devel/py-tipper/Makefile

这将把属性 svn:keywords 设置为 FreeBSD=%H,用于文件 devel/py-tipper/Makefile

show-externals

显示 Subversion 外部引用。使用 -r/--revision 指定特定版本。

gc

压缩 $GIT_DIR/svn/<refname>/unhandled.log 文件,并删除 $GIT_DIR/svn/<refname>/index 文件。

reset

撤销 fetch 操作的影响,回到指定的版本。这允许你重新 fetch 一个 SVN 版本。通常,SVN 版本的内容不应该改变,并且 reset 应该是不必要的。但是,如果 SVN 权限发生变化,或者你更改了 --ignore-paths 选项,fetch 可能会失败,并显示 "not found in commit"(文件之前不可见)或 "checksum mismatch"(遗漏了修改)。如果问题文件无法被永久忽略(使用 --ignore-paths),修复仓库的唯一方法是使用 reset

仅更改 rev_map 和 refs/remotes/git-svn(参见下面 FILES 部分的 $GIT_DIR/svn/**/.rev_map.* 获取详细信息)。在 reset 之后,执行 fetch,然后执行 git resetgit rebase,将本地分支移动到新的树上。

-r <n>
--revision=<n>

指定要保留的最新版本。所有之后的版本都将被丢弃。

-p
--parent

也丢弃指定的版本,而是保留最近的父版本。

示例

假设你在 "master" 分支中有本地更改,但是你需要重新获取 "r2"。

    r1---r2---r3 remotes/git-svn
                \
                 A---B master

修复导致 "r2" 不完整的 ignore-paths 或 SVN 权限问题。然后

git svn reset -r2 -p
git svn fetch
    r1---r2'--r3' remotes/git-svn
      \
       r2---r3---A---B master

然后使用 git rebase 修复 "master"。不要使用 git merge,否则你的历史记录将与未来的 dcommit 不兼容!

git rebase --onto remotes/git-svn A^ master
    r1---r2'--r3' remotes/git-svn
                \
                 A'--B' master

选项

--shared[=(false|true|umask|group|all|world|everybody)]
--template=<template-directory>

仅与 init 命令一起使用。这些直接传递给 git init

-r <arg>
--revision <arg>

fetch 命令一起使用。

这允许支持部分/烧蚀历史的版本范围。支持 $NUMBER, $NUMBER1:$NUMBER2(数字范围), $NUMBER:HEAD, 和 BASE:$NUMBER。

这可以允许你在运行 fetch 时制作部分镜像;但是通常不建议这样做,因为历史记录将被跳过和丢失。

-
--stdin

仅与 set-tree 命令一起使用。

从 stdin 读取提交列表,并按相反的顺序提交它们。仅从每行读取前导的 sha1,因此可以使用 git rev-list --pretty=oneline 的输出。

--rmdir

仅与 dcommitset-treecommit-diff 命令一起使用。

如果 SVN 树中没有留下任何文件,则删除目录。SVN 可以对空目录进行版本控制,如果其中没有文件,则默认情况下不会删除它们。Git 无法对空目录进行版本控制。启用此标志将使提交到 SVN 的行为类似于 Git。

config key: svn.rmdir
-e
--edit

仅与 dcommitset-treecommit-diff 命令一起使用。

在提交到 SVN 之前编辑提交消息。对于作为提交的对象,默认情况下禁用此选项,而在提交树对象时强制启用此选项。

config key: svn.edit
-l<num>
--find-copies-harder

仅与 dcommitset-treecommit-diff 命令一起使用。

它们都直接传递给 git diff-tree;有关更多信息,请参见 git-diff-tree[1]

config key: svn.l
config key: svn.findcopiesharder
-A<filename>
--authors-file=<filename>

语法与 git cvsimport 使用的文件兼容,但是可以提供带有 <> 的空电子邮件地址。

	loginname = Joe User <user@example.com>

如果指定了此选项,并且 git svn 遇到 authors-file 中不存在的 SVN 提交者名称,git svn 将中止操作。然后,用户必须添加相应的条目。在修改 authors-file 之后,重新运行之前的 git svn 命令应该可以继续操作。

config key: svn.authorsfile
--authors-prog=<filename>

如果指定了此选项,对于 authors 文件中不存在的每个 SVN 提交者名称,将执行给定的文件,并将提交者名称作为第一个参数。该程序应该返回单行格式的 "Name <email>" 或 "Name <>",这将被视为包含在 authors 文件中。

由于历史原因,相对 filename 首先在相对于 initclone 的当前目录中搜索,以及相对于 fetch 的工作树的根目录中搜索。如果找不到 filename,则像 $PATH 中的任何其他命令一样搜索它。

config key: svn.authorsProg
-q
--quiet

使 git svn 不那么冗长。第二次指定使其更不冗长。

-m
--merge
-s<strategy>
--strategy=<strategy>
-p
--rebase-merges

这些仅与 dcommitrebase 命令一起使用。

如果无法使用 git reset(参见 dcommit),则在使用 dcommit 时直接传递给 git rebase

-n
--dry-run

可以与 dcommitrebasebranchtag 命令一起使用。

对于 dcommit,打印出 Git 参数序列,该参数将显示哪些差异将提交到 SVN。

对于 rebase,显示与当前分支关联的上游 svn 仓库关联的本地分支,以及将从中获取数据的 svn 仓库的 URL。

对于 branchtag,显示在创建分支或标签时将用于复制的 URL。

--use-log-author

在将 svn 提交检索到 Git 中(作为 fetchrebasedcommit 操作的一部分)时,在日志消息中查找第一个 From: 行或 Signed-off-by trailer,并将其用作作者字符串。

config key: svn.useLogAuthor
--add-author-from

在从 Git 提交到 svn(作为 set-treedcommit 操作的一部分)时,如果现有的日志消息还没有 From:Signed-off-by trailer,则追加一个基于 Git 提交的作者字符串的 From: 行。如果使用此选项,那么 --use-log-author 将为所有提交检索有效的作者字符串。

config key: svn.addAuthorFrom

高级选项

-i<GIT_SVN_ID>
--id <GIT_SVN_ID>

这设置了 GIT_SVN_ID(而不是使用环境变量)。这允许用户在使用跟踪单个 URL 时覆盖要从中获取的默认引用名称。logdcommit 命令不再需要此开关作为参数。

-R<remote-name>
--svn-remote <remote-name>

指定要使用的 [svn-remote "<remote-name>"] 部分,这允许跟踪多个 SVN 仓库。默认值:"svn"

--follow-parent

仅当跟踪分支(使用仓库布局选项 --trunk、--tags、--branches、--stdlayout 之一)时,此选项才相关。对于每个跟踪的分支,尝试找出其版本是从哪里复制的,并在分支的第一个 Git 提交中设置合适的父级。当跟踪一个在仓库中移动过的目录时,这尤其有用。如果禁用此功能,则 git svn 创建的分支将全部是线性的,不共享任何历史记录,这意味着将没有关于分支在哪里分支或合并的信息。但是,跟踪长/复杂的历史记录可能需要很长时间,因此禁用此功能可能会加快克隆过程。默认情况下启用此功能,使用 --no-follow-parent 禁用它。

config key: svn.followparent

仅限配置文件的选项

svn.noMetadata
svn-remote.<name>.noMetadata

这会删除每个提交末尾的 git-svn-id: 行。

此选项只能用于一次性导入,因为如果没有元数据,git svn 将无法再次获取。此外,如果你丢失了 $GIT_DIR/svn/**/.rev_map.* 文件,git svn 将无法重建它们。

git svn log 命令也将无法在使用了此选项的仓库上工作。由于(希望是)显而易见的原因,使用此选项与 useSvmProps 选项冲突。

不建议使用此选项,因为它会使在现有文档、错误报告和档案中查找旧的 SVN 版本号引用变得困难。如果你计划最终从 SVN 迁移到 Git 并且确定要删除 SVN 历史记录,请考虑 git-filter-repo。filter-repo 还允许重新格式化元数据以方便阅读,并为非 "svn.authorsFile" 用户重写作者身份信息。

svn.useSvmProps
svn-remote.<name>.useSvmProps

这允许 git svn 重新映射使用 SVN::Mirror (或 svk) 创建的镜像中的仓库 URL 和 UUID 以用于元数据。

如果一个 SVN 版本具有 "svm:headrev" 属性,则该版本很可能是由 SVN::Mirror(也被 SVK 使用)创建的。该属性包含一个仓库 UUID 和一个版本号。我们希望使其看起来像是在镜像原始 URL,因此引入一个辅助函数来返回原始身份 URL 和 UUID,并在提交消息中生成元数据时使用它。

svn.useSvnsyncProps
svn-remote.<name>.useSvnsyncprops

类似于 useSvmProps 选项;这是为使用 SVN 1.4.x 及更高版本随附的 svnsync(1) 命令的用户准备的。

svn-remote.<name>.rewriteRoot

允许用户从备用 URL 创建仓库。例如,管理员可以在服务器本地运行 git svn (通过 file:// 访问),但希望在元数据中使用公共 http:// 或 svn:// URL 分发仓库,以便用户看到公共 URL。

svn-remote.<name>.rewriteUUID

类似于 useSvmProps 选项;这是为需要手动重新映射 UUID 的用户准备的。这在原始 UUID 无法通过 useSvmProps 或 useSvnsyncProps 获取的情况下可能很有用。

svn-remote.<name>.pushurl

类似于 Git 的 remote.<name>.pushurl,此键旨在用于 url 通过只读传输指向 SVN 仓库的情况,以提供备用的读/写传输。假定两个键都指向同一个仓库。与 commiturl 不同,pushurl 是基本路径。如果可以使用 commiturlpushurl,则 commiturl 优先。

svn.brokenSymlinkWorkaround

禁用可能代价高昂的检查,以解决由损坏的客户端检入 SVN 的损坏的符号链接。如果跟踪具有许多非符号链接的空 blobs 的 SVN 仓库,请将此选项设置为 "false"。可以在 git svn 运行时更改此选项,并在下次获取版本时生效。如果未设置,则 git svn 假定此选项为 "true"。

svn.pathnameencoding

指示 git svn 将路径名重新编码为给定的编码。Windows 用户以及在非 utf8 区域设置中工作的人员可以使用它来避免带有非 ASCII 字符的损坏文件名。有效的编码是 Perl 的 Encode 模块支持的编码。

svn-remote.<name>.automkdirs

通常,"git svn clone" 和 "git svn rebase" 命令会尝试重新创建 Subversion 仓库中的空目录。如果此选项设置为 "false",则仅在显式运行 "git svn mkdirs" 命令时才会创建空目录。如果未设置,则 git svn 假定此选项为 "true"。

由于 noMetadata、rewriteRoot、rewriteUUID、useSvnsyncProps 和 useSvmProps 选项都会影响 git svn 生成和使用的元数据;它们必须在导入任何历史记录之前在配置文件中设置,并且一旦设置后,这些设置不应更改。

此外,每个 svn-remote 节只能使用这些选项中的一个,因为它们会影响 git-svn-id: 元数据行,rewriteRoot 和 rewriteUUID 除外,它们可以一起使用。

基本示例

跟踪并贡献给 Subversion 管理的项目的 trunk(忽略 tags 和 branches)

# Clone a repo (like git clone):
	git svn clone http://svn.example.com/project/trunk
# Enter the newly cloned directory:
	cd trunk
# You should be on master branch, double-check with 'git branch'
	git branch
# Do some work and commit locally to Git:
	git commit ...
# Something is committed to SVN, rebase your local changes against the
# latest changes in SVN:
	git svn rebase
# Now commit your changes (that were committed previously using Git) to SVN,
# as well as automatically updating your working HEAD:
	git svn dcommit
# Append svn:ignore and svn:global-ignores settings to the default Git exclude file:
	git svn show-ignore >> .git/info/exclude

跟踪并贡献给整个 Subversion 管理的项目(包含 trunk、tags 和 branches)

# Clone a repo with standard SVN directory layout (like git clone):
	git svn clone http://svn.example.com/project --stdlayout --prefix svn/
# Or, if the repo uses a non-standard directory layout:
	git svn clone http://svn.example.com/project -T tr -b branch -t tag --prefix svn/
# View all branches and tags you have cloned:
	git branch -r
# Create a new branch in SVN
	git svn branch waldo
# Reset your master to trunk (or any other branch, replacing 'trunk'
# with the appropriate name):
	git reset --hard svn/trunk
# You may only dcommit to one branch/tag/trunk at a time.  The usage
# of dcommit/rebase/show-ignore should be the same as above.

初始的 git svn clone 可能非常耗时(特别是对于大型 Subversion 仓库)。如果多个人(或一台机器上的同一个人)想要使用 git svn 与同一个 Subversion 仓库交互,你可以首先对服务器上的仓库执行初始的 git svn clone,然后让每个人都使用 git clone 克隆该仓库

# Do the initial import on a server
	ssh server "cd /pub && git svn clone http://svn.example.com/project [options...]"
# Clone locally - make sure the refs/remotes/ space matches the server
	mkdir project
	cd project
	git init
	git remote add origin server:/pub/project
	git config --replace-all remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
	git fetch
# Prevent fetch/pull from remote Git server in the future,
# we only want to use git svn for future updates
	git config --remove-section remote.origin
# Create a local branch from one of the branches just fetched
	git checkout -b master FETCH_HEAD
# Initialize 'git svn' locally (be sure to use the same URL and
# --stdlayout/-T/-b/-t/--prefix options as were used on server)
	git svn init http://svn.example.com/project [options...]
# Pull the latest changes from Subversion
	git svn rebase

REBASE VS. PULL/MERGE (变基 vs. 拉取/合并)

首选使用 git svn rebasegit rebase,而不是 git pullgit merge 来同步未集成的提交和 git svn 分支。这样做将使未集成的提交历史记录相对于上游 SVN 仓库保持线性,并允许使用首选的 git svn dcommit 子命令将未集成的提交推回到 SVN 中。

最初,git svn 建议开发人员从 git svn 分支拉取或合并。这是因为作者倾向于使用 git svn set-tree B 来提交单个 head,而不是使用 git svn set-tree A..B 表示法来提交多个提交。将 git pullgit mergegit svn set-tree A..B 一起使用会导致提交到 SVN 中时,非线性历史记录被扁平化,并且这可能会导致合并提交意外地撤消 SVN 中先前的提交。

MERGE TRACKING (合并跟踪)

虽然 git svn 可以跟踪采用标准布局的仓库的复制历史记录(包括分支和标签),但它还不能将 git 内部发生的合并历史记录向上游传递给 SVN 用户。因此,建议用户在 Git 中尽可能保持历史记录的线性,以简化与 SVN 的兼容性(请参阅下面的注意事项部分)。

HANDLING OF SVN BRANCHES (SVN 分支的处理)

如果 git svn 配置为获取分支(并且 --follow-branches 生效),它有时会为一个 SVN 分支创建多个 Git 分支,其中附加分支的名称形式为 branchname@nnn(其中 nnn 是一个 SVN 版本号)。如果 git svn 找不到 SVN 分支中第一次提交的父提交,以将该分支连接到其他分支的历史记录,则会创建这些附加分支。

通常,SVN 分支中的第一次提交包含复制操作。git svn 将读取此提交以获取创建分支的 SVN 版本。然后,它将尝试查找与此 SVN 版本对应的 Git 提交,并将其用作分支的父级。但是,可能没有合适的 Git 提交作为父级。如果 SVN 分支是未被 git svn 获取的版本(例如,由于它是使用 --revision 跳过的旧版本)的副本,或者如果在 SVN 中复制了 git svn 未跟踪的目录(例如,根本未跟踪的分支,或已跟踪分支的子目录),则会出现这种情况。在这些情况下,git svn 仍然会创建一个 Git 分支,但是它不会使用现有的 Git 提交作为分支的父级,而是会读取从其中复制分支的目录的 SVN 历史记录并创建适当的 Git 提交。这由消息 "Initializing parent: <branchname>" 指示。

此外,它将创建一个名为 <branchname>@<SVN-Revision> 的特殊分支,其中 <SVN-Revision> 是从其中复制分支的 SVN 版本号。此分支将指向该分支新创建的父提交。如果在 SVN 中删除了该分支,然后从不同的版本重新创建,则会有多个带有 @ 的此类分支。

请注意,这可能意味着为单个 SVN 版本创建了多个 Git 提交。

一个例子:在具有标准 trunk/tags/branches 布局的 SVN 仓库中,在 r.100 中创建了一个目录 trunk/sub。在 r.200 中,通过将其复制到 branches/ 来分支 trunk/sub。然后,git svn clone -s 将创建一个分支 sub。它还将为 r.100 到 r.199 创建新的 Git 提交,并将它们用作分支 sub 的历史记录。因此,对于 r.100 到 r.199 的每个版本,将有两个 Git 提交(一个包含 trunk/,一个包含 trunk/sub/)。最后,它将创建一个指向分支 sub 的新父提交的分支 sub@200(即 r.200 和 trunk/sub/ 的提交)。

注意事项

为了简单起见并与 Subversion 互操作,建议所有 git svn 用户直接从 SVN 服务器克隆、获取和 dcommit,并避免 Git 仓库和分支之间的所有 git clone/pull/merge/push 操作。在 Git 分支和用户之间交换代码的推荐方法是 git format-patchgit am,或者只是 'dcommit’ing 到 SVN 仓库。

不建议在你计划从中 dcommit 的分支上运行 git mergegit pull,因为 Subversion 用户看不到你所做的任何合并。此外,如果你从作为 SVN 分支镜像的 Git 分支合并或拉取,dcommit 可能会提交到错误的分支。

如果你确实合并,请注意以下规则:git svn dcommit 将尝试提交到 SVN 提交之上,该 SVN 提交在

git log --grep=^git-svn-id: --first-parent -1

因此,你必须确保你要 dcommit 到的分支的最新提交是合并的第一个父级。否则将会一片混乱,特别是如果第一个父级是同一 SVN 分支上的较旧提交。

git clone 不克隆 refs/remotes/ 层次结构下的分支或任何 git svn 元数据或配置。因此,使用 git svn 创建和管理的仓库应使用 rsync 进行克隆(如果需要进行克隆)。

由于 dcommit 在内部使用 rebase,因此你在 dcommit 之前 git push 到的任何 Git 分支都需要强制覆盖远程仓库上现有的引用。这通常被认为是不好的做法,请参阅 git-push[1] 文档以获取详细信息。

不要在你已经 dcommit 的更改上使用 git-commit[1] 的 --amend 选项。更改你已经推送到远程仓库供其他用户使用的提交被认为是不好的做法,而 dcommit 与 SVN 类似。

克隆 SVN 仓库时,如果没有使用任何用于描述仓库布局的选项(--trunk、--tags、--branches、--stdlayout),git svn clone 将创建一个具有完全线性历史记录的 Git 仓库,其中分支和标签显示为工作副本中的单独目录。虽然这是获取完整仓库副本的最简单方法,但对于具有许多分支的项目,它会导致工作副本比仅 trunk 大很多倍。因此,对于使用标准目录结构 (trunk/branches/tags) 的项目,建议使用选项 --stdlayout 进行克隆。如果项目使用非标准结构,并且/或者如果不需要分支和标签,则最简单的方法是仅克隆一个目录(通常是 trunk),而不提供任何仓库布局选项。如果需要包含分支和标签的完整历史记录,则必须使用选项 --trunk / --branches / --tags

当使用多个 --branches 或 --tags 时,git svn 不会自动处理名称冲突(例如,如果来自不同路径的两个分支具有相同的名称,或者如果分支和标签具有相同的名称)。在这些情况下,请使用 init 设置你的 Git 仓库,然后在第一次 fetch 之前,编辑 $GIT_DIR/config 文件,以便将分支和标签与不同的命名空间相关联。例如

branches = stable/*:refs/remotes/svn/stable/*
branches = debug/*:refs/remotes/svn/debug/*

配置

git svn 将 [svn-remote] 配置信息存储在仓库的 $GIT_DIR/config 文件中。它类似于核心 Git 的 [remote] 部分,但 fetch 键不接受 glob 参数;而是由 branchestags 键处理。由于某些 SVN 仓库的配置非常特殊,包含多个项目,因此允许使用如下所示的 glob 扩展。

[svn-remote "project-a"]
	url = http://server.org/svn
	fetch = trunk/project-a:refs/remotes/project-a/trunk
	branches = branches/*/project-a:refs/remotes/project-a/branches/*
	branches = branches/release_*:refs/remotes/project-a/branches/release_*
	branches = branches/re*se:refs/remotes/project-a/branches/*
	tags = tags/*/project-a:refs/remotes/project-a/tags/*

请记住,本地 ref (: 右侧) 的 * (星号) 通配符必须是最右边的路径组件;但是,远程通配符可以位于任何位置,只要它是一个独立的路径组件(被 / 或 EOL 包围)。这种类型的配置不是由 init 自动创建的,应该使用文本编辑器或 git config 手动输入。

另请注意,每个单词只允许一个星号。 例如

branches = branches/re*se:refs/remotes/project-a/branches/*

将匹配分支 releaseresere123se,但是

branches = branches/re*s*e:refs/remotes/project-a/branches/*

将产生错误。

也可以使用大括号中以逗号分隔的名称列表来获取分支或标签的子集。 例如

[svn-remote "huge-project"]
	url = http://server.org/svn
	fetch = trunk/src:refs/remotes/trunk
	branches = branches/{red,green}/src:refs/remotes/project-a/branches/*
	tags = tags/{1.0,2.0}/src:refs/remotes/project-a/tags/*

支持多个 fetch、branches 和 tags 键

[svn-remote "messy-repo"]
	url = http://server.org/svn
	fetch = trunk/project-a:refs/remotes/project-a/trunk
	fetch = branches/demos/june-project-a-demo:refs/remotes/project-a/demos/june-demo
	branches = branches/server/*:refs/remotes/project-a/branches/*
	branches = branches/demos/2011/*:refs/remotes/project-a/2011-demos/*
	tags = tags/server/*:refs/remotes/project-a/tags/*

在这种配置中创建分支需要使用 -d 或 --destination 标志来区分使用哪个位置

$ git svn branch -d branches/server release-2-3-0

请注意,git-svn 会跟踪分支或标签出现的最高修订版本。 如果在获取后更改了分支或标签的子集,则必须手动编辑 $GIT_DIR/svn/.metadata 以删除(或重置)branches-maxRev 和/或 tags-maxRev (如果适用)。

文件

$GIT_DIR/svn/**/.rev_map.*

Subversion 修订号和 Git 提交名称之间的映射。 在未设置 noMetadata 选项的仓库中,可以从每个提交末尾的 git-svn-id: 行重建此映射(有关详细信息,请参阅上面的 svn.noMetadata 部分)。

git svn fetchgit svn rebase 会在 rev_map 丢失或不是最新时自动更新它。 git svn reset 会自动倒回它。

BUG

我们忽略除 svn:executable 之外的所有 SVN 属性。 任何未处理的属性都将记录到 $GIT_DIR/svn/<refname>/unhandled.log

重命名和复制的目录不会被 Git 检测到,因此在提交到 SVN 时不会被跟踪。 我不打算添加对此的支持,因为它很难且耗时才能为所有可能的极端情况工作(Git 也没有这样做)。 如果重命名和复制的文件足够相似以供 Git 检测到,则完全支持提交重命名和复制的文件。

在 SVN 中,可以(尽管不鼓励)提交对标签的更改(因为标签只是一个目录副本,因此技术上与分支相同)。 克隆 SVN 仓库时,git svn 无法知道将来是否会发生此类提交到标签的操作。 因此,它会采取保守的措施,并将所有 SVN 标签作为分支导入,并在标签名称前加上 tags/

参见

GIT

属于 git[1] 套件的一部分

scroll-to-top