20180108工作日志
svn服务器搭建
Linux下搭建svn服务器
- Mac自带svn
- CentOS需要安装
1. svn相关知识
如果只是使用svn不必深入了解,但是要搭建svn服务器并作为管理员,需要对svn有比较深入的了解。
1.1 svn是什么?
Subversion是一个集中式的信息共享系统,版本库是Subversion的核心部分,是数据的中央仓库,版本库以典型的文件和目录结构形式文件系统树来保存信息。
实际上,Subversion的确是一种文件服务器,但和一般文件服务器不同的地方在于,它会记录每一次的改变,每个文件的改变,甚至是目录树的改变。
版本控制系统的核心问题: 设计用来记录和跟踪数据变化的系统。
1.2 Subversion如何解决文件共享的问题
方案1: “锁定-修改-解锁”方案
一个时间段里某个文件只允许一个人修改,缺点是限制太多,经常会成为用户的障碍。
方案2: "拷贝-修改-合并"方案
每个客户端联系项目版本库建立一个个人工作副本 -- 版本库中文件和目录的本地映射,
用户并行工作,修改自己的工作副本,最终,各个私有的拷贝合并在一起,成为最终的版
本。
Subversion绝大多数情况下采用方案2,通常情况下,你的工作副本的每个文件夹都有一个以.svn为名的文件夹,它是工作副本的管理目录,用以帮助识别哪些文件做过修改,哪些文件相对别人已经过期。
示例1
同一个文件A,Hally和Sally都建立了自己的副本,Sally首先保存修改到版本库,Hally想去提交修改
过期
如果版本库提示A已经过期,换句话说,A在Hally上一次更新之后已经更改了,所以 当H请求合并版本库时,如果Sally的修改和他的不冲突,则可以将工作拷贝到版本库。
冲突
如果Sally和Hally的修改重叠了,这种情况就叫做冲突。一般可以看到一对冲突的修改集, 手工选择保留一组修改即可。
1.3 版本库是什么?
Subversion版本库是保存任意数量项目版本化数据的中央仓库,通过典型的文件浏览器应用程序或命令行为基础的文件系统浏览工具看,Subversion版本库只是另一个目录,也有一些子目录包含可读或不可读的数据文件,这些文件详细作用如下
$ ls
conf/ dav/ db/ format hooks/ locks/ README.txt
conf 一个存储版本库配置文件的目录
dav 提供给Apache和mod_dav_svn的目录,让它们存储自己的数据
db 你的版本化数据的数据存储方式
format 包含了一个用来表示版本库布局版本号整数的文件
hooks 一个存储钩子脚本模板的目录(还有钩子脚本本身)
locks 一个存储Subversion版本库锁定文件的目录,被用来追踪版本库的访问
README.txt 略
当通过Subversion库访问时,这些文件和目录变成虚拟文件系统的实现,由自定义的事件触发完成,它和真实的文件系统区别在于它在修订版本间锁定目录和文件。
Subversion使用URL来识别Subversion版本库中的版本化资源。
svn checkout http://svn.example.com:9834/repos
1.4 版本库格式
SVN服务器版本库有两种格式,一种是FSFS,一种是BDB,把文件上传到SVN版本库后,上传的文件不再以原来的格式存储,而是被svn以它自定义的格式压缩成版本库数据,存放在版本库中。
如果是FSFS格式,这些数据存放在版本库的db目录中,里面的revs和revprops分别存放着每次提交的差异数据和日志等信息。
1.5 版本库结构
一个典型的Subversion版本库经常包含许多项目的文件,通常每一个项目都是版本库的子目录
举例:
你的版本库包含两个软件项目,paint和calc,每个项目在它们各自的顶级子目录下。为了得到一个工作副本,你必须checkout出版本库的一个子树(checkout可以得到一个项目的私有拷贝),要得到calc,可以执行以下命令
svn checkout http://svn.example.com/repos/calc
提交
将你的修改提交到版本库,可以使用Subversion的commit命令
svn commit button.c -m "Fixed a typo in button.c"
更新
要更新本地的工作副本,可以使用svn update命令。
svn commit操作可以作为一个原子事务,发布任意数量文件和目录的修改,原子事务的意思是:要么所有的改变都发生,要么都不发生
每当版本库接受了一个提交,文件系统进入了一个新的状态,叫做一次修订(revision)
Subversion的修订号是针对整个目录树的,而不是单个文件,每个修订号代表了一次提交后版本库整个目录树的特定状态。
本地副本的四种状态
未修改且是当前的
本地工作副本未做修改,svn服务器上版本库也未修改,此时svn commit/svn update均不做任何事情
本地已修改且是当前的
本地工作副本修改但没有提交,服务器上版本库未做修改,svn commit会成功,svn update不做任何事情
本地未修改,已过时
本地工作副本未修改,服务器上版本库已经有更改,svn commit将不做任何事,svn update将会更新本地副本
本地已修改,已过时
本地工作副本已经修改,服务器上版本库也已经更改,svn commit将会失败,这个文件必须首先更新,svn update命令会合并公共和本地修改,如果Subversion不可以自动完成,将会让用户解决。
更详细的svn知识详见后续引用书籍
2. 搭建svn服务器
查看本机是否已经安装Subversion
rpm -qa subversion
卸载旧版
yum remove subversion
安装svn
yum install subversion
验证版本
svnserve --version
新建一个目录用于存储svn所有文件
mkdir /path/to/repos
创建svn版本库
svnadmin create /path/to/repos
这样就在目录/path/to/repos使用默认数据存储方式创建了一个新的版本库(可以指定格式),这个新的版本库会以修订版本版本0开始其生命周期,以版本库的视角来看,里面除了最上层的根目录(/),什么都没有。
以文件的视角看,可以发现文件夹里包含了conf, db,format,hooks, locks, README.txt等文件,说明一个SVN库已经建立。
配置svn用户权限
修改 /conf目录下三个文件 authz, passwd, svnserve.conf
1.打开 svnserve.conf,将下列配置项前面的#和空格都去掉
#anon-access = read
anon-access :定义非授权用户的访问权限,anon即anonymous,有三种方式: none 、 read 、 write ,设置为 none 限制访问,read 为只读, write 为具有读写权限,默认为 read 。
#auth-access = write
定义授权用户的访问权限,有三种方式: none 、 read 、 write ,设置为 none 限制访问, read 为只读,write 为具有读写权限,默认为 write 。
# password-db = passwd
定义保存用户名和密码的文件名称,这里为 passwd ,和该文件位于同一目录。
# authz-db = authz
定义保存授权信息的文件名称,这里为 authz,和该文件位于同一目录。
将 anon-access = read 的 read 改为 none,禁止匿名访问
对svnserve.conf的修改需要重启以使配置生效,对passwd和authz的修改直接生效,不必重启
添加帐号密码
[users] # harry = harryssecret # sally = sallyssecret mj=123 jj=456
帐号是mj,密码是123;帐号是jj,密码是456
配置权限
权限配置分为两个部分,[groups]分组配置和[repo:/]路径下权限的精细配置
[groups]分组配置,用来划分用户
[groups] # harry_and_sally = harry,sally # harry_sally_and_joe = harry,sally,&joe topgroup=rh # 在[groups]下面添加组名和用户名,多个用户间用逗号隔开可以对不同用户组设置不同权限,没必要对每个用户进行单独设置 @topgroup=rw # 用户组前面用@符号,如果是用户,直接写用户名就可以了。 * = # 表示除了上面设置了权限的用户组之外,其他任何人都被禁止访问本目录,这个很重要
版本库(repos)路径下权限的精细配置,用来划分用户的读写权限
[<版本库名>:<路径>] [repo:/]
repo是版本库的名字,比如我们通过“svnadmin create /home/user/svn/test”创建了一个版本库test,则repo就是'test'
如版本库abc的路径/tmp的版本库路径权限段的段名为 "[abc:/tmp]" # [/foo/bar] # harry = rw # &joe = r
示例1
[test:/] @g_manager = rw * = r “[test:/]”表示这个目录结构的相对根节点,或者说是test项目的根目录 “@”表示g_manager是一个组名,这一组用户的权限为读写,权限适用范围是整个/test目录下 “* = r" 表示其他人只能读,不能写
示例2
[test:/home/thinker] thinker = rw * = r 版本库"test"中路径"/home/thinker"只有用户"thinker"有读写权限,其他用户只有可读权限
启动svn服务
默认端口(3690)启动
svnserve -d -r /path/to/repos --listen-port 1999
指定端口启动
svnserve -d -r /path/to/repos --listen-port 1990 在1990端口启动svn
svn默认监听3690端口,-d代表以守护进程启动。
3. 防火墙设置
svn进程运行起来以后,本地可以直接连接,但是远端客户端要连接还需要打开防火墙的svn运行端口
CentOS6和7命令不一样, 以下命令适用于CentOS6.9
防火墙开启端口
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
防火墙关闭端口
/sbin/iptables -I INPUT -p tcp --dport 80 -j DROP
保存
/etc/rc.d/init.d/iptables save
查看打开的端口
/etc/init.d/iptables status
重启防火墙
service iptables restart
查看svn
ps -ef | grep svn
4. 远程连接svn服务
svn co svn://211.149.xxx.xxx:xxxx/xxx # co = checkout
svn co svn://211.149.xxx.xxx:xxx/test
正常
svn co svn://211.149.xxx.xxx:xxx/test 此处test是svn创建文件夹的子文件夹
svn: E000061: Can't connect to host '211.149.xxx.xxx':
Connection refused
checkout
svn co svn://test1@211.xxx.xxx.xxx:xxxx/test
查看svn上文件
svn list svn://211.149.xxx.xxx:xxx/test --username test1
导入本地文件
svn import kktest/ svn://211.149.xxx.xxx:xxx/test/kktest -m "add a test dir"
更多操作详见参考书籍
参考资料:
https://www.awaimai.com/1650.html
https://www.cnblogs.com/weifeng1463/p/7593729.html
《使用Subversion进行版本控制》 -- Ben Collins-Sussman 等人著