SVN 树冲突和目录丢失问题(1)
临下班了,一个老朋友 (之后用yzw代称) 在 MSN 上呼我。说他的 SVN 遇到问题了:
注:在《SVN 树冲突和目录丢失问题(3)》中,我介绍了一个更为直接的重现 yzw 问题的方法。虽然 yzw 还是最有可能用本文的步骤遇到的问题,因为 分支和主线相应的提交都是 yzw 一个人完成的,没有他人参与。
- 在执行分支合并时,一个目录发生了树冲突
- 直接在硬盘上将该目录删除
- 之后执行 svn update 该目录不能检出
- 不知道树冲突为何物,也不知道目录怎么变成了一团糟
$ svn st M . ! + C somedir > local add, incoming add upon update看来他遇到的树冲突,是因为在两个分支同时创建了一个同名目录 somedir,然后在合并更新时出现树冲突。
重现问题的过程
版本库准备
- 创建svn 版本库于 /tmp/svnserver
- 检出版本库到目录 ~/tmp/svntf 下 (windows用户需要知道的是:~ 代表我的主目录 /home/jiangxin 是也)
- 创建 SVN 三个顶级目录:trunk tags branches
- 创建分支 branches/0.x
- 在 branches/0.x 分支下创建目录 somedir,并增加一个文件 somedir/branch.txt
- 在主线 trunk 下也创建一个目录 somedir,并增加一个文件 somedir/trunk.txt
- 主线下执行 svn info
~/tmp/svntf/trunk$ svn info 路径: . URL: file:///tmp/svnserver/trunk 版本库根: file:///tmp/svnserver 版本库 UUID: c0e3cb0f-81b0-40e5-9c35-42972dbc50aa 版本: 4 节点种类: 目录 调度: 正常 最后修改的作者: jiangxin 最后修改的版本: 4 最后修改的时间: 2010-04-22 19:51:55 +0800 (四, 2010-04-22)
- 主线下目录下的文件
~/tmp/svntf/trunk$ svn ls -R somedir/ somedir/trunk.txt
- 主线的更改历史
~/tmp/svntf/trunk$ svn log ------------------------------------------------------------------------ r4 | jiangxin | 2010-04-22 19:51:55 +0800 (四, 2010-04-22) | 1 行 to trunk, we add somedir/trunk.txt file. ------------------------------------------------------------------------ r1 | jiangxin | 2010-04-22 19:48:57 +0800 (四, 2010-04-22) | 1 行 initial ------------------------------------------------------------------------
- 分支的中的文件列表
~/tmp/svntf/trunk$ svn ls -R file:///tmp/svnserver/branches/0.x somedir/ somedir/branch.txt
- 分支的更改历史
~/tmp/svntf/trunk$ svn log file:///tmp/svnserver/branches/0.x ------------------------------------------------------------------------ r3 | jiangxin | 2010-04-22 19:51:21 +0800 (四, 2010-04-22) | 1 行 to branch 0.x, we add somedir/branch.txt file. ------------------------------------------------------------------------ r2 | jiangxin | 2010-04-22 19:50:27 +0800 (四, 2010-04-22) | 1 行 trunk => branch/0.x ------------------------------------------------------------------------ r1 | jiangxin | 2010-04-22 19:48:57 +0800 (四, 2010-04-22) | 1 行 initial ------------------------------------------------------------------------
备份当前的 .svn 目录
直接拷贝 .svn 到 .svn-orignal,以便在出现意外的时候,进行参照。~/tmp/svntf/trunk$ cp -a .svn .svn-orignalTips: 如果不想每次在执行 svn status 时显示 .svn-orignal 目录,设置svn属性 svn:ignore 值为 ".svn*"。(问题优点复杂化了,算了)
合并分支改动,引发异常
- 执行合并操作,引发异常
~/tmp/svntf/trunk$ svn merge file:///tmp/svnserver/branches/0.x --- 正在合并 r2,经由 r4,到 “.”: C somedir 冲突概要: 树冲突:1
- 删除 somedir 目录
~/tmp/svntf/trunk$ rm -rf somedir/
- 执行 svn status 查看当前状态
~/tmp/svntf/trunk$ svn st M . ? .svn-merge-conflict ? .svn-orignal ! C somedir > 本地 增加,动作 增加,操作 合并
- 虽然结果和yzw很像了,但是还不是完全一致。
- yzw 执行 svn status 显示的英文,最后一行翻译为中文是:
> 本地 增加,动作 增加,操作 更新
- 而我的结果是:
> 本地 增加,动作 增加,操作 合并
- 看来,还需要作些工作才能完全重现错误。
- yzw 执行 svn status 显示的英文,最后一行翻译为中文是:
- 这时我又备份了一下 .svn 目录,将 .svn 复制到 .svn-merge-conflict,以便后面比较
- 执行 svn up 命令
~/tmp/svntf/trunk$ svn up 跳过“somedir” D somedir 更新到版本 4。 冲突概要: 跳过的路径:1 ~/tmp/svntf/trunk$ svn up 版本 4。
- 以上执行了两次 svn up ,结果不一致,说明 svn 干了些什么。
实际上,通过比较 .svn 目录和之前备份的 .svn-merge-conflict 可以看出端倪:
~/tmp/svntf/trunk$ diff -r .svn-merge-conflict .svn diff -r .svn-merge-conflict/entries .svn/entries 38,40d37 < somedir < dir <
- 执行 svn 恢复操作,再执行 svn up,发现 somedir 没有了:
~/tmp/svntf/trunk$ svn revert -R . 已恢复“somedir” ~/tmp/svntf/trunk$ svn up 版本 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 <
- 这时如果再执行从分支合并,合并的过程就很有意思了
居然没有发生冲突。yzw 这时后一定很欣喜,居然可以成功合并了。
~/tmp/svntf/trunk$ svn merge file:///tmp/svnserver/branches/0.x --- 正在合并 r2,经由 r4,到 “.”: A somedir A somedir/branch.txt
- 但是慢着,这个合并是假的。不信提交看一看
~/tmp/svntf/trunk$ svn st M . ? .svn-merge-conflict ? .svn-orignal A + somedir A + somedir/branch.txt ~/tmp/svntf/trunk$ svn ci -m "merge from branch 0.x" 正在发送 trunk 增加 trunk/somedir svn: 提交失败(细节如下): svn: 目录 “/trunk/somedir” 已经过时
- 提交过时?很简单,SVN 的经典问题:服务器有更新的版本,更新之
~/tmp/svntf/trunk$ svn up 版本 4。
- 执行 svn update 没有反应?带目录执行 svn update 试试,果然发生冲突了:
~/tmp/svntf/trunk$ svn up somedir C somedir 版本 4。 冲突概要: 树冲突:1
- 查看冲突的状态,是不是和 yzw 的一致了
~/tmp/svntf/trunk$ svn st M . ? .svn-merge-conflict ? .svn-orignal A + C somedir > 本地 增加,动作 增加,操作 更新 A + somedir/branch.txt
- 不太一样?删掉 somedir 先。然后看状态:
~/tmp/svntf/trunk$ rm -rf somedir
再看看状态?~/tmp/svntf/trunk$ svn st M . ? .svn-merge-conflict ? .svn-orignal ! + C somedir > 本地 增加,动作 增加,操作 更新
注:在《SVN 树冲突和目录丢失问题(3)》中,我介绍了一个更为直接的重现 yzw 问题的方法。虽然 yzw 还是最有可能用本文的步骤遇到的问题,因为 分支和主线相应的提交都是 yzw 一个人完成的,没有他人参与。