directory search
Guides gitattributes giteveryday gitglossary gitignore gitmodules gitrevisions gittutorial gitworkflows Administration git archive git bundle git clean git filter-branch git fsck git gc git instaweb git reflog Basic Snapshotting git add git commit git diff git mv git reset git rm git status Branching and Merging git branch git checkout git log git merge git mergetool git stash git tag Debugging git bisect git blame git grep Email git am git format-patch git request-pull git send-email External Systems git fast-import git svn Getting and Creating Projects git clone git init Git git annotate git archimport git bisect-lk2009 git check-attr git check-mailmap git check-ref-format git checkout-index git cherry git citool git column git credential git credential-cache git credential-store git cvsexportcommit git cvsimport git cvsserver git diff-files git diff-tree git difftool git fast-export git fetch-pack git fmt-merge-msg git get-tar-commit-id git gui git http-backend git http-fetch git http-push git imap-send git index-pack git interpret-trailers git ls-remote git ls-tree git mailinfo git mailsplit git merge-file git merge-index git merge-one-file git merge-tree git mktag git mktree git name-rev git notes git p4 git pack-objects git pack-redundant git pack-refs git parse-remote git patch-id git prune git prune-packed git quiltimport git receive-pack git remote-ext git remote-fd git remote-testgit git repack git replace git rerere git send-pack git sh-i18n git sh-setup git shell git show-branch git show-index git stripspace git unpack-file git unpack-objects git upload-archive git upload-pack git var git verify-commit git verify-tag git whatchanged git worktree Inspection and Comparison git describe git shortlog git show Miscellaneous api credentials api index gitcli gitcore tutorial gitcredentials gitcvs migration gitdiffcore githooks gitk gitnamespaces gitremote helpers gitrepository layout gitsubmodules gittutorial 2 gitweb gitweb.conf pack format User Manual Patching git apply git cherry-pick git rebase git revert Plumbing Commands git cat-file git check-ignore git commit-tree git count-objects git diff-index git for-each-ref git hash-object git ls-files git merge-base git read-tree git rev-list git rev-parse git show-ref git symbolic-ref git update-index git update-ref git verify-pack git write-tree Server Admin git daemon git update-server-info Setup and Config git git config git help Sharing and Updating Projects git fetch git pull git push git remote git submodule
characters

命名

git-svn  -  Subversion版本库和Git之间的双向操作

概要

git svn <command> [options] [arguments]

描述

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

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

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

命令

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

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

--use-svm-props

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

--use-svnsync-props

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

--rewrite-root=<URL>

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

--rewrite-uuid=<UUID>

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

--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自己的远程跟踪引用布局兼容(参考文献/远程/ $远程/)。如果您希望跟踪共享公共存储库的多个项目,那么设置前缀也很有用。默认情况下,前缀设置为origin/

注意

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

--ignore-refs=<regex>

当传递给initclone正则表达式将被保存为配置密钥。请参阅fetch有关说明--ignore-refs

--ignore-paths=<regex>

当传递给initclone正则表达式将被保存为配置密钥。请参阅fetch有关说明--ignore-paths

--include-paths=<regex>

当传递给initclone正则表达式将被保存为配置密钥。请参阅fetch有关说明--include-paths

--no-minimize-url

当跟踪多个目录(使用--stdlayout, -  branch或-tags选项)时,git svn将尝试连接到Subversion存储库的根(或最高允许级别)。如果整个项目在存储库中移动,则此默认值允许更好地跟踪历史记录,但可能会导致存在读取访问限制的存储库中出现问题。传递--no-minimize-url将允许git svn按原样接受URL,而不尝试连接到更高级别的目录。当只有一个URL /分支被跟踪时,这个选项默认是关闭的(它不会有什么好处)。

fetch

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

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

--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"

跳过第一级目录的“分支”和“标签”

--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的基名自动创建一个目录; 或者是否传递了第二个参数; 它会创建一个目录并在其中工作。它接受initfetch命令接受的所有参数; 除了--fetch-all--parent。克隆存储库后,该fetch命令将能够更新修订版而不影响工作树; 并且该rebase命令将能够使用最新更改更新工作树。

--preserve-empty-dirs

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

--placeholder-filename=<filename>

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

rebase

这会从当前HEAD的SVN父节点获取修订,并将当前(未提交到SVN)的工作重新绑定到它。

这与其相似svn updategit pull除了它保留了线性历史记录git rebase而不是git merge为了方便提交git svn

这接受所有选项git svn fetchgit rebase接受。但是,--fetch-all只能从当前的svn-remote中获取,而不是所有的svn-remote定义。

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

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

-l   --local

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

dcommit

将当前分支中的每个diff直接提交到SVN存储库,然后重新绑定或重置(取决于SVN和head之间是否存在差异)。这将在Git中为每个提交创建SVN修订。

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

使用dcommit优于set-tree(下面)。

--no-rebase

提交后,不要重新设置或重置。

--commit-url <URL>

提交到这个SVN URL(完整路径)。这样做的目的在于,如果稍后用户可以访问替代传输方法(例如或)来提交,那么允许git svn使用一种传输方法(例如svn://http://用于匿名读取)创建的现有存储库被重用。svn+ssh://https://

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

请注意,commiturl config密钥的SVN URL包含SVN分支。如果您想为整个SVN存储库设置提交URL,请改为使用svn-remote。<name> .pushurl。

使用这个选项用于任何其他目的(不要问)非常不鼓励。

--mergeinfo=<mergeinfo>

在dcommit(eg --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属性。目前,只有在提交非快进合并的情况下,只有第一个父母已经被推入SVN的情况下才能完成此操作。

--interactive

要求用户确认补丁集应该实际发送给SVN。对于每个补丁,可以回答“是”(接受此补丁),“否”(丢弃此补丁),“全部”(接受所有补丁)或“退出”。

git svn dcommit 如果回答为“否”或“退出”,则立即返回,但不向SVN提交任何内容。

branch

在SVN存储库中创建一个分支。

-m   --message

允许指定提交消息。

-t   --tag

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

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

如果给initor clone命令提供了多个--branches(或--tags)选项,则必须提供您希望在SVN存储库中创建的分支(或标签)的位置。<path>指定用于创建分支或标记的路径,并且应该与其中一个配置的分支或标记refspecs的左侧的模式相匹配。您可以使用这些命令查看这些refspecs

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

其中<name>是由-R选项init(默认情况下为“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 /  - 修订号时,这应该能够轻松查找svn日志消息。

'svn log'支持以下功能:

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

支持,非数字参数不是:HEAD,NEXT,BASE,PREV等...

-v   --verbose

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

--limit=<n>

与--max-count不同,不会计入合并/排除提交

--incremental

支持的

新功能:

--show-commit

也显示了Git commit 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

当给定表单的SVN修订号时rN,返回相应的Git提交散列(可以选择后跟一个tree-ish来指定应该搜索哪个分支)。当给定树时,返回相应的SVN修订版号。

-B   --before

如果给定SVN修订版,不要求完全匹配,而是在指定修订版中找到与SVN存储库(在当前分支上)相对应的提交。

-A   --after

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

set-tree

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

create-ignore

递归查找目录上的 svn:ignore 属性并创建匹配的 .gitignore 文件。生成的文件被分阶段提交,但未提交。使用 -r /  -  revision 来引用特定的版本。

show-ignore

递归查找并列出目录上的 svn:ignore 属性。输出适用于追加到 $ 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

提交命令行中两个树型参数的差异。该命令不依赖于在git svn init-ed存储库中。这个命令有三个参数,(a)原始树进行区分,(b)新的树结果,(c)目标Subversion存储库的URL。如果您正在使用git svn-aware存储库(已init与之配合使用git svn),则可以省略最后一个参数(URL )。这需要-r <revision>选项。

当第二个 tree-ish 表示这样一个对象,或者通过调用一个编辑器(请参阅下面的选项)请求时,提交消息直接提供给-mor -F选项,或者间接来自标记或提交--edit

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

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

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

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

info

显示有关类似'svn info'提供的文件或目录的信息。目前不支持-r /  - 修订参数。使用--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:keywordsFreeBSD=%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选项,a fetch可能会因“未在提交中找到”(文件先前不可见)或“校验和不匹配”(错过修改)而失败。如果问题文件永远不能被忽略(使用--ignore-paths),修复repo的唯一方法就是使用reset

只有rev_map和refs / remotes / git-svn被更改(请参阅$GIT_DIR/svn/*\*/.rev_map.*下面的FILES部分了解详细信息)。跟随reset一个fetch然后git resetgit rebase移动当地分支到新的树上。

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

指定要保留的最新版本。以后的所有修订都会被丢弃。

-p   --parent

同样放弃指定的修订版本,而是保留最近的父版本。

例子:

假设您在“主”中进行了本地更改,但您需要重新提取“r2”。

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

修复首先导致“r2”不完整的忽略路径或SVN权限问题。然后:

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

然后修正“主”与git rebase。不要使用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都支持。

这可以使您在运行提取时创建部分镜像; 但通常不推荐使用,因为历史记录会被跳过并丢失。

  • --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遇到作者文件中不存在的SVN提交者名称,git svn则会中止操作。用户将不得不添加适当的条目。git svn作者文件被修改后重新运行前面的命令应该继续运行。

config key: svn.authorsfile

--authors-prog=<filename>

如果指定了此选项,则对于作者文件中不存在的每个SVN提交者名称,将使用提交者名称作为第一个参数来执行给定文件。该程序预计会返回一个形式为“Name <email>”的单行,该行将被视为包含在作者文件中。

config key: svn.authorsProg

-q   --quiet

git svn更简洁。再指定一次,使其更加冗长。

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

这些仅用于dcommitrebase命令。

如果a 不能使用,请直接转至git rebase使用时间(请参阅)。dcommitgit resetdcommit

-n   --dry-run

这可以通过使用dcommitrebasebranchtag命令。

对于dcommit,打印出一系列Git参数,这些参数将显示哪些差异将提交给SVN。

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

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

--use-log-author

当检索SVN提交到Git的(作为的一部分fetchrebase或者dcommit操作),找第一From:Signed-off-by:日志消息行和使用,作为作者的字符串。

config key: svn.useLogAuthor

--add-author-from

当承诺的SVN混帐(作为的一部分commit-diffset-tree或者dcommit操作),如果现有的日志消息不已经有一个From:Signed-off-by:行,追加一个From:基于Git的行提交的作者字符串。如果你使用这个,那么--use-log-author将为所有提交检索一个有效的作者字符串。

config key: svn.addAuthorFrom

高级选项

-i<GIT_SVN_ID>   --id <GIT_SVN_ID>

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

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

指定要使用的svn-remote“<remote name>”部分,这允许SVN多个存储库被跟踪。默认值:“svn”

--follow-parent

如果我们跟踪分支(使用存储库布局选项之一--trunk,--tags, -  branch,--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-branch [1]。filter-branch还允许重新格式化元数据,以便读取和重写非“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存储库以提供备用读/写传输的情况。假定两个键都指向同一个存储库。不像commiturlpushurl是一个基本路径。如果使用commiturlpushurl可以使用,commiturl则优先。

svn.brokenSymlinkWorkaround

这将禁用潜在的昂贵检查来解决由破碎的客户端检入到SVN中的损坏的符号链接。如果您跟踪具有许多空符号链接的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管理项目的主干(忽略标签和分支):

# 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 settings to the default Git exclude file:
        git svn show-ignore >> .git/info/exclude

跟踪和贡献整个Subversion管理的项目(包含干线,标签和分支):

# 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

喜欢使用git svn rebasegit rebase,而不是git pullgit merge以非整合的提交与同步git svn分支。这样做会使未集成的提交历史与上游SVN存储库保持线性关系,并允许使用首选的git svn dcommit子命令将未集成的提交推回到SVN中。

最初,git svn建议开发商从git svn分支机构撤出或合并。这是因为作者倾向于git svn set-tree B提交一个单独的头部而不是git svn set-tree A..B标记来提交多个提交。使用git pullgit merge使用git svn set-tree A..B会导致触犯到SVN时被压扁的非线性历史,这可能导致合并提交意外扭转了以前的SVN提交。

Merge tracking

虽然git svn可以追踪采用标准布局的存储库的复制历史记录(包括分支和标签),但它还不能代表SVT用户在git上游发生的合并历史记录。因此,建议用户在Git中保持历史尽可能线性,以便与SVN兼容(请参阅下面的CAVEATS部分)。

Handling of svn branches

如果git svn配置为获取分支(并且--follow分支有效),它有时会为一个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中,trunk / sub通过将其复制到分支/来进行分支。git svn clone -s然后将创建一个分支sub。它还将为r.100到r.199创建新的Git提交并将其用作分支的历史记录sub。因此,从r.100到r.199的每个修订将有两个Git提交(其中一个包含trunk /,一个包含trunk / sub /)。最后,它会创建一个分支,sub@200指向分支的新的父提交sub(即提交r.200和trunk / sub /)。

Caveats

为简单起见,并与Subversion互操作,则建议所有git svn用户克隆,提取和dcommit直接从SVN服务器,并避免所有git clone/ pull/ merge/ pushGit存储区和支路之间的操作。GIT中分支和用户之间交换代码的推荐的方法是git format-patchgit am,或只是“dcommit'ing至SVN库。

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

如果您合并,请注意以下规则:git svn dcommit将尝试提交在名为in的SVN提交之上

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

must因此,您确保您想要提交的分支的最近提交是first合并的父代。否则就会出现混乱,尤其是如果第一个父代在同一个SVN分支上是较旧的提交。

git clone不会在refs / remotes /层次结构或任何git svn元数据或配置下克隆分支。因此,如果要完成克隆,使用创建和管理的存储库git svn应该rsync用于克隆。

由于dcommit内部使用重订,任何的Git分支您git push之前dcommit就需要迫使现有裁判的覆盖上的远程存储库。这通常被认为是不好的做法,详情请参阅git-push [1]文档。

不要在您已经提交的更改中使用git-commit [1]的--amend选项。对于已经推送到其他用户的远程存储库的验证提交被认为是不好的做法,而使用SVN的dcommit与此类似。

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

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

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

Bugs

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

重命名和复制的目录不会被Git检测到,因此在提交SVN时不会被跟踪。我不打算增加对此的支持,因为为所有可能的角落案例工作是非常困难和耗时的(Git也没有这样做)。完全支持提交重命名和复制的文件,只要它们足够类似于Git来检测它们即可。

在SVN中,可以(虽然不鼓励)对标签提交更改(因为标签只是目录副本,因此在技术上与分支相同)。克隆SVN存储库时,git svn不知道将来是否会对此标签进行提交。因此,它保守地行事,并将所有SVN标签作为分支导入,以标签名称作为前缀tags/

组态

git svn将svn-remote配置信息存储在存储库$ GIT_DIR / config文件中。它类似于核心的Git远程部分,但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/*

请记住,*本地引用(:*)右边的(星号)通配符必须是最右边的正确路径组件; 但是,只要远程通配符是独立路径组件(由/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/*

支持多个提取,分支和标签密钥:

[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以根据需要删除(或重置)分支-maxRev和/或tags-maxRev。

Files

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

Subversion版本号和Git提交名之间的映射。在没有设置noMetadata选项的存储库中,可以从每次提交结束时的git-svn-id:行重新创建(参见svn.noMetadata上面的细节部分)。

git svn fetchgit svn rebase自动更新rev_map,如果它丢失或不是最新的。git svn reset自动倒带它。

Previous article: Next article: