SVN MERGE 和冲突

本文介绍如何在Subversion (SVN) 中正确地进行分支(branch)与主干(trunk)间的合并操作,避免冲突,并详细解释了使用svn merge命令的方法及如何使用svn resolve命令解决合并过程中产生的冲突。

摘要:最佳做法是避免冲突。冲突时,不要把branch merge到trunk. 先由最新版本的trunk得到branch,然后再修改文件,直接merge过去就行。这样不会有冲突。先用svn merge --dry-run来模拟假装merge一下看是否有冲突


1 svn merge

# svn merge --help
merge: Apply the differences between two sources to a working copy path.
usage: 1. merge sourceURL1[@N] sourceURL2[@M] [WCPATH]
       2. merge sourceWCPATH1@N sourceWCPATH2@M [WCPATH]
       3. merge [-c M | -r N:M] SOURCE[@REV] [WCPATH]

我们以第一个为例
merge sourceURL1[@N] sourceURL2[@M] [WCPATH]
这个help里面提示,merge需要三个参数
sourceURL1,sourceURL2的含义并不是两个分支,或者一个分支一个主干,而是同一个分支的两个状态,或者说是两个版本。对这两个版本做一个diff,然后把diff的结果,应用到最后的参数WCPATH上,WCPATH代表是一个本地已经checkout的工作区

svn merge的思想是diff and apply

比如,我开发一个项目叫做proj
目录结构是
proj/trunk
proj/branches
proj/tags

(省略了http:// 之后的,只是相对路径,但是真正使用时候不能省略)

当版本达到100的时候,我决定做一个branch进行一些其他开发

 [Reversion:100]
 $svn cp proj/trunk proj/branches/proj_branch_1
 OK Reversion:101

然后,trunk和proj_branch_1都在开发,到了某一个版本,比如150,branch开发完成,需要merge回到trunk
此时的目录结构是
[Reversion:150]
proj/trunk
proj/branches/proj_branch_1
proj/tags

按照svn的实现,我需要知道proj_branch_1所做的所有的变化,也就是当前的状态对刚刚生成时候状态的变化。根据这个变化生成一个diff文件,在apply一个本地的工作区上。(建议是一个干净的本地trunk工作区)

那么执行
$cd proj/trunk
$svn merge proj/branches/proj_branch_1@101 proj/branches/proj_branch_1 .

其实,第一个URL(我们称之为左边),为起始状态,通过最后的@101,表示取版本101,这个101就是cp成功之后的那个版本。第二个URL(我们称之为右边),为最终状态,取最新的,
 左边和右边做了一个diff,应用到当前工作区目录,也就是trunk。
 此时
 $svn st就可以看到变化了

这里的一个问题是如何获取这个cp之后的版本,也就是例子中的101
可以使用svn log里面的--stop-on-copy命令
$svn log --stop-on-copy proj/branches/proj_branch_1
会到cp的时候停下来,那里边标注的版本就是需要的版本

 比如,这是一个真正项目的一个例子,
 ------------------------------------------------------------------------
 r995 | yinweiming | 2007-10-24 09:07:08 +0800 (三, 24 10月 2007) | 1 line

 Create a branch for proj client using
 ------------------------------------------------------------------------
 其中的r995,995就是我需要的版本
 (说明一下,commit时候写commet的好处,比如这里我就很明确的肯定这是branch的起始点)

对于svn merge的另外的用法也是类似,只要是明白了
他是根据左边,右边生成diff,然后应用到本地的一个工作区就容易理解了。

还有可以使用svn merge --dry-run来模拟假装merge一下,看一下merge会发生什么,而不是真正的做这个动作。


而对于merge的help里面的 3. merge [-c M | -r N:M] SOURCE[@REV] [WCPATH]
这个也很容易理解,就是取 SOURCE 这个东西,版本N,M之间的区别,作用在WCPATH这个本地工作区上

注意!
做branch千万别根据本地修改过的工作区做,一定基于某一个URL的版本做
我就吃过这个亏
diff的时候,diff不出来,因为基于本地工作区的,所以现在merge起来很是费劲


转自:http://www.blogjava.net/lingy/archive/2009/06/02/279544.html


2 svn resolve 解决冲突

svn resolve --accept  ARG  file 

 --accept ARG             : specify automatic conflict resolution source
                            ('base', 'working', 'mine-conflict',
                             'theirs-conflict', 'mine-full', 'theirs-full')


Resolve “conflicted” state on working copy files or directories. This routine does not semantically resolve conflict markers, however, it replaces PATH with the version specified by the --accept argument and then removes conflict-related artifact files. This allows PATH to be committed again—that is, it tells Subversion that the conflicts have been “resolved.”. You can pass the following arguments to the --accept command depending on your desired resolution:

base

Choose the file that was the BASE revision before you updated your working copy. That is, the file that you checked out before you made your latest edits.

working

Assuming that you've manually handled the conflict resolution, choose the version of the file as it currently stands in your working copy.

mine-full

Resolve all conflicted files with copies of the files as they stood immediately before you ran svn update.

theirs-full

Resolve all conflicted files with copies of the files that were fetched from the server when you ran svn update.



例子:

工程师A修改了a.txt的第一行,提交了。

工程师B也修改了a.txt的第一行,然后执行svn up,这时SVN提示了:(以下,你开始扮演工程师B的角色了)
$ svn up
在 “a.txt” 中发现冲突。
选择: (p) 推迟,(df) 显示全部差异,(e) 编辑,
(mc) 我的版本, (tc) 他人的版本,
(s) 显示全部选项:

我一般选择p(推迟),即引入冲突到本地,不过不会影响到SVN服务器端,可以放心。

OK,开始解决冲突了。

这时,会生成几个文件:

a.txt 

 a.txt.mine  a.txt.r6328  a.txt.r6336

其中a.txt中包含了工程师A、B的所有修改,以<<<<<<<、=======、>>>>>>>分隔。

a.txt.mine是工程师B的修改,也就是未update前的a.txt。

a.txt.r6328 是工程师A提交前的版本,即未导致冲突的版本。

a.txt.r6336是工程师A提交后的版本,即导致冲突的版本。

一般,查看a.txt就可以看到冲突的详情了:

[yicheng@chengyi svntest]$ cat a.txt

<<<<<<< .mine

i also modify ,agndagnagasdg;

=======

i modify this line;

>>>>>>> .r6336

以上,<<<<<<< .mine和=======之间是工程师B(当前的“你”)修改的内容,=======与>>>>>>> .r6336之间是工程师A修改的内容。这时,最好的办法是,叫上工程师A,你们一起确定这些修改是否都需要,是否相互兼容,然后留下需要的部分,删 除<<<<<<< .mine、=======和>>>>>>> .r6336。

然后,测试,测试!确定没问题之后,就可以告诉SVN,你解决冲突了:

svn resolve –accept working a.txt (该命令会删除a.txt.mine  a.txt.r6328  a.txt.r6336)

svn ci -m ’some comment’ a.txt

<think>我们正在讨论SVN的合并(merge)功能以及如何解决合并冲突。根据用户的问题,用户希望了解如何使用svnmerge命令以及如何解决合并时出现的冲突。首先,参考引用内容:-引用[1]提供了svnmerge命令的基本用法,说明了三种使用方式。我们重点关注第一种形式:`svnmergesourceURL1[@N]sourceURL2[@M][WCPATH]`。这表示将两个源URL之间的差异应用到工作副本路径(WCPATH)上。这里的NM可以是版本号。-引用[2]提到在提交时如果遇到文件过期(outofdate)的错误,需要先更新(update)。-引用[3][4]则介绍了如何使用TortoiseSVN工具解决冲突以及如何提交解决冲突后的文件。因此,我们可以将回答分为两部分:1.使用svnmerge命令进行合并的基本步骤。2.解决合并过程中可能出现的冲突。###第一部分:使用svnmerge合并假设我们有两个分支:主干(trunk)分支(branch)。现在需要将分支上的修改合并到主干上。步骤:1.切换到主干的工作副本目录。```bashcdtrunk_working_copy```2.更新主干到最新版本,以避免冲突(引用[2]提到过时的错误)。```bashsvnupdate```3.执行合并命令。例如,将分支从版本100到200的修改合并到当前主干工作副本。```bashsvnmerge-r100:200http://svn.example.com/svn/branch```或者,如果知道具体的两个版本之间的差异,也可以使用两个URL的形式(如引用[1]中的第一种用法):```bashsvnmergehttp://svn.example.com/svn/branch@100http://svn.example.com/svn/branch@200.```这里的`.`表示当前目录(工作副本)。4.合并后,检查是否有冲突。如果没有冲突,可以直接提交。###第二部分:解决合并冲突如果在合并过程中发生冲突SVN会标记这些文件为冲突状态。解决冲突的步骤:1.**识别冲突**:SVN会提示哪些文件有冲突冲突的文件在工作副本中会显示为带有感叹号(在TortoiseSVN图标中)或者使用`svnstatus`命令可以看到状态为'C'。2.**解决冲突**:-**手动解决**:打开冲突文件,你会看到类似这样的内容:```<<<<<<<.mine这是你的修改=======这是来自合并源的修改>>>>>>>.r200```你需要编辑文件,保留需要的部分,并删除这些标记。-**使用工具**:如引用[3]所述,可以使用TortoiseSVN的“Editconflicts”工具来图形化解决冲突。-**选择版本**:如果你决定使用某一方的版本,可以使用命令:-使用自己的版本(本地修改):```bashsvnresolve--acceptmine-full文件名```-使用传入的版本(合并源的版本):```bashsvnresolve--accepttheirs-full文件名```3.**标记为已解决**:解决冲突后,需要告诉SVN冲突已经解决。```bashsvnresolve文件名```或者使用TortoiseSVN的“Resolved”菜单项。4.**提交**:解决所有冲突后,就可以提交合并的结果(如引用[4]所示)。```bashsvncommit-m"合并分支,解决冲突"```###注意事项-在合并前更新工作副本可以避免一些不必要的冲突。-合并后,最好先构建测试代码,确保合并没有引入问题,然后再提交。-使用svnmerge时,如果合并的范围很大,可以考虑分多次小范围合并,以降低冲突的复杂性。###相关问题根据以上内容,生成以下相关问题:1.如何撤销一次未提交的svn合并操作?2.如何避免在svn合并时产生冲突?3.什么是svn合并的“追踪合并信息”(mergetracking)?它如何帮助合并?4.除了命令行,如何使用TortoiseSVN图形化工具进行合并?请用户根据实际需要选择相关问题进一步了解。</think>### 如何使用 SVN 合并功能及解决冲突 #### 一、SVN 合并基本用法 SVN 合并的核心命令为 `svn merge`,其语法格式如下: ```bash svn merge SOURCE[@REV] [TARGET_WCPATH] ``` - **SOURCE**:源分支或版本的 URL/路径 - **@REV**:指定版本号(可选) - **TARGET_WCPATH**:目标工作副本路径(默认为当前目录) ##### 常用场景示例: 1. **合并分支到主干**(将分支 `branch` 的修改合并到 `trunk`): ```bash cd trunk_working_copy svn merge ^/branches/mybranch ``` - `^/` 表示仓库根目录的相对路径[^1] 2. **合并特定版本范围**: ```bash svn merge -r 150:200 ^/branches/mybranch ``` - 合并分支从版本 150 到 200 的修改 3. **合并单个修订版本**: ```bash svn merge -c 305 ^/trunk ``` - `-c` 表示合并特定修订版(此处为 r305) --- #### 二、解决合并冲突的步骤 当合并导致文件冲突时,按以下流程处理: ##### 1. **识别冲突文件** 执行合并后,冲突文件会标记为 `C`: ```bash $ svn status C test.txt ``` ##### 2. **手动解决冲突** - 打开冲突文件,会看到冲突标记: ```plaintext <<<<<<< .mine # 你的本地修改 本地内容 ======= 合并来源内容 >>>>>>> .r102 # 来源版本号 ``` - 编辑文件,保留需要的代码段并删除标记 ##### 3. **标记为已解决** ```bash svn resolve --accept=working test.txt # 使用当前修改 # 或选择其他策略: # --accept=mine-full 保留本地全部内容 # --accept=theirs-full 保留合并来源内容 ``` ##### 4. **提交结果** ```bash svn commit -m "解决合并冲突" ``` --- #### 三、图形化工具解决冲突(TortoiseSVN) 1. 右键点击冲突文件 → **Edit Conflicts** 2. 使用三窗格对比工具修改文件 3. 点击 **Mark as resolved** 4. 提交更改[^3][^4] --- #### 四、常见错误与处理 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | `svn: File is out of date` | 工作副本未更新 | 先执行 `svn update`[^2] | | 树冲突(Tree conflict) | 文件/目录被移动或删除 | 使用 `svn resolve --accept working PATH` | | 合并后编译失败 | 逻辑冲突未解决 | 手动检查代码兼容性 | > ⚠️ **重要提示**:合并前务必更新工作副本(`svn update`),可减少 70% 的冲突概率[^2]。 --- ### 相关问题 1. 如何撤销已执行但未提交的 SVN 合并操作? 2. SVN 的 `--reintegrate` 参数在合并中起什么作用? 3. 如何避免分支合并时出现树冲突(Tree Conflict)? 4. SVN 与 Git 的合并机制有哪些核心差异? [^1]: svn merge 命令的三种标准用法格式 [^2]: 提交失败时的典型错误提示及更新要求 [^3]: TortoiseSVN 图形化冲突解决流程 [^4]: 冲突解决后的标准提交操作示例
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值