`
nanjingjiangbiao_T
  • 浏览: 2594024 次
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

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 接合使用,因为毕竟他现在做的是商业软件开发,还需要精细的代码授权(至少是对别人授权)。
分享到:
评论

相关推荐

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

    平时我们说的冲突,是因为对同一文件的不同修改造成的冲突。树冲突,指的是由于目录(文件)树的改变,造成内容修改修改不能匹配在...本文介绍了重现 update 导致树冲突的重现过程,对SVN冲突解决机制进行实例探讨。

    SVN客户端用户使用手册

    SVN客户端用户使用手册 20061115 该文档将逐步教您如何在软件开发过程中使用svn客户端 环境模拟 现有项目名称:test 服务端版本库:test URL:http://10.155.11.10:81/svn 开发人员:devA,devB 版本库目录结构: ...

    开源版本控制SVN管理后台pySvnManager用户使用手册(pysvnmanager user-guide)

    pySvnManager 是群英汇开发的一个Subversion 的管理后台,用 Python 写的一个 Web 应用,用于管理 SVN 授权文件,只需要一个 SVN 授权文件即可工作,并且使用扩展的 SVN 授权文件进行 pySvnManager 本身的授权,而...

    SVN操作手册中文版网页格式

    4.20.3. 合并两个不同的目录树 4.20.4. 合并选项 4.20.5. 预览合并结果 4.20.6. 合并跟踪 4.20.7. 子合并期间处理冲突 4.20.8. Merge a Completed Branch 4.20.9. Feature Branch Maintenance 4.21. 锁 4.21...

    SVN培训教程.pptx

    SVN基本概念 配置库( Repository ) SVN的核心是配置库,储存所有的数据,配置库按照文件树形式储存数据-包括文件和目录,任意数量的客户端可以连接到配置库,读写这些文件。通过写数据,别人可以看到这些信息;...

    subversion-merge-conflict-resolver:Subversion树冲突解决程序

    Subversion树冲突解决程序当开发人员移动/重命名/删除文件或文件夹时,另一个开发人员也已经移动/重命名/删除或修改了文件或文件夹,就会发生树冲突。 有许多不同的情况可能导致树冲突,并且所有这些情况都需要不同...

    TortoiseSVN和TortoiseMerge的中文帮助文档(chm格式)

    4.6.3. 树冲突 4.6.3.1. 本地删除,当更新时有更改进入 4.6.3.2. 本地更改,当更新时有删除进入 4.6.3.3. 本地删除,当更新时有删除进入 4.6.3.4. 本地缺少,当合并时有更改进入 4.6.3.5. 本地更改,当合并时有删除...

    软件操作培训教程.pptx

    3.SVN相关基本概念 配置库( Repository ) SVN的核心是配置库,储存所有的数据,配置库按照文件树形式储存数据-包括文件和目录,任意数量的客户端可以连接到配置库,读写这些文件。通过写数据,别人可以看到这些...

    Git权威指南PDF完整版

    16.5.1 手工操作解决树冲突/ 227 16.5.2 交互式解决树冲突/ 228 16.6 合并策略/ 230 16.7 合并相关的设置/ 231 第17章 Git 里程碑/ 233 17.1 显示里程碑/ 234 17.2 创建里程碑/ 236 17.2.1 轻量级里程碑/ 237 17.2.2...

    subversion-TortoiseSVN-使用手册(CHM+HTML,中英完整版)

    合并两个不同的目录树 5.17.3. 预览合并结果 5.17.4. 忽略祖先 5.18. 锁 5.18.1. 锁定在Subverion中是如何工作的 5.18.2. 取得锁定 5.18.3. 释放锁定 5.18.4. 检查锁定状态 5.18.5. 让非锁定的文件变成只读 5.18.6....

    URULE是一款基于RETE算法的纯Java规则引擎.zip

    通过集成Git、SVN等版本控制系统,支持团队成员间的代码共享、分支管理、合并请求和冲突解决。 可视化设计与原型制作: 对于UI/UX设计,有界面设计工具,如Sketch、Adobe XD,可以帮助设计师快速构建应用程序...

    powerline-shell:一个美丽而有用的shell提示

    显示有关git / svn / hg / fossil分支的一些重要详细信息(请参见下文) 如果最后一个命令以失败代码退出,则更改颜色 如果您太深了目录树,请用省略号缩短显示的路径 显示当前的Python 环境 易于定制和扩展。 ...

    TortoiseSVN中文手册

    3.2.6. 使用 svn+ssh 认证 ........................................... 28 3.2.7. svnserve 基于路径的授权 ...................................... 28 4. 版本库 ................................................

    GIT中文资源

    1 起步 1 1.1 关于版本控制 . . . . . . . . ....1.1.1 本地版本控制系统 ....3.2.3 冲突的合并 . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.3 分支管理 . . . . . . . . . . . . . . . . . . ...

Global site tag (gtag.js) - Google Analytics