33.1 克隆 SVN 仓库
你需要使用以下命令创建一个新的本地仓库副本:
git svn clone SVN_REPO_ROOT_URL [DEST_FOLDER_PATH] -T TRUNK_REPO_PATH -t TAGS_REPO_PATH -b BRANCHES_REPO_PATH
如果你的 SVN 仓库遵循标准布局(trunk、branches、tags 文件夹),可以简化操作:
git svn clone -s SVN_REPO_ROOT_URL [DEST_FOLDER_PATH]
git svn clone 会逐个检出 SVN 的每个修订版本,并在你的本地仓库中创建一个 git 提交,以重建历史记录。如果 SVN 仓库中有大量提交,这将需要一些时间。
当命令完成后,你将拥有一个完整的 git 仓库,其中包含一个名为 master 的本地分支,该分支跟踪 SVN 仓库的 trunk 分支。
33.2 将本地更改推送到 SVN
命令
git svn dcommit
会为你的每个本地 git 提交创建一个 SVN 修订版本。与 SVN 一样,你的本地 git 历史必须与 SVN 仓库中的最新更改保持同步,因此如果命令失败,尝试先执行 git svn rebase。
33.3 本地操作
就像使用正常的 git 仓库一样,使用以下常规 git 命令:
git add FILE和git checkout -- FILE用于暂存/取消暂存文件。git commit用于保存更改。这些提交是本地的,不会“推送到” SVN 仓库,就像在正常的 git 仓库中一样。git stash和git stash pop允许使用暂存。git reset HEAD --hard撤销所有本地更改。git log访问仓库中的所有历史记录。git rebase -i允许自由重写本地历史。git branch和git checkout用于创建本地分支。
正如 git-svn 文档所述,“Subversion 是一个远不如 Git 复杂的系统”,因此你不能使用 Git 的全部功能而不破坏 Subversion 服务器上的历史记录。幸运的是,规则很简单:保持历史线性。 这意味着你可以执行几乎所有 git 操作:创建分支、移除/重新排序/合并提交、移动历史记录、删除提交等。但不能执行合并操作。如果你需要重新整合本地分支的历史记录,使用 git rebase 而不是合并。 执行合并时,会创建一个合并提交。合并提交的特殊之处在于它们有两个父提交,这使得历史记录变得非线性。非线性历史记录在你将合并提交“推送到”仓库时会混淆 SVN。 不过不用担心:如果你将 git 合并提交“推送到” SVN,不会破坏任何东西。如果你这样做,当 git 合并提交发送到 SVN 服务器时,它将包含该合并的所有提交的所有更改,因此你将丢失这些提交的历史记录,但不会丢失代码中的更改。
33.4 获取 SVN 中的最新更改
相当于 git pull 的命令是:
git svn rebase
此命令从 SVN 仓库获取所有更改,并将它们应用到你当前分支的本地提交之上。 你也可以使用以下命令:
git svn fetch
此命令从 SVN 仓库获取更改并将其带到你的本地机器,但不会将其应用到你的本地分支。
33.5 处理空文件夹
Git 不识别文件夹的概念,它只处理文件及其路径。这意味着 Git 不跟踪空文件夹。然而,SVN 却可以。使用 git-svn 时,默认情况下,你对空文件夹所做的更改不会传播到 SVN。 在提交时使用 --rmdir 标志可以解决这个问题,并在你本地删除文件夹中的最后一个文件时,删除 SVN 中的空文件夹:
git svn dcommit --rmdir
不幸的是,它不会删除现有的空文件夹:你需要手动删除它们。 为了避免每次执行 dcommit 时都添加该标志,或者如果你使用的是 git GUI 工具(如 SourceTree),为了安全起见,你可以将此行为设置为默认值:
git config --global svn.rmdir true
这会更改你的 .gitconfig 文件,并添加以下内容:
[svn]
rmdir = true
要删除所有未跟踪的文件和文件夹(这些文件和文件夹应该为空以供 SVN 使用),可以使用以下命令:
git clean -fd
请注意:此命令将删除所有未跟踪的文件和空文件夹,包括那些应该由 SVN 跟踪的文件夹!如果你需要重新生成 SVN 跟踪的空文件夹,可以使用以下命令:
git svn mkdirs
实际上,这意味着如果你想清理工作区中的未跟踪文件和文件夹,你应该始终使用这两个命令来重新生成 SVN 跟踪的空文件夹:
git clean -fd && git svn mkdirs