0%

SVN 命令基础用法

工作以来,使用的版本控制工具一直是 SVN(Subversion)。在 Windows 下使用的是 SVN 的图形界面工具,在 Linux 系统下,使用的是 SVN 命令行。虽然接触 SVN 已经有几年历史了,但是很多时候为了完成稍微复杂一些的日常任务,总是不得不去网上查找,这显得不是那么 酷炫。所以这次下定决心,好好学习 SVN 命令的基础用法。

本篇文章将覆盖日常工作流程中对 SVN 的基本用法,不涉及 SVN 服务器的配置以及仓库管理等高级话题。

SVN 基础理论

SVN 是一个版本控制工具,用来跟踪文件的版本变化。版本控制工具的核心概念是仓库(repository),它是系统数据的集中存储,通常以目录树的形式组织信息。客户端连接到仓库后,可以读写文件。

SVN 使用的是 copy-modify-merge 版本控制模型。客户端和 SVN 仓库建立连接后,可以创建项目文件的本地副本,每个人在自己的本地私有版本上进行修改,最后将自己的私有副本合并到 SVN 仓库。在合并的时候,可能会出现修改冲突,此时需要个人手动解决冲突问题。

SVN 同时也提供 lock-modify-unlock 的版本控制模型,主要是方便对非文本文件进行版本控制。

SVN 仓库在接受 SVN 客户端提交的修改(commit)后,会创建文件系统树的一个新状态,并用唯一的一个自然数标识,该数字称为 revision。新创建的 SVN 仓库初始 revision 为 0,此后随着客户端的每次提交, SVN 仓库的 revision 将逐渐递增。注意,SVN 的 revision 是应用于整个仓库,而不是独立的文件。所以 foo.c 的 revision 为 5 真实含义为 svn 仓库为 revision 5 时 的 foo.c。

SVN 本地副本(working copy)是本地系统中的目录树。当然 SVN 本地副本中也包含一些由 SVN 创建和维护的文件,每个本地副本下都包含一个子目录 .svn,该目录也被称为 SVN 的 管理目录。对于本地副本的每个文件,SVN 都会记录两个信息:

  • 该文件基于的 revision
  • 该文件上次从仓库更新的时间戳

通过以上信息,以及对比 SVN 仓库,本地副本的文件可以有以下四种状态:

  • Unchanged, and current:文件本地未修改,SVN 仓库中的对应文件也未被修改
  • Locally Changed, and current:文件本地被修改,SVN 仓库中的对应文件未被修改。此时 svn commit 可以提交修改,svn update 对文件没有影响
  • Unchanged, and out of date:文件本地未修改,SVN 仓库中的对应文件已经被修改。此时 svn commit 无影响,svn update 将更新本地文件
  • Locally changed, and out of date:文件本地被修改,SVN 仓库中的对应文件也被修改。此时 svn commit 将会失败,原因是 out-of-date。首先需要使用 svn update 更新该文件,更新本地副本时 SVN 将会尝试合并公共修改和本地修改,如果出现冲突,需由用户手动解决冲突

需要注意,在 SVN 中 commitupdate 是相互独立的。push 动作并不引发执行 pull,反之亦然。所以,每次你使用 svn commit 提交某个文件的修改后,你的本地仓库将处于 mixed revisions 状态:所提交的文件将处于最新的 revision,而其它文件可能还处于旧的 revision。mixed revision 在开发流程中有时也很有作用。

SVN 基本用法

接下来将介绍 SVN 的基本用法,这些知识足以让你完成日常工作中的绝大多数任务。SVN 命令的完整手册可以访问这里

使用 svn help 命令可以获取 SVN 命令行的帮助信息,使用 svn help SUBCOMMAND 获取每个子命令的详细帮助信息,包括子命令的语法、选项和行为。

导入数据到仓库

svn import 命令是最快速的方法,用于把未版本化的文件拷贝到 SVN 仓库,在导入过程中将按需创建中间目录。当你本地已经有工作目录树,希望使用 SVN 进行版本跟踪,可以使用该命令:

1
svn import /path/to/mytree http://svn.example.com/svn/repo/some/project -m "Initial import"

执行上述命令,mytree 目录下的文件都将被拷贝到 SVN 仓库,而 SVN 仓库中的目录并不需要手动创建,import 命令将自动帮你完成这一过程。需要注意,import 命令完成后,本地目录并不会自动成为 working copy,还是需要重新创建本地副本。

仓库布局惯例

尽管 SVN 允许你在仓库中创建任意的目录和文件,但是在漫长的开发岁月中,关于代码仓库的布局已经形成了一套传统,这些布局规则中的代码目录名称将为开发人员提供有价值的信息。

首先,仓库中的每个项目都有一个可标识的项目根目录(project root)。其次,该项目根目录下将包含以下子目录:

  • trunk:项目开发主线
  • branches:用于不同开发目的的分支
  • tags:完成一些开发需求后的稳定版本

创建本地副本

使用 svn checkout 命令从 SVN 仓库中创建项目的本地副本,默认情况下,该命令将获取目录的最新版本以及该目录下的所有子目录。

1
svn checkout http://svn.example.com/svn/repo/trunk

使用该命令后,将在本地文件系统创建一个目录,目录名为 checkout URL 的最后一个组件名。当然你也可以显式指定本地目录的名称,如果该目录不存在,checkout 命令将帮你创建:

1
svn checkout http://svn.example.com/svn/repo/trunk my-working-copy

更新本地副本

通常一个项目会有多个人同时修改,为了使你的本地工作副本更新到 SVN 仓库的最新状态,可以使用 svn uddate 命令。

1
2
3
4
5
$ svn update
Updating '.':
U foo.c
U bar.c
Updated to revision 2.

本地修改

在将本地工作副本更新到最新状态后,就可以开始你自己的修改了。通常存在两种形式的修改:

  • 文件内容的修改
  • 目录结构的修改

对文件内容的修改,不需要额外通知 SVN 什么信息,直接使用你的编辑器修改文件即可。但是对于目录结构的修改(包括添加/删除文件或目录,重命名文件或目录,移动文件或目录),需要使用 SVN 命令来进行操作。注意这些命令执行完毕后只在本地工作副本立即生效,只有 commit 后才会在 SVN 仓库生效

  • svn add:添加文件/目录到 SVN 仓库。如果添加的是目录,目录底下的所有内容都会被添加,可以使用 --depth=empty 来添加目录本身
  • svn delete:从 SVN 仓库中删除文件/目录。如果删除是文件,该操作在本地工作副本下立即生效。如果删除的是目录,只有提交后才会从本地副本和 SVN 仓库中删除该目录
  • svn copy FOO BAR:创建一个 FOO 的副本,名为 BAR。除非使用 —parents 选项,否则不创建中间目录
  • svn move FOO BAR:将 FOO 重命名为 BAR,该命令等效于运行 svn copy FOO BARsvn delete FOO
  • svn mkdir FOO:创建一个新目录 FOO,该命令等效于运行 mkdir FOOsvn add FOO

SVN 支持直接修改仓库的内容,即不通过 commit 本地修改的方式。svn mkdir / svn copy / svn more / svn delete 都可以直接使用仓库 URL 作为参数,从而直接对仓库进行修改。

查看你的修改

查看整体修改

在提交修改之前,通常需要对本地修改进行确认。使用 svn status 命令可以查看整体修改。

1
2
3
4
5
6
$ svn status
? scratch.c
A stuff/loot
A stuff/loot/new.c
D stuff/old.c
M bar.c

该命令的输出会显示所有本地修改过的文件,文件前的字符显示了修改状态:

  • ?:该文件/目录未在版本控制下
  • A:该文件/目录即将新添加到 SVN 仓库
  • C:文件处于冲突状态。这表明从仓库更新后对该文件的修改和本地修改出现冲突。在提交仓库之前必须手动解决冲突
  • D:该文件/目录即将从 SVN 仓库删除
  • M:文件内容被修改

使用 --verbose(-v) 选项,可以看到本地副本所有文件的状态,即使该文件未被修改,而且输出信息更详细:

1
2
$ svn status -v
M 44 23 sally README

该命令输出的第一列表示文件修改状态,第二列输出表示文件的当前 revision,第三列输出表示文件上次被修改后的 revision,第四列表示上次谁修改该文件,第五列表示文件名。

可以使用 --show-update(-u) 选项,查看自上次更新以来,哪些文件在 SVN 仓库中已经被修改过,即查看本地副本中的过期文件。

查看详细修改

使用 svn diff 命令可以查看文件内容的差异。在本地副本的顶级目录下运行该命令,可以查看本地副本下所有修改文件的差异。该命令的输出采用统一的 diff 文件格式,所以 svn diff 命令的输出结果可以应用于 patch 程序,这样就可以把你在本地副本上所做的修改共享给其他人,而不需要首先提交该修改。

1
$ svn diff > patchfile

svn diff 命令也可以使用外部程序来产生不同的 diff 文件格式,使用 --diff-cmd 传递外部程序的名称,使用 --extensions(-x) 来指定传递给该外部程序的选项参数。示例如下:

1
2
$ svn diff --diff-cmd /usr/bin/diff -x "-i" foo.c
...

修正错误

当使用 svn diff 命令检查所有修改后,如果你发现对某个文件的修改存在错误,一种解决办法是将文件恢复到原始状态,然后重新进行修改。在 SVN 中,可以使用 svn revert 命令达到该效果。

1
2
3
4
5
$ svn status README
M README
$ svn revert README
Reverted 'README'
$ svn status README

除了对文件内容的还原,svn revert 也能够对文件的添加/删除进行还原。例如,取消对文件的添加:

1
2
3
4
5
6
7
8
$ svn status new-file.txt
? new-file.txt
$ svn add new-file.txt
A new-file.txt
$ svn revert new-file.txt
Reverted 'new-file.txt'
$ svn status new-file.txt
? new-file.txt

解决冲突

当仓库中的某个文件出现了修改,而你在本地副本中也对该文件进行了修改,之后使用 svn update 命令对该文件进行更新时,该文件可能会出现冲突。

假设执行 svn update 命令出现如下输出:

1
2
3
4
5
6
7
8
$ svn update
Updating '.':
U INSTALL
G README
Conflict discovered in 'bar.c'.
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options:

对于标识为 U(updated,表示已更新)和标识为 G(merGed,表示已合并)的文件不需要关心,这些文件正常地从仓库中获取了更新。但是对于文件 bar.c 则出现了冲突,此时 SVN 将询问你采取何种措施来解决冲突。可采取的动作包括:

  • e,edit:使用编辑器打开出现冲突的文件,编辑器由环境变量 EDITOR 指定
  • df,diff-full: 显示该文件的 base revision 和当前内容的差异
  • r,resolve:当编辑文件之后,告诉 SVN 你已经解决了冲突,SVN 应该接受文件的当前内容
  • dc,display-conflict:显示文件的所有冲突区域,忽略已经成功合并的部分
  • mc,mine-conflict:对于和本地修改出现冲突的仓库修改,全部采用本地修改。但是仍接受从仓库中获取的未冲突修改
  • tc,theirs-conflict:对于和本地修改出现冲突的仓库修改,全部采用仓库修改,即忽略本地修改。但是仍保留本地文件中的未冲突修改。
  • mf,mine-full:忽略所有从仓库中获取到的修改,同时全部保留本地修改
  • tf,theirs-full:忽略所有本地修改,同时全部接受从仓库中获取的修改
  • p,postone:将该文件保留为冲突状态,在 update 命令执行完毕之后再进行解决
  • l,launch:启动外部程序来解决冲突,该方式需要做一些提前设置
  • s,show all:显示交互式解决冲突时所有可使用的命令

交互式地查看冲突

使用 df(diff-full) 命令可以显示冲突区域对应的本地修改(相比较于 base revision):

1
2
3
4
5
6
7
8
9
10
11
12
13
...
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: df
--- .svn/text-base/sandwich.txt.svn-base Tue Dec 11 21:33:57 2007
+++ .svn/tmp/tempfile.32.tmp Tue Dec 11 21:34:33 2007
@@ -1 +1,5 @@
-Just buy a sandwich.
+<<<<<<< .mine
+Go pick up a cheesesteak.
+=======
+Bring me a taco!
+>>>>>>> .r32

在这个例子中,diff 内容的第一行显示了对本地副本(即 Base Revision)的修改,这些修改没有出现冲突。

1
-Just buy a sandwich.

接下来的内容行则是出现冲突的区域,首先是你的修改:

1
+Go pick up a cheesesteak.

之后的内容行则是从服务器中收到的修改:

1
+Bring me a taco!

而如果使用 dc(diff-conflict) 命令则只显示冲突区域,而不是对文件的所有修改。而且该命令使用不同的格式来显示冲突区域,允许你更容易地比较冲突区域的差异。

交互式地解决冲突

在获取到冲突区域的详细信息后,就可以着手解决这些冲突,主要有两种方式:

  • 使用编辑器修改冲突区域
  • 直接选择本地修改或仓库修改

延迟解决冲突

当然,也可以使用 p(postone) 来推迟对该文件的冲突解决。如果你根本不想使用交互式方式来解决冲突,可以在使用 svn update 命令时传递 --non-interactive 选项,之后所有的冲突文件都会直接被标记为 C(Conflicted) 状态。

当你延迟解决冲突时,SVN 会做以下三件事,用于协助你解决冲突:

  • update 命令执行过程中,会对冲突文件标记为 C,并始终记住该状态
  • 如果该文件是可合并的,它将在文件中放置冲突标记符,用于可视化地展示冲突区域
  • 对于每个冲突文件,都将创建 3 个额外的未版本化的文件
    • filename.mine:在 update 流程之前本地副本中的该文件,它包含了所有的本地修改
    • filename.rOLDREV:对应于 BASE revision 的该文件,即 update 流程之前该文件的未修改版本,OLDREV 表示 base revision 号
    • filename.rNEWREV:对应于从仓库中获取到的新版本的该文件,NEWREV 对应于该文件的 revision 号(一般为 HEAD)

之后,在这些临时文件被删除之前,该冲突文件都不能被 commit。你需要使用 svn resolve 命令来解决冲突,同时使用 —accept 选项来指定解决冲突的方式,该选项有如下参数:

  • base:选择该文件的 base revision,即不包含任何本地修改
  • mine-full:选择只包含你的修改的文件版本
  • theirs-full:选择从仓库中获取的文件版本,即忽略所有你的修改
  • working:同时选择你的修改以及从 SVN 仓库中获取的修改,此时需要在本地副本的相应文件中手动合并冲突内容

当使用 svn resolve 命令解决冲突后,该文件对应的 3 个临时文件将被删除,该文件也不再处于冲突状态。

手动合并冲突

接下来将展示如何手动合并冲突。对于如下冲突文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cat sandwich.txt
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
Creole Mustard
Bottom piece of bread

<、=、> 都是冲突标记符,并不是真实的冲突内容。在你解决冲突后、准备提交前,需要确保这些标记符从文件中被删除了。以下内容是冲突区域中你所做的修改:

1
2
3
4
5
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======

然后是冲突区域中对应的仓库修改:

1
2
3
4
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2

根据你的实际情况,手动解决冲突内容,然后使用 svn resolve 命令告诉 SVN 冲突已经被解决。注意,使用该命令一定要确保冲突的确已经被解决,执行该命令后,临时文件将被删除。之后就可以对该文件提交成功(即使该文件仍然包含冲突标记符)。

1
2
$ svn resolve --accept working sandwich.txt
Resolved conflicted state of 'sandwich.txt'

使用 svn revert

如果你想放弃你的修改,你可以使用 svn revert 命令将文件恢复成 base revision。即使此时文件已经处于冲突状态,该命令也可以生效,而且执行该命令后冲突也会被解决。

所以当你 revert 一个冲突文件之后,不需要再使用 svn resolve 命令。

提交修改

使用 svn commit 命令向 SVN 仓库提交你的修改。提交修改时,需要添加日志信息,如果日志信息非常简短,可以直接使用 --message(-m) 选项。日志信息也可以保存在文件中,使用 --file(-F) 选项指定文件路径。

1
2
3
4
$ svn commit -m "Corrected number of cheese slices."
Sending sandwich.txt
Transmitting file data .
Committed revision 3.

如果你没有显式地指定日志信息,SVN 将自动启动编辑器让你输入日志。

检查历史

以下几个命令可以让你从 SVN 仓库获取历史数据信息:

  • svn diff:以行级别显示具体的差异
  • svn log:显示每个 revision 对应的日志信息,包括提交日志、日期、作者、修改路径等
  • svn cat:检索指定 revision 下的某文件,并显示文件内容
  • svn annotate:显示指定 revision 下的某文件,同时显示该文件每一行的最近一次修改信息
  • svn list:显示指定 revision 下的某目录内容

获取历史变化的具体信息

svn diff 主要有以下 3 种用途:

  • 检查本地修改
  • 将你的本地副本和仓库进行比较
  • 比较仓库中不同 revision 变化

当不带任何选项运行 svn diff 命令时,将获取本地修改信息,它把当前本地副本中的文件和缓存在 .svn 目录下的原始文件信息进行对比:

1
$ svn diff

如果使用 –revision(-r) 选项指定单个 revision 号,将把本地副本和仓库中的指定 revision 进行比较。

1
$ svn diff -r 3 rules.txt

如果使用 –revision(-r) 选项指定两个 revision 号,中间用 : 隔开,将比较仓库中指定文件的两个版本的差异:

1
$ svn diff -r 2:3 rules.txt

如果要比较仓库中某个文件的某个 revision 和前一个 revision 之间的差异,可以使用 --change(-c) 的差异:

1
$ svn diff -c 3 rules.txt

最后,即使你没有本地副本,你也可以比较仓库中的版本差异,只需要在命令行中指定仓库的 URL:

1
$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt

获取历史变化列表

使用 svn log 命令可以获取文件或目录的历史变化信息。该命令将显示谁修改了该文件/目录、在哪个 revision 发生了修改、修改时间、修改日志。默认日志信息以时间顺序逆序显示。

1
2
3
4
5
6
7
8
9
10
11
$ svn log
------------------------------------------------------------------------
r3 | sally | 2008-05-15 23:09:28 -0500 (Thu, 15 May 2008) | 1 line
Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | 2008-05-14 18:43:15 -0500 (Wed, 14 May 2008) | 1 line
Added main() methods.
------------------------------------------------------------------------
r1 | sally | 2008-05-10 19:50:31 -0500 (Sat, 10 May 2008) | 1 line
Initial import
------------------------------------------------------------------------

可以通过 --revision 选项获取指定 revision 之间或单个 revision 的日志信息:

命令 作用
svn log -r 5:9 按时间顺序显示 revision 5 到 9 之间的日志信息
svn log -r 9:5 按时间顺序逆序显示 revision 5 到 9 之间的日志信息
svn log -r 8 获取 revision 为 8 时的日志信息

使用 --verbose(-v) 选项可以显示修改的文件信息。使用 --diff 选项,还可以同时显示每个 revision 之间的具体差异。

浏览仓库

使用 svn cat 命令可以显示指定 revision 的某文件,可以通过重定向命令将输出重定向到文件中:

1
$ svn cat -r 2 rules.txt > rules.txt.v2

svn annotate 命令类似于 svn cat 命令,也可以显示文件内容,但是该命令使用表格形式进行输出。每一行不仅显示文件内容,同时还显示这一行最近一次修改的用户名、revision 号和时间戳(可选,使用 –verbose 选项)。

在该命令的输出中可能某些行没有属性,这是因为这些行已经在本地副本中被修改了。所以这也是另一种方式来查看本地副本中哪些内容被修改。可以指定 BASE revision,从而忽略本地副本对这些行的修改:

1
2
3
4
5
$ svn annotate rules.txt@BASE
1 harry Be kind to others
3 sally Freedom = Responsibility
1 harry Everything in moderation
1 harry Chew with your mouth open

注意,svn blamesvn praise 等效于 svn annotate。所以使用哪个命令,取决于你看到代码时的心情。

svn list 允许你直接显示 SVN 仓库中某目录的文件列表,而不需要先创建你的本地副本。使用 --verbose(-v) 选项可以获取更详细的信息。

1
2
3
4
5
$ svn list http://svn.example.com/repo/project
README
branches/
tags/
trunk/

通过 svn update 命令的 --revision(-r) 选项来获取指定 revision 的仓库快照。当然你也可以使用 svn checkout 命令的 -r 选项来 checkout 指定 revision 的仓库快照。对于 SVN 新手可能会犯一个错误,不能通过 checkout 一个旧版本,然后再提交该旧版本来回退修改,因为 SVN 不允许你提交过期的文件。

1
2
3
4
5
6
7
# Checkout the trunk from r1729.
$ svn checkout http://svn.example.com/svn/repo/trunk@1729 trunk-1729
...
# Checkout the current trunk as it looked in r1729.
$ svn checkout http://svn.example.com/svn/repo/trunk -r 1729 trunk-1729
...
$

如果你仅仅想要仓库文件的副本,之后不需要通过 SVN 跟踪本地版本的变化,可以使用 svn export 创建本地副本,该命令创建的本地副本中不存在 .svn 管理目录。

1
2
3
4
5
6
7
8
9
10
# Export the trunk from the latest revision.
$ svn export http://svn.example.com/svn/repo/trunk trunk-export
...
# Export the trunk from r1729.
$ svn export http://svn.example.com/svn/repo/trunk@1729 trunk-1729
...
# Export the current trunk as it looked in r1729.
$ svn export http://svn.example.com/svn/repo/trunk -r 1729 trunk-1729
...
$

从中断中恢复

当 SVN 尝试更新你的本地副本时,SVN 会在一个私有的 to-do-list 中记录它将要采取的行动,然后按照该列表逐一完成每个任务,并且对工作副本中的相关部分进行加锁。当所有任务完成后,SVN 清空它的 to-do-list 并释放锁。该流程类似于一个日志型文件系统。

如果 SVN 操作中间被中断,该私有的 to-do-list 仍然存在工作副本中。所以如果执行某些 SVN 操作提示工作副本处于 locked 状态,只需要运行 svn cleanup 命令来纠正错误。svn status 的输出中 L 状态表示文件处于 locked 状态。

1
2
3
4
5
6
$ svn status
L somedir
M somedir/foo.c
$ svn cleanup
$ svn status
M somedir/foo.c

处理文件树冲突

之前介绍的冲突是关于文件内容的冲突,还有一种情况是目录结构出现冲突。对于目录结构冲突,在解决冲突之前 SVN 也不允许你执行提交操作。

例如,如果执行 svn update 命令出现如下结果:

1
2
3
4
5
6
7
8
9
$ svn update
Updating '.':
C code/bar.c
A code/baz.c
U Makefile
Updated to revision 14.
Summary of conflicts:
Tree conflicts: 1
$

在这个例子中,仓库中的 code/bar.c 被其它人重命名为 code/baz.c,因此本地副本更新后出现文件树冲突(Tree conflict)。通过 svn status 命令得知 code/bar.c 本地已经修改,但是仓库中已经删除:

1
2
3
4
5
6
7
$ svn status
M code/foo.c
A + C code/bar.c
> local edit, incoming delete upon update
Summary of conflicts:
Tree conflicts: 1
$

之后我们需要通过一些方法调查文件树的变动过程,该过程可以和他人沟通,也可以通过 SVN 的历史记录获取一些线索。通过 svn info 获取冲突文件的详细信息:

1
2
3
4
5
6
7
8
9
$ svn info code/bar.c
Path: code/bar.c
Name: bar.c
URL: http://svn.example.com/svn/repo/trunk/code/bar.c
...
Tree conflict: local edit, incoming delete upon update
Source left: (file) ^/trunk/code/bar.c@4
Source right: (none) ^/trunk/code/bar.c@5
$

得知到文件树变动过程后,我们就需要着手解决冲突。在这个例子中,如果我们同意变动,并且决定将本地修改移植到新文件 code/baz.c,我们可以这样做:

首先基于旧文件产生 diff 文件:

1
$ svn diff code/bar.c > PATCHFILE

修改 diff 文件中的内容,从而将修改应用到新的文件 code/baz.c

1
2
3
4
5
6
$ cat PATCHFILE
Index: code/baz.c
===================================================================
--- code/baz.c (working copy)
+++ code/baz.c (working copy)
...

将修改后的 diff 文件应用到新文件

1
2
3
$ svn patch PATCHFILE
U code/baz.c
$

之后删除本地中的 code/bar.c 并告诉 SVN 成功已经解决:

1
2
3
4
5
6
7
$ svn delete --force code/bar.c
D code/bar.c
$ svn resolve --accept=working code/bar.c
Resolved conflicted state of 'code/bar.c'
$ svn status
M code/foo.c
M code/baz.c

如果我们不同意重命名,则只需要在本地副本中删除新文件 code/baz.c,而原来的 code/bar.c 已经被 SVN 自动设置为添加状态,不需要再运行 svn add 命令:

1
2
3
4
5
6
7
8
9
$ svn delete --force code/baz.c
D code/baz.c
$ svn resolve --accept=working code/bar.c
Resolved conflicted state of 'code/bar.c'
$ svn status
M code/foo.c
A + code/bar.c
D code/baz.c
M Makefile

以上,一个由于重命名而导致的文件树冲突就被解决了。