习惯Git后再用回SVN是一种什么体验

343 阅读5分钟

最近由于一些特殊原因需要接触到SVN,由于之前用惯了Git,所以在学习SVN的过程中感觉还是蛮痛苦的,总感觉“倒退”了一样,这里也记录下方便后续快速回顾。

1、SVN服务端

SVN有服务端和客户端之分,服务端就是我们的远程代码仓库,客户端就是我们的本地仓库。如果没有搭建SVN服务端的需要,纯粹像我一样只是熟悉SVN的语法,能够提交代码即可,则比较推荐使用 SVNBucket 代码托管平台,只要注册就拥有了自己的SVN服务端,而且免费版有100M,足以让我们测试。

2、SVN客户端

关于SVN客户端的选择可以参考这篇文章,里面介绍了Windows和Mac典型的客户端,比如Windows典型的客户端就是TortoiseSVN(小乌龟), 而Mac典型的有:**CornerStone 和 SmartSVN,**当然如果你熟悉终端命令,也可以使用终端。

另外,Jetbrain全家桶的Subversion也是一个不错的选择,目前我就是终端 + Subversion的搭配(因为我是Mac)

3、创建远程仓库

如果你已经有了仓库,则可以跳过这一步,如果没有,也可以用上面提到的 **SVNBucket 创建一个。

图一

4、SVN项目结构

SVN的项目结构一般有三个目录,分别是 trunkbranchestags,但也不绝对,有时候也只有 trunktags,或者 trunkbranches,视人而定。

网上的说法一般是这样:

  • trunk:主分支,是日常开发进行的地方
  • branches:分支,一些阶段性的release版本,这些版本是可以继续进行开发和维护
  • tags:里程碑的发布版本,一般是只读的

我的理解就是 trunk 相当于我们的develop分支(开发环境测试),branches就是我们的各个功能分支,而tags就是实际线上版本。也不知道理解得是否正确,欢迎大家指正~

5、拉取代码

在Git中,拉取远程代码用的是clone命令,在SVN中,使用的是checkout命令。

# 检出最新代码
$ svn checkout svn://svn.svnbucket.com/low_svn/user_svn/
认证领域: <svn://svn.svnbucket.com:3690> svnbucket
用户名: low_svn
“low_svn”的密码: **********************

A    user_svn/branches
A    user_svn/tags
A    user_svn/trunk
取出版本 1。

# 指定分支/tags
$ svn checkout svn://svn.svnbucket.com/low_svn/user_svn/tags/u_v1/

# 指定版本  -r <版本号>
$ svn co svn://svn.svnbucket.com/low_svn/user_svn -r 4

如果想用Jetbrain检出代码的话,可以点击 VCS —> Subversion —> import into xxx,但目前看只支持http的SVN URL。

图二

如果不想用这种方式的话,也可以先命令行拉取代码,再用Jetbrain打开项目,并 update 一下,建立关联。

图三

6、添加文件

当我们拉完代码后,可以看到本地已经有 trunk、tags、branches三个目录,前面提过,trunk是开发的地方,所以我们先往 trunk 里面加点代码。

本次添加了 file.txt 和 test.php 两份文件,添加完毕后需要通过 add 命令往仓库添加文件。

终端命令:

# 跟git的用法差不多
$ svn add trunk/file.txt
A         trunk/file.txt

Jetbrain操作如下:

图四

7、提交文件

这里需要注意下,SVN的提交(commit)不同于Git,SVN的提交会直接把代码提交到本地仓库,相当于Git的Push命令。(提交文件前必须添加文件,同Git)

终端命令:

$ svn commit -m "第一次提交"
正在增加       trunk/file.txt
正在增加       trunk/test.php
传输文件数据..done
正在读取事务
提交后的版本为 2。

Jetbrain操作如下:

图五

图六

提交完可以在远程仓库查看 图七

8、查看文件状态

查看文件状态用的是 status 命令,同Git。

终端:

$ svn status
?       .idea
A       trunk/file.txt
A       trunk/test.php

9、查看文件历史

查看文件历史使用的是 log 命令,同Git。不过这里SVN有一个和Git比较不同的地方,就是本地Commit后,通过 svn log 是看不到这次commit的,必须 svn update 一下才有,这也是我一开始比较困惑的地方。

# 目前的历史
$ svn log
------------------------------------------------------------------------
r1 | low_svn | 2022-06-28 00:04:50 +0800 (二, 2022-06-28) | 1 行

initial directory structure
------------------------------------------------------------------------

# update一下
$ svn update
正在升级 '.':
版本 2。

# 再查看,有了最新的提交
$ svn log
------------------------------------------------------------------------
r2 | low_svn | 2022-06-28 00:31:21 +0800 (二, 2022-06-28) | 1 行

第一次提交
------------------------------------------------------------------------
r1 | low_svn | 2022-06-28 00:04:50 +0800 (二, 2022-06-28) | 1 行

initial directory structure
------------------------------------------------------------------------

10、查看仓库信息

查看仓库信息使用的是 info 命令,可以看到项目地址,使用版本等信息。

$ svn info
路径: .
工作副本根目录: /Users/xxx/svn_lab/user_svn
URL: svn://svn.svnbucket.com/low_svn/user_svn
Relative URL: ^/
版本库根: svn://svn.svnbucket.com/low_svn/user_svn
版本库 UUID: b2be9e5b-9b86-4342-a794-d2def649e819
版本: 3
节点种类: 目录
调度: 正常
最后修改的作者: low_svn
最后修改的版本: 3
最后修改的时间: 2022-06-28 00:46:57 +0800 (二, 2022-06-28)

11、打Tag

当我们把代码 Commit 上去后,就应该打一个Tag验证了。不同于Git,SVN的打Tag就是一个Copy的操作,完全复制了一份代码,所以它的命令也是Copy。

终端命令:

# 语法;svn cp -m "<说明>"  <源分支>  <目标分支>
# 其实看成 Linux 的 cp 命令也可以
svn cp -m "v1版本" svn://svn.svnbucket.com/low_svn/user_svn/trunk/ svn://svn.svnbucket.com/low_svn/user_svn/tags/u_v1
正在读取事务
提交后的版本为 3。

这里还有一个注意点,copy后,本地是没有 u_v1 这个Tag的,这个Tag存在于远程仓库,所以这个命令相当于帮我们在远程仓库打了一个Tag。

图八

如果要把远程的代码拉下来,则再次执行 svn update 命令

$ svn update
正在升级 '.':
A    tags/u_v1
A    tags/u_v1/file.txt
A    tags/u_v1/test.php
更新到版本 3。

如果是用Jetbrain,操作如下:

图九

图十

12、分支/Tags切换

有时候我们需要切换不同的分支进行开发,亦或是线上需要切换不同的Tag进行更新或者回退,使用的命令是:sw(switch)。

终端:

# 语法
svn sw [URL]

# 我们刚刚打了两个Tag,分别是u_v1 和 u_v2,现在来模拟下两者的切换
# 1、先看看目前的URL (URL个人理解就是文件夹路径)
$ svn info
...
URL: svn://svn.svnbucket.com/low_svn/user_svn

# 2、切到 u_v1  (报错是因为两者的层级不同,如果是u_v1 和 u_v2 切换则没有这个问题)
$ svn sw svn://svn.svnbucket.com/low_svn/user_svn/tags/u_v1/
svn: E195012: 路径“.”与请求的切换位置没有共同的祖先。使用 --ignore-ancestry 可以禁用此检查。
svn: E195012: “svn://svn.svnbucket.com/low_svn/user_svn/tags/u_v1”与“/Users/hongxinxie/PhpstormProjects/svn_lab/user_svn”没有共同的祖先

# 为了测试,可以加 --ignore-ancestry 禁用此检查。
$ svn sw svn://svn.svnbucket.com/low_svn/user_svn/tags/u_v1/ --ignore-ancestry
D    branches
D    tags
D    trunk
A    file.txt
A    test.php
更新到版本 4。

# 查看此时有哪些文件,可以看到被切到 v1 版本了
$ ls
file.txt test.php

# 3、切到 u_v2 (注意这时不用加 --ignore-ancestry,因为两者层级一致)
$ svn sw svn://svn.svnbucket.com/low_svn/user_svn/tags/u_v2/                  
版本 4。

13、项目开发流程

其实这一套整下来,我发现SVN其实就是一个远程的大文件夹,添加提交文件也就是把文件上传到远程而已,而切换分支其实就是切换不同的文件夹而已。

那么在实际操作中,一个项目的开发流程应该是怎样的呢?

对于我而言:

  • 1、首先你应该把代码拉下来,使用checkout命令
  • 2、从稳定版本拉一个分支出来,使用copy命令
  • 3、在该分支进行修改,添加提交文件,使用 add + commit 命令
  • 4、此时将代码合并到trunk进行主干验证(开发环境),验证通过后再从该分支打一个Tag到现网验证

这是我目前的使用方式,不知道大家是不是这样呢,欢迎大家讨论~

14、其他命令

SVN的命令远不止上面这几个,常用的还有merge、revert命令,这里有一篇文章可供参考

SVN常用命令

参考

svn客户端下载

SVN快速上手教程

必看!SVN管理工具 Mac Cornerstone 详细图文教程