学习SVN01

Posted wuhg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习SVN01相关的知识,希望对你有一定的参考价值。

第一章  SVN介绍

1.1 什么是SVN(subversion)

  SVN是近年来崛起的非常优秀的版本管理工具,与CVS管理工具一样,SVN是一个固态的跨平台的开源的版本控制系统。SVN版本管理工具管理者随时间改变的各种数据。这些数据放置在一个中央资料档案库(repository)中,这个档案库很像一个普通的文件服务器或者FTP服务器,但是,与其他服务器不同的是,SVN会备份并记录每个文件每一次的修改更新变动。这样我们就可以把任意一个时间点的档案恢复到想要的某一个旧的版本,当然也可以直接浏览指定的更新历史记录。
    为什么会有SVN这样一个项目?
    官方解释:为了接管CVS的用户基础,确切的说,我们写了一个新的版本控制系统,它和CVS很相似,但是它修正了以前CVS所没有解决的许多问题。
    SVN时一个非常通用的软件系统,它常被用来管理程序 源码,但是他也可以管理任何类似的文件,如文本、视频,图片等等。

SVN相关站点:

技术分享图片

截至到当前,所接触到常见的版本管理软件有:vss,cvs,svn,git,其中常用的就是SVN版本管理系统。

2 SVN与git的区别

2.1 SVN集中式版本控制系统

SVN版本控制系统时集中式的数据管理,存在一个中央版本库,所有开发人员本地开发所使用的代码都是来自于这个版本库,提交了代码也都必须提交到这个中央版本库。
    SVN版本控制系统工作流程如下:
1. 在中央库上创建或从主干复制一个分支。
2. 从中央库check out下这个分支的代码。
3. 增加自己的代码文件,修改现存的代码或删除代码文件。
4. Commit代码。假设有人在刚刚的分支上提交了代码,你就会被提示代码过期。

你得先up你的代码后再提交。Up代码的时候如果出现冲突,需要解决冲突后再进行提交。

2.2 git分布式版本控制

    Git是由Linus开发的,所以很自然的git个Linux文件系统结合的比较紧密,以至于在Windows上你必须使用cygwin才能使其完美工作。

那git凭什么叫做分布式的版本控制系统呢?还是从模式讲起。

Git中没有了中央版本库的说法了,但是为了开发小组的代码共享,从某种程度上说本地的仓库和远程的仓库在身份上是等价的,没有主从之分。

如果你的项目是闭源项目,或者你习惯于以往的集中式的管理模式的的话,那么在git下你也可以像SVN那么工作,知识流程中可能增加一些步骤。

1. 你本地创建一个git库,并将其add到远程git库中

2. 你在本地添加或者删除文件,然互commit。当然commit操作都是提交到本地的git库中了(其实是提交到git目录下的object目录中去了)

3. 将本地git库的分支push到远程git库的分支,如果这个时候远程git库中已经有别人push过,那么远程git库将不允许你push,这个时候你需要先pull,然后如果有冲突,处理好冲突,commit到本地git库后,再push到远程git库。

3 企业应用场景

SVN仍是当前企业主流。Git正在发展,也许未来也会成为主流,但是现在还不是。

4 运维人员掌握版本管理

    对于版本管理系统,运维人员需要掌握的技术点:

  1. 安装,部署,维护,故障。
  2. 简单的使用,很多公司都是由开发来管理,包括建立账户和添加删除账号。
  3. 对于版本控制系统,运维人员相当于开发商,开发人员是业主,运维搭建的系统为开发人员服务。

5 SVN服务运行模式和访问方式

5.1 Svn服务端运行方式

svn服务常见的运行访问方式有3种:

1、独立服务器

访问地址如:svn://svn.baby.org/sadoc);

2、借助apache等http服务

访问地址如:http://svn.baby.org/sadoc);

       a.单独安装apache+svn(不要用)。

       b.CSVN(apache+svn)是一个单独的整合的软件,带web界面管理的SVN软件

3、本地直接访问(例如:file:///root/svndata/sadoc)

5.2 SVN客户端访问方式

SVN客户端可以通过多种方式访问服务器,例如:本地磁盘访问,或者各种各样不同的网络协议访问,但一个版本库地址永远都是URL,URL反映了访问方法。

技术分享图片

6 svn 版本系统逻辑架构原理图

技术分享图片

7 SVN集中版本管理系统

SVN是一种集中式版本管理系统,集中式管理的工作流程如下图所示:

 技术分享图片

 

 

集中式代码管理的核心是SVN服务器,所有开发者在开始新一天的工作之前必须从服务器获取代码,然后进行开发,最后解决冲突,提交。所有的版本信息都放在SVN服务器上。因此如果脱离了服务器,开发者就无法进行提交代码工作

8 开发者利用SVN版本管理工作过程

下面举例说明:

开始新一天的工作:

  1. 首先从SVN服务器下载项目组最新代码:
  2. 进入自己的分支,进行开发工作,每隔一小时向服务器上自己的分支提交一次代码(很多程序员都有这个习惯。因为有时候自己对代码改来改去,最后又想还原到前一个小时的版本,或者看看前一小时修改了哪些代码,就需要这样做了)
  3. 下班时间快到了,把自己的分支合并到主分支上,一天的工作完成,并反映给服务器

这就是经典的SVN工作流程,从流程上看有缺点也有优点:

缺点:

  1. 由于每一次提交都保留一个原始副本,因此SVN数据库容量会暴增
  2. 如果不能连接到SVN服务器上,基本上不可以工作, 例如上面第二步,如果服务器不能连接上,就不能提交,还原,对比 。
  3. 不适合开源系统开发(开发人数非常多,但是Google appengine就是用的SVN的)但是一般集中式管理的有非常明确的权限管理机制(例如分只访问限制)可以实现分层管理,从而很好的解决开发人数众多的问题。

优点:
1. 管理方便,逻辑清晰明确,符合一般人思维习惯。
2. 易于管理,中实施svn服务器更能保证数据安全性。
3. 代码一致性非常高。
4. 适合开发人数不多的项目开发。
5. 普及度高,大部分软件配置管理的大学教材都是使用svn和vss。

第二章 安装配置SVN服务

1 准备操作系统并查看系统环境

1
2
3
4
5
6
[[email protected] ~]# cat /etc/redhat-release
CentOS release 6.7 (Final)
[[email protected] ~]# uname -r
2.6.32-573.el6.x86_64
[[email protected] ~]# uname -m
x86_64

2 安装SVN(subversion )

1. 首先检查SVN软件程序是否已经安装:

1
2
[[email protected] ~]# rpm -qa subversion
subversion-1.6.11-14.el6.x86_64

2.如果没有如上结果,则需要执行如下命令安装

1
2
3
[[email protected] ~]# yum install subversion -y
[[email protected] ~]# rpm -qa subversion
subversion-1.6.11-15.el6_7.x86_64

补充:yum安装rpm包安装后本地不清除的方法

1
2
[[email protected] ~]# grep keepcache /etc/yum.conf   
keepcache=1     

3 配置并启动SVN

建立SVN版本库数据存储根目录(svndata)及用户,密码权限目录(svnpasswd)

1
2
3
4
#数据存储根目录
[[email protected] ~]# mkdir -p /root/svndata
#用户密码权限目录
[[email protected] ~]# mkdir -p /root/svnpasswd 

启动SVN服务指定访问的SVN根目录

1
[[email protected] ~]# svnserve -d -r /root/svndata/  

可以查看svnserve命令帮助,了解相关启动参数:

1
[[email protected] ~]# svnserve --help

查看SVN进程

1
2
3
[[email protected] ~]# ps -ef |grep svn
root       3008      1  0 00:32 ?        00:00:00 svnserve -d -r /root/svndata/
root       3010   2919  0 00:32 pts/0    00:00:00 grep svn

检查SVN端口

1
2
3
4
5
[[email protected] ~]# lsof -i :3690
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
svnserve 3008 root    3u  IPv4  53617      0t0  TCP *:svn (LISTEN)
[[email protected] ~]# netstat -lntup|grep svn
[[email protected] ~]# lsof -i tcp:3690

4 建立项目版本库

创建一个新的SVN项目sadoc其实类似sadoc这样的项目可以创建多个,每个项目对应不同的代码,这里只是以创建一个项目为例。

1
2
3
[[email protected] ~]# svnadmin create /root/svndata/sadoc
[[email protected] ~]# LANG=en
[[email protected] ~]# tree /root/svndata/sadoc/

5 调整SVN配置文件及权限

修改svnserve.conf文件

1
2
3
4
5
6
7
8
[[email protected] ~]# cd /root/svndata/sadoc/conf/
total 12
-rw-r--r-- 1 root root 1080 Feb 23 16:11 authz
-rw-r--r-- 1 root root  309 Feb 23 16:11 passwd
-rw-r--r-- 1 root root 2279 Feb 23 16:11 svnserve.conf
[[email protected] conf]# cp svnserve.conf{,.org} 操作前备份
[[email protected] conf]# vim svnserve.conf

更改后的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[[email protected] conf]# diff svnserve.conf.org svnserve.conf
12,13c12,13
< # anon-access = read
< # auth-access = write
---
> anon-access = none
> auth-access = write
20c20
< # password-db = passwd
---
> password-db = /root/svnpasswd/passwd
27c27
< # authz-db = authz
---
> authz-db = /root/svnpasswd/authz
提示:可以用sed进行快速替换,每个开头要顶格写,没有空格
    等号前为账户等号后为密码,密码是明文的,注意权限
    更改svnserve.conf,需要重启SVN,更改authz,passwd不比重启。
#重启SVN命令
[[email protected] svnpasswd]# svnserve -d -r /root/svndata/

 修改passwd文件添加用户及密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
把密码文件模板拷贝到相关目录
[[email protected] conf]# cp passwd authz /root/svnpasswd/
[[email protected] conf]# ll /root/svnpasswd/
total 8
-rw-r--r-- 1 root root 1080 Mar 31 00:51 authz
-rw-r--r-- 1 root root  309 Mar 31 00:51 passwd
为了安全起见可以加权限
[[email protected] conf]# cd /root/svnpasswd/
[[email protected] svnpasswd]# chmod 700 *
[[email protected] svnpasswd]# ll
total 8
-rwx------ 1 root root 1080 Mar 31 00:51 authz
-rwx------ 1 root root  309 Mar 31 00:51 passwd
[[email protected] svnpasswd]# cd /root/svnpasswd/
[[email protected] svnpasswd]# vim passwd
[[email protected] svnpasswd]# cat passwd
### This file is an example password file for svnserve.
### Its format is similar to that of svnserve.conf. As shown in the
### example below it contains one section labelled [users].
### The name and password for each user follow, one account per line.
[users]
# harry = harryssecret
# sally = sallyssecret
zhangyang = zhangyang123
gongli = gongli123
stu001 = 123
stu002 = 456
youngcheung = youngcheung123
[[email protected] svnpasswd]#

修改authz文件设置权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[[email protected] svnpasswd]# cat authz
[aliases]
# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average
[groups]
# harry_and_sally = harry,sally
# harry_sally_and_joe = harry,sally,&joe
#
zhangyang26 = stu001,stu002
# [/foo/bar]
# harry = rw
# &joe = r
# * =
# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r
[sadoc:/]
zhangyang = rw
gongli = r
@zhangyang26 = r
youngcheung = rw
 
注意:
1、权限配置文件中出现的额用户名必须已在用户配置文件中定义。
2、对权限配置文件的修改立即生效,不必重启svn。
用户组格式:
[groups]
=,
其中,1一个胡勇组可以包含1和或多个用户,用户间以逗号分隔。
版本库目录格式:
[版本库:/项目/目录]
@用户组名=权限
用户名=权限
其中,方括号内部分可以有多种写法:
[/],表示根目录及以下,跟目录是svnserve启动时指定的
[repos:/]表示对版本库repos设置权限;
[repos:/sadoc]表示对版本库repos中的sadoc项目设置权限;
[repos:/sadoc/web]表示对版本库repos中的sadoc项目的web目录设置权限;

第三章 客户端软件TortoiseSVN SVN安装

Win32位操作系统

1
http://sourceforge.net/projects/tortoisesvn/files/1.6.16/root/TortoiseSVN-1.6.16.21511-win32-svn-1.6.17.msi/download

Win64位操作系统

1
http://sourceforge.net/projects/tortoisesvn/files/latest/download

软件down下来后,双击安装即可,这个比较简单,相信大家都没问题。

SVN配置

将需要上传的文件进行checkout检出

 技术分享图片

URL:是服务端地址

Chekout directory 是本地需要上传的

 技术分享图片

输入正确的用户名和密码,点击保存

技术分享图片

检出成功

 技术分享图片

文件夹会出现绿色打钩的标示,代表版本和svn一致

 技术分享图片

SVN更新

服务器更新了文件,使用SVNupdate同步最新版本

 技术分享图片

新文件,会从服务器更新至本地

 技术分享图片

SVN上传

放一个文件进去,然后右键文件-àSVNCommit进行提交

 技术分享图片

选择ALL勾选所有进行提交,也可自行勾选提交

 技术分享图片

提交成功,version会+1

 技术分享图片

第四章 Linux下SVN管理

1 SVN管理命令用法

[[email protected] ~]# svn --help

2 导入SVN原始目录树

1
2
3
4
5
6
7
8
9
10
11
12
svn import(recursively commit a copy of PATH to URL)导入目录结构到SVN服务端
[[email protected] db]# svn import /tmp/dir/ svn://10.0.0.52/sadoc/ -m "import svntree"
[[email protected] ~]# svnadmin create /root/svndata/zhangyang
[[email protected] ~]# mkdir -p /svn/trunk /svn/branch /svn/tag
[[email protected] ~]# svn import /svn/ file:///root/svndata/zhangyang -m "import"
svn: warning: cannot set LC_CTYPE locale
svn: warning: environment variable LANG is en
svn: warning: please check that your locale name is correct
Adding         /svn/trunk
Adding         /svn/tag
Adding         /svn/branch
提示:svn import /data/zhangyang/ svn://10.0.0.9/sadoc/ -m “import svntree” svn方式导入

3 从SVN库提取数据

1
2
3
4
5
6
7
8
9
10
11
12
[[email protected] ~]# svnadmin create /root/svndata/zhangyang
svnadmin: warning: cannot set LC_CTYPE locale
svnadmin: warning: environment variable LANG is en
svnadmin: warning: please check that your locale name is correct
[[email protected] ~]# mkdir -p /svn/trunk /svn/branch /svn/tag
[[email protected] ~]# svn import /svn/ file:///root/svndata/zhangyang -m "import"
svn: warning: cannot set LC_CTYPE locale
svn: warning: environment variable LANG is en
svn: warning: please check that your locale name is correct
Adding         /svn/trunk
Adding         /svn/tag
Adding         /svn/branch

查看服务器端的数据

1
2
[[email protected] sadoc]# svn ls svn://192.168.1.9/sadoc/   --username=zhangyang  --password=zhangyang123
[[email protected]]#svn ls  svn://10.0.0.52/sadoc/   --username=zhangyang  --password=zhangyang123 –verbose

当Windows发生改变可以使用下面命令更新Linux服务端数据

1
svn co svn://10.0.0.52/sadoc/ /root/sadoc/ --username zhangyang --password zhangyang123

可以本地更新

1
[[email protected] svndata]# svn co file:///root/svndata/sadoc/

4 查看SVN中的数据

查看版本库的内容‘

1
2
3
4
5
6
7
8
9
[[email protected] ~]# svn list file:///root/svndata/zhangyang/
branch/
tag/
trunk/
[[email protected] ~]# svn list file:///root/svndata/sadoc/ --verbose
      6 zhangyang                Mar 31 02:10 ./
      4 zhangyang                Mar 31 02:08 data/
      1 zhangyang                Mar 31 01:42 old/
      5 zhangyang              0 Mar 31 02:10 zhangyang.txt

5 从本地提交数据到SVN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[[email protected] sadoc]# cd /svndata/
[[email protected] svndata]# ll
total 12
drwxr-xr-x 3 root root 4096 Mar 31 02:09 data
drwxr-xr-x 3 root root 4096 Mar 31 02:08 old
-rw-r--r-- 1 root root    0 Mar 31 02:10 zhangyang.txt
drwxr-xr-x 5 root root 4096 Mar 31 02:13 sadoc
[[email protected] svndata]# rm -rf sadoc/
[[email protected] svndata]# ll
total 8
drwxr-xr-x 3 root root 4096 Mar 31 02:09 data
drwxr-xr-x 3 root root 4096 Mar 31 02:08 old
-rw-r--r-- 1 root root    0 Mar 31 02:10 zhangyang.txt
[[email protected] svndata]# touch {a..g}
[[email protected] svndata]# ll
total 8
-rw-r--r-- 1 root root    0 Mar 31 02:28 a
-rw-r--r-- 1 root root    0 Mar 31 02:28 b
-rw-r--r-- 1 root root    0 Mar 31 02:28 c
-rw-r--r-- 1 root root    0 Mar 31 02:28 d
drwxr-xr-x 3 root root 4096 Mar 31 02:09 data
-rw-r--r-- 1 root root    0 Mar 31 02:28 e
-rw-r--r-- 1 root root    0 Mar 31 02:28 f
-rw-r--r-- 1 root root    0 Mar 31 02:28 g
drwxr-xr-x 3 root root 4096 Mar 31 02:08 old
-rw-r--r-- 1 root root    0 Mar 31 02:10 zhangyang.txt
[[email protected] svndata]# pwd
/svndata
[[email protected] svndata]# svn add a b c d e f g
A         a
A         b
A         c
A         d
A         e
A         f
A         g
[[email protected] svndata]# ls
a  b  c  d  data  e  f  g  old  zhangyang.txt
[[email protected] svndata]# svn ci
svn: Commit failed (details follow):
svn: Could not use external editor to fetch log message; consider setting the $SVN_EDITOR environment variable or using the --message (-m) or --file (-F) options
svn: None of the environment variables SVN_EDITOR, VISUAL or EDITOR are set, and no ‘editor-cmd‘ run-time configuration option was found
[[email protected] svndata]# svn ci -m "svn ci data"
Adding         a
Adding         b
Adding         c
Adding         d
Adding         e
Adding         f
Adding         g
Transmitting file data .......
Committed revision 7.
Windows本地更新查看是否存在

6 SVN copy

1
2
3
4
5
[[email protected] svndata]# mkdir -p /svn/trunk /svn/branch /svn/tag
[[email protected] ~]# svn import /svn/ file:///root/svndata/zhangyang -m "import"
Adding         /svn/trunk
Adding         /svn/tag
Adding         /svn/branch

主干拷贝成分支的命令

1
2
[[email protected] svndata]# svn copy svn://10.0.0.9/sadoc/trunk svn://10.0.0.9/sadoc/branch_cms_110 -m "create a branch by zy" --username=zhangyang --password=zhangyang123
svn list file:///root/svndata/sadoc/svn list file:///root/svndata/sadoc/

提交:

1
2
3
4
5
[[email protected] sadoc]# svn ci -m "zhangyang data" --username zhangyang --password zhangyang123
checkout:
svn co svn://10.0.0.5/sadoc/ /root/sadoc/ --username=zhangyang --password=zhangyang123
commit:
svn ci -m "zhangyang data" --username zhangyang --password zhangyang123

出现错误

1
2
3
svn: Can‘t convert string from ‘UTF-8‘ to native encoding:
svn: /svndata/?230?150?176?229?187?186?230?150?135?230?156?172?230?150?135?230?161?163.txt
解决export LC_CTYPE="zh_CN.UTF-8"

svn钩子脚本简介

    钩子脚本的具体写法就是操作系统中shell脚本程序的写法,可根据自己的svn所在的操作系统和shell程序进行相应的开发。
    钩子脚本就是被某些版本库时间出发的程序,例如:创建新版本或修改为被版本控制的属性。每个钩子都能掌管足够的信息来了解发生了什么事件,操作对象时什么以及出发时间用户的账号。类似inotify或sersync。
    根据钩子的输出或者返回状态,钩子程序能以某种方式控制该动作继续执行,停止或挂起。

默认情况下,钩子的子目录中包含各种版本库钩子模板

[[email protected] ~]# ls -l /root/svndata/sadoc/hooks/

total 36

-rw-r--r-- 1 root root 1977 Mar 31 00:35 post-commit.tmpl

-rw-r--r-- 1 root root 1638 Mar 31 00:35 post-lock.tmpl

-rw-r--r-- 1 root root 2289 Mar 31 00:35 post-revprop-change.tmpl

-rw-r--r-- 1 root root 1567 Mar 31 00:35 post-unlock.tmpl

-rw-r--r-- 1 root root 3426 Mar 31 00:35 pre-commit.tmpl

-rw-r--r-- 1 root root 2410 Mar 31 00:35 pre-lock.tmpl

-rw-r--r-- 1 root root 2786 Mar 31 00:35 pre-revprop-change.tmpl

-rw-r--r-- 1 root root 2100 Mar 31 00:35 pre-unlock.tmpl

-rw-r--r-- 1 root root 2780 Mar 31 00:35 start-commit.tmpl

1.2   SVN钩子生产应用场景举例

1.3   SVN生产应用实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[[email protected] ~]# mkdir /data/www/ -p
[[email protected] data]# svn co svn://10.0.0.9/sadoc /data/www --username=zhangyang --password=zhangyang123
A    /data/www/a
A    /data/www/branch_cms_110
A    /data/www/b
A    /data/www/c
A    /data/www/d
A    /data/www/trunk
A    /data/www/e
A    /data/www/f
A    /data/www/g
A    /data/www/zhangyang.txt
A    /data/www/data
A    /data/www/tag
A    /data/www/branch
A    /data/www/old
Checked out revision 9.
[[email protected] hooks]# dos2unix post-commit
dos2unix: converting file post-commit to UNIX format ...

[[email protected] hooks]# cat post-commit

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh
REPOS="$1"
REV="$2"
export LANG="en_US.UTF-8"
LOGPATH="/app/log"
[ ! -d ${LOGPATH} ] $$ mkdir ${LOGPATH} -p
SVN=/usr/bin/svn
$SVN update --username zhangyang --password=zhangyang123 /data/www
if [ $? -eq 0 ]
 then
  /usr/bin/rsync -az --delete /data/www /tmp
fi

[[email protected] hooks]# dos2unix post-commit

dos2unix: converting file post-commit to UNIX format ...

添加执行权限

chmod 755 post-commit

利用pre-commit限制上传文件扩展名及大小

JIRA 用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。

B.Mantis是一款php开源Bug跟踪系统,比较适合中小型项目的管理及跟踪,具有多特性包括:易于安装,易于操作,基于Web,支持任何可运行PHP的平台(Windows,Linux,Mac,Solaris,AS400/i5等),已经被翻译成68种语言,支持多个项目,为每一个项目设置不同的用户访问级别,跟踪缺陷变更历史,定制我的视图页面,提供全文搜索功能,内置报表生成功能(包括图形报表),通过Email报告缺陷,用户可以监视特殊的Bug,附件可以保存在web服务器上或数据库中(还可以备份到FTP服务器上),自定义缺陷处理工作流,支持输出格包括csv、MicrosoftExcel、MicrosoftWord,集成源代码控制(SVN与CVS),集成wiki知识库与聊天工具(可选/可不选),支持多种数据库(mysql、MSSQL、PostgreSQ、Oracle、DB2),提供WebService(SOAP)接口,提供Wap访问。

 

 
















以上是关于学习SVN01的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记:python3,代码片段(2017)

学习SVN01

学习 PyQt5。在我的代码片段中找不到错误 [关闭]

svn_学习_01_TortoiseSVN使用教程

Git----分支管理01

常用HTML5代码片段