本文档旨在描述 Apache™ Subversion® 的 1.7.x 系列。如果您运行的是其他版本的 Subversion,强烈建议您访问 https://svnbooks.subversion.org.cn/ 并查阅适合您 Subversion 版本的文档。

基本工作周期

Subversion 拥有众多功能、选项、铃铛和哨声,但在日常工作中,您可能只会使用其中的一部分。在本节中,我们将介绍您在一天的工作中可能需要使用 Subversion 执行的最常见操作。

典型的工作周期如下所示

  1. 更新您的工作副本。 这涉及使用 svn update 命令。

  2. 进行您的更改。 您最常进行的更改是对现有文件内容的编辑。但有时您需要添加、删除、复制和移动文件和目录——svn addsvn deletesvn copysvn move 命令处理工作副本中的这些结构性更改。

  3. 查看您的更改。 svn statussvn diff 命令对于查看您在工作副本中所做的更改至关重要。

  4. 修复您的错误。 没有人是完美的,因此在查看您的更改时,您可能会发现一些不正确的地方。有时,修复错误的最简单方法是从头开始。svn revert 命令将文件或目录恢复到其未修改状态。

  5. 解决任何冲突(合并他人的更改)。 在您进行和查看更改的时间里,其他人也可能已经进行了更改并发布了更改。您需要将他们的更改集成到您的工作副本中,以避免在尝试发布您自己的更改时出现潜在的过时情况。同样,svn update 命令是执行此操作的方法。如果这导致本地冲突,您需要使用 svn resolve 命令来解决这些冲突。

  6. 发布(提交)您的更改。 svn commit 命令将您的更改传输到存储库,如果它们被接受,它们将创建您修改的所有内容的最新版本。现在其他人也可以看到您的工作了!

更新您的工作副本

当您在一个通过多个工作副本进行修改的项目上工作时,您需要更新您的工作副本以接收自上次更新以来其他工作副本提交的任何更改。这些可能是项目团队其他成员所做的更改,也可能是您自己从另一台计算机上所做的更改。为了保护您的数据,Subversion 不会允许您将新更改提交到过时的文件和目录,因此最好在进行自己的新更改之前拥有项目所有文件和目录的最新版本。

使用 svn update 将您的工作副本与存储库中的最新修订版同步

$ svn update
Updating '.':
U    foo.c
U    bar.c
Updated to revision 2.
$

在这种情况下,似乎有人在您上次更新后将修改检入 foo.cbar.c,Subversion 已更新您的工作副本以包含这些更改。

当服务器通过 svn update 将更改发送到您的工作副本时,每个项目旁边都会显示一个字母代码,以让您知道 Subversion 执行了哪些操作来使您的工作副本更新。要了解这些字母的含义,请运行 svn help update 或参见 svn update (up)第 9 章,Subversion 完整参考 中。

进行您的更改

现在您可以开始工作并在您的工作副本中进行更改。您可以对您的工作副本进行两种更改:文件更改树更改。您无需告诉 Subversion 您打算更改文件;只需使用您的文本编辑器、文字处理器、图形程序或您通常使用的任何工具进行更改即可。Subversion 会自动检测哪些文件已更改,此外,它可以像处理文本文件一样轻松地处理二进制文件——而且效率也一样高。树更改不同,它涉及对目录结构的更改。此类更改包括添加和删除文件、重命名文件或目录以及将文件或目录复制到新位置。对于树更改,您使用 Subversion 操作来 计划 文件和目录以供删除、添加、复制或移动。这些更改可能立即发生在您的工作副本中,但直到您提交它们,存储库中才会发生任何添加或删除。

以下是您最常使用以进行树更改的五个 Subversion 子命令的概述

svn add FOO

使用此命令将文件、目录或符号链接 FOO 计划添加到仓库中。下次提交时,FOO 将成为其父目录的子项。请注意,如果 FOO 是一个目录,则 FOO 下的所有内容都将被计划添加。如果您只想添加 FOO 本身,请传递 --depth=empty 选项。

svn delete FOO

使用此命令将文件、目录或符号链接 FOO 计划从仓库中删除。如果 FOO 是一个文件或链接,它将立即从您的工作副本中删除。如果 FOO 是一个目录,它不会被删除,但 Subversion 会将其计划删除。当您提交更改时,FOO 将完全从您的工作副本和仓库中删除。[6]

svn copy FOO BAR

创建一个名为 BAR 的新项目,作为 FOO 的副本,并自动安排 BAR 进行添加。当 BAR 在下次提交时添加到仓库时,它的复制历史记录将被记录(最初来自 FOO)。svn copy 不会创建中间目录,除非您传递 --parents 选项。

svn move FOO BAR

此命令与运行 svn copy FOO BAR; svn delete FOO 完全相同。也就是说,BAR 被安排为 FOO 的副本进行添加,而 FOO 被安排为删除。svn move 不会创建中间目录,除非您传递 --parents 选项。

svn mkdir FOO

此命令与运行 mkdir FOO; svn add FOO 完全相同。也就是说,创建一个名为 FOO 的新目录,并安排其进行添加。

查看您的更改

完成更改后,您需要将它们提交到仓库,但在这样做之前,通常最好查看一下您到底更改了什么。通过在提交之前检查您的更改,您可以编写更准确的 日志消息(与这些更改一起存储在仓库中的更改的人类可读描述)。您也可能会发现您无意中更改了一个文件,并且需要在提交之前撤消该更改。此外,这是一个在发布更改之前审查和仔细检查更改的好机会。您可以使用 svn status 命令查看所做更改的概述,并可以使用 svn diff 命令深入了解这些更改的详细信息。

查看更改概述

要查看更改概述,请使用svn status命令。您可能比任何其他 Subversion 命令都更频繁地使用svn status

[Tip] 提示

由于cvs status命令的输出非常嘈杂,并且由于cvs update不仅执行更新,还报告本地更改的状态,因此大多数 CVS 用户习惯使用cvs update来报告他们的更改。在 Subversion 中,更新和状态报告功能是完全独立的。有关更多详细信息,请参阅名为“状态和更新之间的区别”的部分

如果您在工作副本的顶部运行svn status,并且没有其他参数,它将检测并报告您所做的所有文件和树更改。

$ svn status
?       scratch.c
A       stuff/loot
A       stuff/loot/new.c
D       stuff/old.c
M       bar.c
$

在默认输出模式下,svn status 打印七列字符,然后是几个空格字符,然后是文件或目录名称。第一列显示文件或目录及其内容的状态。svn status 显示的一些最常见的代码是

? item

文件、目录或符号链接item 不在版本控制之下。

A item

文件、目录或符号链接 item 已被安排添加到仓库中。

C item

文件 item 处于冲突状态。也就是说,在更新过程中从服务器接收到的更改与您工作副本中的本地更改(在更新期间未解决)重叠。您必须在将更改提交到仓库之前解决此冲突。

D item

文件、目录或符号链接 item 已被安排从仓库中删除。

M item

文件 item 的内容已修改。

如果您将特定路径传递给 svn status,您将获得有关该项目本身的信息

$ svn status stuff/fish.c
D       stuff/fish.c

svn status 还有一个 --verbose (-v) 选项,它将显示您工作副本中 每个 项目的状态,即使它没有被更改

$ svn status -v
M               44        23    sally     README
                44        30    sally     INSTALL
M               44        20    harry     bar.c
                44        18    ira       stuff
                44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
                44        21    sally     stuff/things
A                0         ?     ?        stuff/things/bloo.h
                44        36    harry     stuff/things/gloo.c

这是 svn status长格式 输出。第一列中的字母与之前相同,但第二列显示项目的当前修订版本。第三列和第四列显示项目最后更改的修订版本以及更改者。

之前对 svn status 的调用都不会联系仓库 - 它们只是根据存储在工作副本管理区域中的记录以及修改文件的 timestamps 和内容来报告有关工作副本项目的信息。但有时查看工作副本中的哪些项目自上次更新工作副本以来在仓库中被修改是有用的。为此,svn status 提供了 --show-updates (-u) 选项,它会联系仓库并添加有关过时项目的的信息

$ svn status -u -v
M      *        44        23    sally     README
M               44        20    harry     bar.c
       *        44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
A                0         ?     ?        stuff/things/bloo.h
Status against revision:   46

请注意前面的示例中的两个星号:如果您要在此处运行 svn update,您将收到对 READMEtrout.c 的更改。这告诉您一些非常有用的信息 - 因为其中一个项目也是您本地修改的项目(文件 README),您需要更新并获取该文件的服务器更改,然后才能提交,否则仓库将拒绝您的提交,因为它已经过时。我们将在后面更详细地讨论这一点。

svn status 可以显示关于工作副本中文件和目录的更多信息,比我们这里展示的要多得多。要详细了解 svn status 及其输出,请运行 svn help status 或查看 svn status (stat, st)第 9 章,Subversion 完整参考 中。

检查本地修改的详细信息

另一种检查更改的方法是使用 svn diff 命令,该命令显示文件内容的差异。当您在工作副本的顶层运行 svn diff 而不带任何参数时,Subversion 将打印您对工作副本中人类可读文件所做的更改。它以 统一 diff 格式显示这些更改,这种格式将更改描述为文件内容的 (或 片段),其中每行文本都以一个单字符代码为前缀:空格,表示该行未更改;减号 (-),表示该行已从文件中删除;或加号 (+),表示该行已添加到文件中。在 svn diff 的上下文中,这些以减号和加号为前缀的行分别显示了这些行在您修改之前和之后的样子。

以下是一个示例

$ svn diff
Index: bar.c
===================================================================
--- bar.c	(revision 3)
+++ bar.c	(working copy)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>

 int main(void) {
-  printf("Sixty-four slices of American Cheese...\n");
+  printf("Sixty-five slices of American Cheese...\n");
 return 0;
 }

Index: README
===================================================================
--- README	(revision 3)
+++ README	(working copy)
@@ -193,3 +193,4 @@
+Note to self:  pick up laundry.

Index: stuff/fish.c
===================================================================
--- stuff/fish.c	(revision 1)
+++ stuff/fish.c	(working copy)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.

Index: stuff/things/bloo.h
===================================================================
--- stuff/things/bloo.h	(revision 8)
+++ stuff/things/bloo.h	(working copy)
+Here is a new file to describe
+things about bloo.

svn diff 命令通过将您的工作文件与它的原始文本库进行比较来生成此输出。计划添加的文件将显示为所有行都已添加的文件;计划删除的文件将显示为所有行都已从这些文件中删除的文件。来自 svn diff 的输出与 patch 程序有一定的兼容性——与 Subversion 1.7 中引入的 svn patch 子命令的兼容性更高。这些补丁处理命令读取并应用 补丁文件(或 补丁),这些文件描述了对一个或多个文件所做的更改。因此,您可以通过从 svn diff 的重定向输出创建补丁文件,将您在工作副本中所做的更改与其他人共享,而无需先提交这些更改。

$ svn diff > patchfile
$

默认情况下,Subversion 使用其内部 diff 引擎,该引擎生成统一 diff 格式。如果您想要以其他格式输出 diff,请使用 --diff-cmd 指定外部 diff 程序,并通过 --extensions (-x) 选项传递其所需的任何其他标志。例如,您可能希望 Subversion 将其差异计算和显示推迟到 GNU diff 程序,并要求该程序以上下文 diff 格式(另一种差异格式)打印对文件 foo.c 所做的本地修改,同时忽略仅对文件内容中使用的字母的大小写所做的更改。

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

修复您的错误

假设在查看 svn diff 的输出时,您确定对特定文件所做的所有更改都是错误的。也许您根本不应该更改该文件,或者也许从头开始进行不同的更改会更容易。您可以再次编辑该文件并撤消所有这些更改。您可以尝试找到该文件在您更改之前的样子,然后将其内容复制到您的修改版本之上。您可以尝试使用 patch -R 反向将这些更改应用于该文件。当然,您可能还会采取其他方法。

幸运的是,在 Subversion 中,撤消您的工作并从头开始并不需要如此复杂的技巧。只需使用 svn revert 命令即可

$ svn status README
M       README
$ svn revert README
Reverted 'README'
$ svn status README
$

在此示例中,Subversion 通过用文本库区域中缓存的原始文件版本覆盖该文件,将其恢复到修改前的状态。但请注意,svn revert 可以撤消 任何 计划的操作——例如,您可能决定最终不想添加新文件

$ 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 status README
$ svn delete README
D         README
$ svn revert README
Reverted 'README'
$ svn status README
$

对于不完美的人来说,svn revert 命令提供了救赎。它可以为您节省大量时间和精力,否则这些时间和精力将花费在手动撤消更改或更糟糕的是,丢弃您的工作副本并签出新的工作副本,以便再次获得干净的工作环境。

解决任何冲突

我们已经了解了 svn status -u 如何预测冲突,但处理这些冲突仍然需要解决。 任何时候,当你尝试将来自仓库的更改合并或集成(从非常通用的意义上讲)到你的工作副本中时,都可能发生冲突。 现在你已经知道 svn update 会创建这种场景——该命令的真正目的是通过将你上次更新后所做的所有更改合并到你的工作副本中,使你的工作副本与仓库保持同步。 那么 Subversion 如何向你报告这些冲突,以及你如何处理它们呢?

假设你运行 svn update 并看到这种有趣的输出

$ 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)代码无需担心;这些文件干净地吸收了来自仓库的更改。 用 U 标记的文件不包含本地更改,但已使用来自仓库的更改进行了更新。 用 G 标记的文件最初包含本地更改,但来自仓库的更改与这些本地更改没有重叠。

接下来的几行很有趣。 首先,Subversion 向你报告,在尝试将未决的服务器更改合并到文件 bar.c 中时,它检测到其中一些更改与你在工作副本中对该文件所做的本地修改冲突,但尚未提交。 也许有人更改了你所更改的同一行文本。 无论原因是什么,Subversion 会立即将该文件标记为处于冲突状态。 然后它会询问你希望如何处理这个问题,允许你交互式地选择采取的解决冲突的行动。 最常用的选项会显示出来,但你可以通过键入 s 来查看所有选项。

…
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: s

  (e)  edit             - change merged file in an editor
  (df) diff-full        - show all changes made to merged file
  (r)  resolved         - accept merged version of file

  (dc) display-conflict - show all conflicts (ignoring merged version)
  (mc) mine-conflict    - accept my version for all conflicts (same)
  (tc) theirs-conflict  - accept their version for all conflicts (same)

  (mf) mine-full        - accept my version of entire file (even non-conflicts)
  (tf) theirs-full      - accept their version of entire file (same)

  (p)  postpone         - mark the conflict to be resolved later
  (l)  launch           - launch external tool to resolve conflict
  (s)  show all         - show this list

Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options:

在我们详细介绍每个选项的含义之前,让我们简要回顾一下每个选项。

(e) edit

在环境变量 EDITOR 中设置的你最喜欢的编辑器中打开冲突的文件。

(df) diff-full

以统一 diff 格式显示基础版本和冲突文件本身之间的差异。

(r) resolved

在编辑文件后,告诉 svn 您已解决文件中的冲突,并且它应该接受当前内容——基本上是您已 解决 冲突。

(dc) display-conflict

显示文件的所有冲突区域,忽略已成功合并的更改。

(mc) mine-conflict

丢弃来自服务器的任何新接收的更改,这些更改与您对正在审查的文件的本地更改冲突。但是,接受并合并来自服务器的该文件的任何非冲突更改。

(tc) theirs-conflict

丢弃任何与来自服务器的传入更改冲突的本地更改,这些更改适用于正在审查的文件。但是,保留对该文件的所有非冲突本地更改。

(mf) mine-full

丢弃来自服务器的正在审查文件的任何新接收的更改,但保留对该文件的所有本地更改。

(tf) theirs-full

丢弃对正在审查文件的任何本地更改,并且仅使用来自服务器的该文件的新接收的更改。

(p) postpone

将文件保留在冲突状态,以便您在更新完成后解决。

(l) launch

启动外部程序以执行冲突解决。这需要事先进行一些准备。

(s) show all

显示您可以在交互式冲突解决中使用的所有可能命令的列表。

我们现在将更详细地介绍这些命令,并将它们按相关功能分组在一起。

交互式查看冲突差异

在决定如何交互式地解决冲突之前,您很可能希望查看确切的冲突内容。在交互式冲突解决提示符下可用的两个命令可以帮助您。第一个是 diff-full 命令 (df),它显示对所讨论文件的任何本地修改以及任何冲突区域

…
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 版本),下一行内容是您的更改,最后一行内容是刚刚从服务器接收到的更改(通常HEAD 版本)。

第二个命令类似于第一个命令,但 display-conflict (dc) 命令仅显示冲突区域,而不是对文件进行的所有更改。此外,此命令对冲突区域使用略微不同的显示格式,使您能够更轻松地比较文件内容在这些区域中的显示方式,就像它们在三种状态中的显示方式一样:原始且未编辑;应用了您的本地更改并忽略了服务器的冲突更改;以及仅应用了服务器的传入更改并还原了您的本地冲突更改。

在查看了这些命令提供的信息后,您就可以继续执行下一步操作。

交互式解决冲突差异

有几种不同的方法可以交互式地解决冲突,其中两种方法允许您选择性地合并和编辑更改,其余方法允许您简单地选择文件的一个版本并继续。

如果您希望选择本地更改的某些组合,可以使用 edit 命令 (e) 在文本编辑器中手动编辑带有冲突标记的文件(根据 “使用外部编辑器”部分 中的说明进行配置)。编辑完文件后,如果您对所做的更改感到满意,可以使用 resolved 命令 (r) 告诉 Subversion 编辑后的文件不再冲突。

无论您的本地 Unix 极客可能会告诉您什么,在您喜欢的文本编辑器中手动编辑文件是一种比较低技术的方法来解决冲突(请参阅 “手动合并冲突”部分 以获取逐步操作)。为此,Subversion 提供了 launch 解决命令 (l) 来启动一个花哨的图形合并工具(请参阅 “外部合并”部分)。

如果您决定不需要合并任何更改,而只想接受文件的一个版本或另一个版本,您可以选择您的更改(也称为 mine)使用 mine-full 命令 (mf) 或选择他们的更改使用 theirs-full 命令 (tf)。

最后,还提供了一对折衷方案。 mine-conflict (mc) 和 theirs-conflict (tc) 命令分别指示 Subversion 选择您的本地更改或服务器的传入更改作为所有冲突的 获胜者。 但是,与 mine-fulltheirs-full 命令不同,这些命令在未检测到冲突的文件区域保留您的本地更改和从服务器接收的更改。

推迟冲突解决

这听起来可能像是避免婚姻纠纷的合适部分,但实际上它仍然与 Subversion 有关,所以请继续阅读。 如果您正在执行更新并遇到您没有准备审查或解决的冲突,您可以在运行 svn update 时键入 p 以推迟逐文件解决冲突。 如果您事先知道您不想以交互方式解决任何冲突,您可以将 --non-interactive 选项传递给 svn update,并且任何冲突文件将自动标记为 C

C(代表 冲突)表示服务器的更改与您自己的更改重叠,现在您必须在更新完成后手动选择它们。

  • Subversion 在更新期间打印一个 C 并记住该文件处于冲突状态。

  • 如果 Subversion 认为该文件是可合并的,它会在文件中放置 冲突标记——特殊文本字符串,用于分隔冲突的 两侧——以直观地显示重叠区域。(Subversion 使用 svn:mime-type 属性来决定文件是否能够进行基于上下文的行级合并。请参阅 名为“文件内容类型”的部分 以了解更多信息。)

  • 对于每个冲突文件,Subversion 会在您的工作副本中放置三个额外的未版本化文件。

    filename.mine

    这是您在开始更新过程之前工作副本中存在的该文件。它包含您在该点之前对该文件所做的所有本地修改。(如果 Subversion 认为该文件不可合并,则不会创建 .mine 文件,因为它将与工作文件相同。)

    filename.rOLDREV

    这是该文件在 BASE 修订版中存在的样子,即您在开始更新过程之前工作副本中该文件的未修改版本,其中 OLDREV 是该基本修订版号。

    filename.rNEWREV

    这是您的 Subversion 客户端刚刚通过更新您的工作副本从服务器接收到的文件,其中 NEWREV 对应于您正在更新到的修订版号(HEAD,除非另有要求)。

例如,Sally 对文件 sandwich.txt 进行了更改,但尚未提交这些更改。与此同时,Harry 提交了对同一文件的更改。Sally 在提交之前更新了她的工作副本,并且遇到了冲突,她将其推迟了。

$ svn update
Updating '.':
Conflict discovered in 'sandwich.txt'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: p
C    sandwich.txt
Updated to revision 2.
Summary of conflicts:
  Text conflicts: 1
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2

此时,Subversion 将允许 Sally 提交文件 sandwich.txt,直到删除三个临时文件。

$ svn commit -m "Add a few more things"
svn: E155015: Commit failed (details follow):
svn: E155015: Aborting commit: '/home/sally/svn-work/sandwich.txt' remains in conflict

如果您推迟了冲突,则需要在 Subversion 允许您提交更改之前解决冲突。您将使用 svn resolve 命令和 --accept 选项的几个参数之一来执行此操作。

如果您想选择您上次检出文件之前进行编辑的版本,请选择 base 参数。

如果您想选择仅包含您编辑的版本,请选择 mine-full 参数。

如果您想选择您最近更新从服务器拉取的版本(从而完全丢弃您的编辑),请选择 theirs-full 参数。

但是,如果您想从您的更改和从服务器获取的更新中选择和选择更改,请合并有冲突的文本手动(通过检查和编辑文件中的冲突标记),然后选择工作参数。

svn resolve 删除三个临时文件并接受您使用 --accept 选项指定的版本的文件,Subversion 不再认为该文件处于冲突状态

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

手动合并冲突

手动合并冲突在您第一次尝试时可能非常令人生畏,但只要稍微练习一下,它就会变得像骑自行车一样容易。

以下是一个示例。由于沟通不畅,您和您的合作者 Sally 同时编辑了文件 sandwich.txt。Sally 提交了她的更改,当您更新您的工作副本时,您遇到了冲突,您将不得不编辑 sandwich.txt 来解决冲突。首先,让我们看一下文件

$ 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

小于号、等号和大于号的字符串是冲突标记,不是冲突的实际数据的一部分。您通常希望确保在下次提交之前从文件中删除这些标记。第一个和第二个标记集之间的文本包含您在冲突区域中所做的更改

<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======

第二个和第三个冲突标记集之间的文本是 Sally 提交的文本

=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2

通常您不会只想删除冲突标记和 Sally 的更改——当三明治到达时,它不是她想要的,她会非常惊讶。这就是您拿起电话或走到办公室,向 Sally 解释您无法从意大利熟食店买到酸菜的地方。[7] 一旦您就将要提交的更改达成一致,请编辑您的文件并删除冲突标记

Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
Salami
Mortadella
Prosciutto
Creole Mustard
Bottom piece of bread

现在使用 svn resolve,您就可以提交您的更改了

$ svn resolve --accept working sandwich.txt
Resolved conflicted state of 'sandwich.txt'
$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."

请注意,svn resolve 与本章中我们处理的大多数其他命令不同,它要求您明确列出您希望解决的任何文件名。无论如何,您都要小心,只在您确定已修复文件中的冲突时才使用 svn resolve——一旦临时文件被删除,Subversion 就会让您提交文件,即使它仍然包含冲突标记。

如果您在编辑有冲突的文件时感到困惑,您始终可以参考 Subversion 为您在工作副本中创建的三个文件——包括您更新之前的文件。您甚至可以使用第三方交互式合并工具来检查这三个文件。

放弃您的更改,转而使用新获取的修订版

如果您遇到冲突并决定放弃您的更改,您可以运行 svn resolve --accept theirs-full CONFLICTED-PATH,Subversion 将丢弃您的编辑并删除临时文件。

$ svn update
Updating '.':
Conflict discovered in 'sandwich.txt'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: p
C    sandwich.txt
Updated to revision 2.
Summary of conflicts:
  Text conflicts: 1
$ ls sandwich.*
sandwich.txt  sandwich.txt.mine  sandwich.txt.r2  sandwich.txt.r1
$ svn resolve --accept theirs-full sandwich.txt
Resolved conflicted state of 'sandwich.txt'
$

放弃:使用 svn revert

如果您决定放弃您的更改并重新开始编辑(无论是在冲突之后还是在任何时候),只需还原您的更改。

$ svn revert sandwich.txt
Reverted 'sandwich.txt'
$ ls sandwich.*
sandwich.txt
$

请注意,当您还原冲突文件时,您无需使用 svn resolve

提交您的更改

最后!您的编辑已完成,您已合并了来自服务器的所有更改,并且您已准备好将您的更改提交到存储库。

The svn commit 命令将您的所有更改发送到存储库。当您提交更改时,您需要提供一个日志消息来描述您的更改。您的日志消息将附加到您创建的新修订版。如果您的日志消息简短,您可能希望在命令行上使用 --message (-m) 选项提供它。

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

但是,如果您在工作时在其他文本文件中编写了日志消息,您可能希望告诉 Subversion 从该文件获取消息,方法是将文件名作为 --file (-F) 选项的值传递。

$ svn commit -F logmsg
Sending        sandwich.txt
Transmitting file data .
Committed revision 4.

如果您未指定 --message (-m) 或 --file (-F) 选项,Subversion 将自动启动您最喜欢的编辑器(请参阅 名为“Config”的部分 中关于 editor-cmd 的信息)以编写日志消息。

[Tip] 提示

如果您在编辑器中编写提交消息并决定取消提交,您可以直接退出编辑器而不保存更改。如果您已经保存了提交消息,只需删除所有文本,再次保存,然后中止。

$ svn commit
Waiting for Emacs...Done

Log message unchanged or not specified
(a)bort, (c)ontinue, (e)dit
a
$

存储库不知道也不关心您的更改作为一个整体是否有意义;它只检查在您没有注意的情况下,是否有人更改了与您相同的任何文件。如果有人 已经这样做了,整个提交将失败,并显示一条消息,通知您一个或多个文件已过期。

$ svn commit -m "Add another rule"
Sending        rules.txt
svn: E155011: Commit failed (details follow):
svn: E155011: File '/home/sally/svn-work/sandwich.txt' is out of date
…

(此错误消息的具体措辞取决于您使用的网络协议和服务器,但基本原理在所有情况下都相同。)

此时,您需要运行 svn update,处理任何由此产生的合并或冲突,然后再次尝试提交。

这涵盖了使用 Subversion 的基本工作流程。Subversion 提供了许多其他功能,您可以使用它们来管理您的存储库和工作副本,但您日常使用 Subversion 的大部分时间都将只涉及我们在本章中讨论过的命令。但是,我们将介绍一些您将经常使用的其他命令。



[6] 当然,永远不会真正从存储库中完全删除任何内容——只是从其 HEAD 版本中删除。您仍然可以访问先前版本中的已删除项目。如果您希望恢复该项目,使其再次出现在 HEAD 中,请参阅 名为“恢复已删除项目”的部分

[7] 如果您要求他们这样做,他们很可能会把你赶出城镇。

TortoiseSVN 官方中文版 1.14.7 发布