`
nowing
  • 浏览: 84688 次
  • 来自: ...
社区版块
存档分类
最新评论

(转)svn树冲突

阅读更多
SVN 树冲突和目录丢失问题(1)
临下班了,一个老朋友 (之后用yzw代称) 在 MSN 上呼我。说他的 SVN 遇到问题了:

·             在执行分支合并时,一个目录发生了树冲突

·             直接在硬盘上将该目录删除

·             之后执行 svn update 该目录不能检出

·             不知道树冲突为何物,也不知道目录怎么变成了一团糟

好吧,谁让他公司的 SVN 是我给部署的呢?让他(yzw)执行 svn status 命令,看看显示什么信息,然后我在本地建立一个模型,争取重现并解决他的问题。

在已经一团糟的目录下,执行 svn 显示的信息如下:

$ svn st

M      .

!  +  C somedir

      >   local add, incoming add upon update

看来他遇到的树冲突,是因为在两个分支同时创建了一个同名目录 somedir,然后在合并更新时出现树冲突。

重现问题的过程
版本库准备
1.           创建svn 版本库于 /tmp/svnserver

2.           检出版本库到目录 ~/tmp/svntf 下 (windows用户需要知道的是:~ 代表我的主目录 /home/jiangxin 是也)

3.           创建 SVN 三个顶级目录:trunk tags branches

4.           创建分支 branches/0.x

5.           在 branches/0.x 分支下创建目录 somedir,并增加一个文件 somedir/branch.txt

6.           在主线 trunk 下也创建一个目录 somedir,并增加一个文件 somedir/trunk.txt

看看目前的版本情况

1.           主线下执行 svn info

2.                ~/tmp/svntf/trunk$ svn info

3.                路径: .

4.                URL: file:///tmp/svnserver/trunk

5.                版本库根: file:///tmp/svnserver

6.                版本库 UUID: c0e3cb0f-81b0-40e5-9c35-42972dbc50aa

7.                版本: 4

8.                节点种类: 目录

9.                调度: 正常

10.            最后修改的作者: jiangxin

11.            最后修改的版本: 4

最后修改的时间: 2010-04-22 19:51:55 +0800 (四, 2010-04-22)

12.        主线下目录下的文件

13.            ~/tmp/svntf/trunk$ svn ls -R

14.            somedir/

somedir/trunk.txt

15.        主线的更改历史

16.            ~/tmp/svntf/trunk$ svn log

17.            ------------------------------------------------------------------------

18.            r4 | jiangxin | 2010-04-22 19:51:55 +0800 (四, 2010-04-22) | 1 行

19.            

20.            to trunk, we add somedir/trunk.txt file.

21.            ------------------------------------------------------------------------

22.            r1 | jiangxin | 2010-04-22 19:48:57 +0800 (四, 2010-04-22) | 1 行

23.            

24.            initial

------------------------------------------------------------------------

25.        分支的中的文件列表

26.            ~/tmp/svntf/trunk$ svn ls -R file:///tmp/svnserver/branches/0.x

27.            somedir/

somedir/branch.txt

28.        分支的更改历史

29.            ~/tmp/svntf/trunk$ svn log file:///tmp/svnserver/branches/0.x

30.            ------------------------------------------------------------------------

31.            r3 | jiangxin | 2010-04-22 19:51:21 +0800 (四, 2010-04-22) | 1 行

32.            

33.            to branch 0.x, we add somedir/branch.txt file.

34.            ------------------------------------------------------------------------

35.            r2 | jiangxin | 2010-04-22 19:50:27 +0800 (四, 2010-04-22) | 1 行

36.            

37.            trunk => branch/0.x

38.            ------------------------------------------------------------------------

39.            r1 | jiangxin | 2010-04-22 19:48:57 +0800 (四, 2010-04-22) | 1 行

40.            

41.            initial

------------------------------------------------------------------------

备份当前的 .svn 目录
直接拷贝 .svn 到 .svn-orignal,以便在出现意外的时候,进行参照。

~/tmp/svntf/trunk$ cp -a .svn .svn-orignal

Tips: 如果不想每次在执行 svn status 时显示 .svn-orignal 目录,设置svn属性 svn:ignore 值为 “.svn*”。(问题优点复杂化了,算了)

合并分支改动,引发异常
1.           执行合并操作,引发异常

2.                ~/tmp/svntf/trunk$ svn merge file:///tmp/svnserver/branches/0.x

3.                --- 正在合并 r2,经由 r4,到 “.”:

4.                   C somedir

5.                冲突概要:

  树冲突:1

6.           删除 somedir 目录

~/tmp/svntf/trunk$ rm -rf somedir/

7.           执行 svn status 查看当前状态

8.                ~/tmp/svntf/trunk$ svn st

9.                 M      .

10.            ?       .svn-merge-conflict

11.            ?       .svn-orignal

12.            !     C somedir

13.                  >   本地 增加,动作 增加,操作 合并

14.        虽然结果和yzw很像了,但是还不是完全一致。

o                yzw 执行 svn status 显示的英文,最后一行翻译为中文是:

      >   本地 增加,动作 增加,操作 更新

o                而我的结果是:

      >   本地 增加,动作 增加,操作 合并

o                看来,还需要作些工作才能完全重现错误。

15.        这时我又备份了一下 .svn 目录,将 .svn 复制到 .svn-merge-conflict,以便后面比较

16.        执行 svn up 命令

17.            ~/tmp/svntf/trunk$ svn up

18.            跳过“somedir”

19.            D    somedir

20.            更新到版本 4。

21.            冲突概要:

22.              跳过的路径:1

23.            ~/tmp/svntf/trunk$ svn up

版本 4。

24.        以上执行了两次 svn up ,结果不一致,说明 svn 干了些什么。
实际上,通过比较 .svn 目录和之前备份的 .svn-merge-conflict 可以看出端倪:

25.            ~/tmp/svntf/trunk$ diff -r .svn-merge-conflict .svn

26.            diff -r .svn-merge-conflict/entries .svn/entries

27.            38,40d37

28.            < somedir

29.            < dir

<

30.        执行 svn 恢复操作,再执行 svn up,发现 somedir 没有了:

31.            ~/tmp/svntf/trunk$ svn revert -R .

32.            已恢复“somedir”

33.            ~/tmp/svntf/trunk$ svn up

34.            版本 4。

执行 svn status,看到本地工作目录的冲突状态已经消失了,一切看起来正常了。

~/tmp/svntf/trunk$ svn st

?       .svn-merge-conflict

?       .svn-orignal

但是,慢着,此时 somedir 目录没有了!

~/tmp/svntf/trunk$ ls

实际上,这时版本库中还有 somedir 目录,我们可以用 svn ls 命令查看:

~/tmp/svntf/trunk$ svn ls -R

somedir/

somedir/trunk.txt

但是本地的确已经没有了。如果要刨根问底的话,可以比较一下 .svn 目录和我们之前创建的备份:

~/tmp/svntf/trunk$ diff -r .svn-orignal .svn

diff -r .svn-orignal/entries .svn/entries

38,40d37

< somedir

< dir

<

35.        这时如果再执行从分支合并,合并的过程就很有意思了
居然没有发生冲突。yzw 这时后一定很欣喜,居然可以成功合并了。

36.            ~/tmp/svntf/trunk$ svn merge file:///tmp/svnserver/branches/0.x

37.            --- 正在合并 r2,经由 r4,到 “.”:

38.            A    somedir

A    somedir/branch.txt

39.        但是慢着,这个合并是假的。不信提交看一看

40.            ~/tmp/svntf/trunk$ svn st

41.             M      .

42.            ?       .svn-merge-conflict

43.            ?       .svn-orignal

44.            A  +    somedir

45.            A  +    somedir/branch.txt

46.            ~/tmp/svntf/trunk$ svn ci -m "merge from branch 0.x"

47.            正在发送       trunk

48.            增加           trunk/somedir

49.            svn: 提交失败(细节如下):

svn: 目录 “/trunk/somedir” 已经过时

50.        提交过时?很简单,SVN 的经典问题:服务器有更新的版本,更新之

51.            ~/tmp/svntf/trunk$ svn up

版本 4。

52.        执行 svn update 没有反应?带目录执行 svn update 试试,果然发生冲突了:

53.            ~/tmp/svntf/trunk$ svn up somedir

54.             C somedir

55.            版本 4。

56.            冲突概要:

树冲突:1

57.        查看冲突的状态,是不是和 yzw 的一致了

58.            ~/tmp/svntf/trunk$ svn st

59.             M      .

60.            ?       .svn-merge-conflict

61.            ?       .svn-orignal

62.            A  +  C somedir

63.                  >   本地 增加,动作 增加,操作 更新

A  +    somedir/branch.txt

64.        不太一样?删掉 somedir 先。然后看状态:

~/tmp/svntf/trunk$ rm -rf somedir

再看看状态?

~/tmp/svntf/trunk$ svn st

M      .

?       .svn-merge-conflict

?       .svn-orignal

!  +  C somedir

       >   本地 增加,动作 增加,操作 更新

SVN 树冲突和目录丢失问题(2)
前面的博文《SVN 树冲突和目录丢失问题(1)》,介绍了重现 update 导致树冲突的重现过程。那么应该如何解决树冲突,以及如何找回丢失目录呢?首先我们需要了解:

什么是树冲突?
首先关于树冲突的概念,最好的参考是:SVN BOOK的有关树冲突的章节。

·             平时我们说的冲突,是因为对同一文件的不同修改造成的冲突。

·             树冲突,指的是由于目录(文件)树的改变,造成内容修改修改不能匹配在同一对象(目录/文件)上

·             例如:由于在一个分支中修改的目录和文件,在另外的分支出现了改名的操作。

·             或者像 yzw 的例子,因为两个分支同时增加了一个同名的目录,导致了树冲突。

树冲突的解决,首先要说的是要最好使用 svn 1.6 的客户端。因为 svn 1.5 的客户端对树冲突的处理不好,甚至根本发现不了树冲突,很容易忽略潜在的冲突,出现意想不到的结果。

SVN BOOK 中举了一个本地修改,远程重命名的例子。

例如 svn 1.5 处理这种本地修改/远程文件改名的情况,可能会出现如下结果:

·             发现远程改名,则检查本地文件是否包含修改,若不包含修改直接删除。

·             结果因为远程改名的文件,本地包含修改,因此不删除,而是保留该文件,但是文件的状态变为未受版本控制状态。

·             本地会显示一个新增文件,实际上是本地修改文件的原始(修改前)版本重命名后的文件。

·             这时,如果不太细心(谁那有那么细心?),就会丢失本地的改动。

对于 svn 1.5 最困难的是发现冲突,当然解决冲突也要靠手工比较完成:将本地文件改动在重命名后文件中再次改动一次!

对于 svn1.6 来说,引入了树冲突的概念,看似复杂度增加了,实际上是解决了两个问题:

·             识别冲突的问题:
将本地修改的文件标记为树冲突

·             改动合并的问题:
将本地修改合并到远程改名后的文件中。因为远程改名后的文件来自于本地修改的原始文件

当然对于远程重命名的例子,还要你最终的决定权还是在于你自己:

·             是否接受远程的文件重命名操作?

·             你需要手动将树冲突的状态予以解决:本地文件删除即接受远程重命名;

·             或者将远程添加的文件删除即不允许重命名。

·             对于前一种状况(即接受远程重命名),本地改动 SVN 1. 6的客户端已经自动合并到远程改名后的文件中了。

那么对于 yzw 的情况呢?

本地和远程同时添加目录?

yzw 遇到的树冲突,是因为本地和远程同时添加了相同的目录。实际上,我们在上一个博客中已经看到了两种不同的解决方案影子:

·             本地添加 somedir 目录并提交后,执行合并,显示:“合并引发的树冲突”

o                这时,如果执行 svn resolve –accept working somedir 命令解决冲突的话,

o                就相当于说:“采用我增加的 somedir 目录,他增加的 somedir 目录不算数”

o                然后提交即可

·             树冲突发生后:

o                还原冲突

o                删除主线中的目录。潜台词是:我本地的修改不要了,而是使用远程(分支)添加的目录

o                然后再执行从分支到主线的合并操作

o                合并成功,提交。

o                也就是说,采用的策略是:“采用他增加的 somedir 目录,我增加的 somedir 目录不算数”

看看实际操作的例子:

接受我的修改,远程的修改不算数
·             合并引发树冲突状态

·                    ~/tmp/svntf/trunk$ svn st

·                     M      .

·                    ?       .svn-merge-conflict

·                    ?       .svn-update-conflict

·                    ?       .svn-orignal

·                          C somedir

·                          >   本地 增加,动作 增加,操作 合并

·             使用 svn resolve –accept working 解决冲突:
~/tmp/svntf/trunk$ svn resolve –accept working somedir
“somedir”的冲突状态已解决
~/tmp/svntf/trunk$ svn st
M .
? .svn-merge-conflict
? .svn-update-conflict
? .svn-orignal

·             显示的目录的属性有改变,是因为增加了一个 svn:merge-info 属性

·                    ~/tmp/svntf/trunk$ svn pl -v .

·                    “.” 上的属性:

·                      svn:mergeinfo

·                        /branches/0.x:2-4

·             提交合并的结果

·                    ~/tmp/svntf/trunk$ svn ci -m "忽略分支 0.x 的改动,我的增加是对的。"

·                    正在发送       trunk

·                    

·                    提交后的版本为 5。

·                    ~/tmp/svntf/trunk$ svn st

·                    ?       .svn-merge-conflict

·                    ?       .svn-update-conflict

·                    ?       .svn-orignal

·                    ~/tmp/svntf/trunk$ svn pl -v .

·                    “.” 上的属性:

·                      svn:mergeinfo

    /branches/0.x:2-4

接受远程的修改,我的修改不算数
上一个博文中,我几经尝试,进入到了由于更新引发的树冲突。但是在上一个博客示例最后的更新引发树冲突的状态,虽然也可以用 svn resolve 命令解决树冲突,但是无法提交。

总是报错

~/tmp/svntf/trunk$ svn st

M      .

A  +  C somedir

      >   本地 增加,动作 增加,操作 更新

A  +    somedir/branch.txt

~/tmp/svntf/trunk$ ls somedir

branch.txt

~/tmp/svntf/trunk$ svn resolve --accept working somedir

“somedir”的冲突状态已解决

~/tmp/svntf/trunk$ svn st

M      .

A  +    somedir

A  +    somedir/branch.txt

~/tmp/svntf/trunk$ svn ci -m "删除我的增加的目录,分支 0.x 的增加是对的。"

增加           somedir

svn: 提交失败(细节如下):

svn: 目录 “/trunk/somedir” 已经过时

无论你如何执行 svn update,解决过时错误,也仍然不能提交。会陷入一个无穷无尽的冲突解决==>过时冲突的循环中。

一个撤销本地修改,接受远程分支修订的解决的办法是:

1.           还原

2.                ~/tmp/svntf/trunk$ svn revert -R .

3.                已恢复“.”

4.                已恢复“somedir”

5.                ~/tmp/svntf/trunk$ svn up

6.                版本 4。

7.                ~/tmp/svntf/trunk$ svn st

?       somedir

8.           找回在 .svn/entries 中已经丢弃的 somedir我使用 svn up –set-depth infinity 但是并不能更新出来。如果先执行 –set-depth 为其他,在执行 –set-depth infinity 倒是能够找回 somedir。但是这个方法太过奇怪,好像是 SVN 的一个 BUG,通过奇怪的操作绕过去了一样。我用下面的命令找回丢失的 somedir 目录:

9.                ~/tmp/svntf/trunk$ rm -rf somedir/

10.            ~/tmp/svntf/trunk$ svn up

11.            版本 4。

12.            ~/tmp/svntf/trunk$ svn up somedir

13.            A    somedir

A    somedir/trunk.txt

14.        用 svn 命令删除 somedir目录,并提交

15.            ~/tmp/svntf/trunk$ svn rm somedir/

16.            D         somedir/trunk.txt

17.            D         somedir

18.            

19.            ~/tmp/svntf/trunk$ svn ci -m "丢弃我的改动"

20.            删除           trunk/somedir

21.            

提交后的版本为 5。

22.        然后将分支 0.x 合并到主线,因为本地目录已经不在,合并不会出现冲突了

23.            ~/tmp/svntf/trunk$ svn merge file:///tmp/svnserver/branches/0.x

24.            --- 正在合并 r2,经由 r5,到 “.”:

25.            A    somedir

26.            A    somedir/branch.txt

27.            ~/tmp/svntf/trunk$ svn st

28.             M      .

29.            A  +    somedir

30.            A  +    somedir/branch.txt

31.            ~/tmp/svntf/trunk$ svn ci -m "删除我的增加的目录,分支 0.x 的增加是对的。"

32.            正在发送       trunk

33.            svn: 提交失败(细节如下):

34.            svn: 目录 “/trunk” 已经过时

35.            ~/tmp/svntf/trunk$ svn up

36.            版本 5。

37.            ~/tmp/svntf/trunk$ svn ci -m "删除我的增加的目录,分支 0.x 的增加是对的。"

38.            正在发送       trunk

39.            增加           trunk/somedir

40.            增加           trunk/somedir/branch.txt

41.            

42.            提交后的版本为 6。

中间出现了一次过时问题,是因为目录属性修改,而目录的版本号尚未更新。这其实是 svn 混杂版本号造成的,已经超出本博文的内容。

总结
好了,通过这个例子,我介绍了增加同名目录引发的树冲突的解决方案。

·             如何保留本地修改,取消远程修改

·             如何取消本地修改,保留远程修改

·             怎样的操作,会使 svn 进入一个无法解决的冲突合并状态,以及如何解决

·             发现了一个 SVN 本地目录丢失无法通过  svn update 找回的问题,以及两种解决方法:

o                一个很古怪:分别使用不同的 –set-depth 值执行多次 update,不过最终会成功

o                另外一个却需要知道丢失的目录名称,如果不知道本地有哪个目录缺失,就很难操作了

老杨是我见过的最牛的程序员,但是他的 CVS 的死忠和对 SVN 的憎恨让我觉得异常诧异。可能他和Linus Torvalds 很想像,但又有不同,因为 Linus 对 CVS 和 SVN 同样憎恨。

我估计老杨一旦有时间,一旦掌握了 Git,他就会把 CVS (还有SVN?)扔到九霄云外。不过我估计他还得需要 SVN 和 GIT 接合使用,因为毕竟他现在做的是商业软件开发,还需要精细的代码授权(至少是对别人授权)。
分享到:
评论
1 楼 keke8614 2011-09-15  
废话真多,无语了

相关推荐

    开源版本控制SVN 树冲突、目录丢失问题及解决机制探讨

    **版本控制系统SVN详解与树冲突、目录丢失问题解析** 版本控制系统Subversion(简称SVN)是一种用于管理软件源代码的工具,它允许开发者在不同的时间点保存项目的状态,以便于回溯、合并和协作。当多人同时编辑同一...

    svn版本之间的合并问题

    本文将深入探讨SVN版本之间的合并问题,特别是“树冲突”这一常见但棘手的现象,并提供有效的解决方案。 #### 一、SVN合并机制简介 SVN的合并操作主要涉及到两个或多个版本间的差异比较和整合。当一个文件或目录在...

    SVN日常使用指南

    - **树冲突**:当一人移动、重命名或删除文件/文件夹时,而另一人也进行了类似操作,可能会导致树冲突。 - 解决方案:通常需要手动解决,确保两边的操作不冲突。 以上是对SVN日常使用指南中的关键知识点的详细总结...

    vs2012 安装SVN插件

    它提供了与Visual Studio IDE的无缝集成,使开发者能够在IDE内直接进行版本控制操作,如提交、更新、查看差异和解决冲突等。AnkhSVN的安装文件通常以`.msi`扩展名提供,就像提供的"vs2012 安装SVN插件.msi"一样。 *...

    SVN 使用教程,手把手教你使用SVN

    - **版本库**:这是 SVN 存储所有文件和目录的地方,以文件树的形式组织。 - **修订号**:每次提交都会增加一个修订号,表示版本库在某次提交后的特定状态。 - **锁定**:类似于 VSS 中的 check out,锁定文件以防止...

    svn merge简单操作

    通常情况下,SVN会提示冲突的位置,你需要手动解决冲突后再次提交。 2. **正确使用Merge功能**:确保始终在目标位置使用Merge功能,而不是在源位置。例如,如果你想将分支合并到主干,则应该在主干目录下使用Merge...

    SVN管理员使用指南

    SVN的核心优势在于,它不仅能够处理单一文件的版本控制,还能高效地管理整个项目目录树的版本变化。这种能力使得团队成员可以在各自的环境中对同一组数据进行修改和管理,极大地促进了团队协作和开发效率的提升。 *...

    SVN学习知识.pdf

    1. 目录版本控制:不同于CVS只能追踪单个文件的历史,SVN可以追踪整个目录树的修改。在SVN中,文件和目录都是版本控制的对象,可以对其进行移动和复制操作。 2. 原子提交:SVN的提交操作是原子性的,即要么完全成功...

    svn用户手册 svn常见操作

    - **版本冲突处理**:如果在更新过程中遇到版本冲突,需要手动解决冲突后再提交。 - **分支与合并**:SVN支持分支管理和合并功能,这对于大型项目或需要维护多个版本的情况非常有帮助。 - **权限管理**:通过配置SVN...

    SVN用户使用手册

    5. 版本库结构:在SVN中,版本库(repository)是文件和目录树及其版本历史的存储地点。所有版本库中的数据都是通过特定的URL进行访问的。 6. 分支管理:分支是源代码的一个副本,允许开发者在不影响主版本线...

    eclipse里配置svn

    - 在左侧导航树中,展开“Team”,然后点击“SVN”。 - 点击右上角的“添加”按钮,创建一个新的SVN连接配置。 - 输入SVN服务器的URL,通常是http://或https://开头,然后填写用户名和密码。 - 确认连接信息无误...

    VS的SVN插件最新版

    SVN的核心理念是版本化整个目录树,包括文件和目录,确保了项目的完整性和一致性。 **二、AnkhSVN特性** 1. **无缝集成**:AnkhSVN将SVN命令集直接集成到VS菜单、工具栏和右键上下文菜单中,用户可以直接在VS界面内...

    myeclipse加svn插件

    3. **配置SVN连接**:在MyEclipse中,点击"Window" -&gt; "Preferences",在左侧树形菜单中选择"Team" -&gt; "SVN"。点击右下角的"Add..."按钮,然后在弹出的窗口中填写 SVN 仓库的URL,以及用户名和密码,完成添加。 4. ...

    myeclipse使用的SVN插件

    该插件提供了一种直观的图形用户界面,使得用户可以直接在IDE内部执行常见的SVN操作,如检出、提交、更新、解决冲突等。这极大地减少了开发者在版本控制上的学习成本和操作复杂性。 在提供的压缩包文件列表中,我们...

    myeclipse安装svn插件

    重启后,进入"MyEclipse" -&gt; "Window" -&gt; "Preferences",在左侧树形结构中找到"Team" -&gt; "SVN",点击"SVN Interface",选择已安装的SVN接口,通常推荐使用JNA库。 5. **添加SVN仓库** 接下来,需要配置SVN的连接...

    SVN用户使用详细指南

    除了以上介绍的基本操作外,SVN还支持更复杂的高级功能,如冲突解决、忽略文件设置等。 - **冲突解决**:当两个用户同时修改了同一个文件的不同部分时,SVN会自动合并这些更改。如果同时修改了相同的部分,则会发生...

    比较ClearCase, SVN, GIT

    ClearCase和SVN的版本树是线性的,而GIT的版本树是有向无环图(Directed Acyclic Graph,DAG)。GIT的版本树可以更好地展示版本之间的关系,并且可以自动合并冲突。 合并 ClearCase和SVN的合并需要手动进行,而GIT...

    svn安装包.rar

    3. **版本树**:在SVN中,文件和目录的变更以增量方式存储,形成一个版本树。每个版本都是前一版本的增量,这样可以节省存储空间并提高效率。 4. **工作副本**:用户从服务器获取的本地拷贝称为工作副本,可以在...

    myeclipse集成SVN本地配置

    打开“Window”菜单,选择“Preferences”,在左侧树形菜单中找到“Team” -&gt; “SVN”。 2. 在右侧,点击“SVN Connector”选项卡,确保已正确安装并选择了合适的Connector版本(通常是JavaHL或SVNKit)。 3. 点击...

    svn1.8插件

    3. **改进的树冲突检测**:对于复杂的文件和目录操作,SVN 1.8提供了更精确的树冲突检测机制,帮助用户更好地解决冲突问题。 4. **更大的更改块**:在提交时,可以更大规模地组合更改,减少了网络传输的数据量,...

Global site tag (gtag.js) - Google Analytics