【SVN】使用笔记

svn如何使用import目录作为工作拷贝+我的svn学习笔记

来源: http://blog.renren.com/share/164228750/1040429171

前奏

svn作为一款极其优秀的开源版本控制系统,应用广泛,从组织到个人遍及各行各业。因此学习和熟练掌握它,对提高我们日常工作效率和数据安全非常重要,尤其对开发人员协同管理Project的文档,代码,各类图等,能达到事半功倍的效果。不必再每天完成工作后,打包工程目录,备份每天的版本;也不用几个人堆在一起效率低下地手工合计代码;也不用担心偶尔因忘记打包,而丢失宝贵的数据资料。现在笔者已经养成完全使用svn管理日常的一些小项目,即使是个人使用,因为实在是不想每次都打包了,然后找数据再去一堆压缩包里去找。

svn有Win和Linux的版本,这里讲的是后者,而且主要是命令行操作(不过通过命令行或者能更加理解svn的工作方式和原理),前者有乌龟这类图形工具,虽功能不全,但操作也确实简单。

需求分析

为了避免手工管理一个我们日益变大的项目,于是我们选择svn,让程序为我们自动控制版本并记录下更改记录。但每当使用import子命令将工程导入到svn时,我们遇到一个极其恶的问题:将本地的工程目录全部提交上去之后,但是这个原始工程目录却不是工作拷贝,于是我还得把这个原始工作目录删掉,重新从版本库中checkout出来一个拷贝。这太不爽了,暂且不论这个工程占多大磁盘空间,明明有这个工程,只是缺少版本控制信息,有必要就删掉而重新检出整个工程么。于是我在google再google,但始终没有找到解决方法,后来了解到,svn本来就没有考虑过这个问题,貌似就只能删掉原始工程目录,而重新从库中检出一个带版本控制信息的一模一样的工程。

Solution

可能是因为个人有某种强迫症,偶还是一如继往地寻找方法企图解决这个问题,现在终于使用了一个小技巧搞定了,目前市场上还没有见到过这种方法,完全自创哦。方法如下(依然以最经典的helloworld工程为例) :

1. cd进入helloworld工程所在目录 2. 递归导入工程到版本库: svn import helloworld svn://localhost/project -m "Just Test this Trick." 3. 执行最关键的命令(参数--depth=empty是精髓,它只初始化版本控制信息,不检出任何文件): svn co --depth=empty svn://localhost/project helloworld 4. 然后进入工程目录: cd helloworld 5. 执行命令: svn st 然后显示所有文件前全带?号,因为此时这些文件还不在版本控制管辖范围内。 6. 因此我们将它们全部加入: svn add * 现在所有文件前全显示为A标记,即为Add状态。 7. 为了与版本库一致,执行update命令(其实此时这些文件与现在版本库中是一模一样的,因为我们才刚刚提交完,没有作任何更改,此举是为了“骗过”svn): svn up * 此时更新必然会有冲突,而且还是100%,程序提示“在 “xxx” 中发现冲突。选择: (p) 推迟,(mf) 全用我的,(tf) 全用他人的,(h) 使用帮助以得到更多选项:”,这时我们一定要选“(mf) 全用我的“,即输入mf,否则我们前面的工作就没有意义了。 8. 这时再用如下命令: svn st svn ci 命令均无显示,因为无状态变化,现在这个原始工程已经“转变“成一个work copy了。现在开始工作吧^_^。

--------------------------------俺是分隔线----------------------------------------



以下是我个人曾经的学习笔记,很乱,如果能用上,则看看,高手们就忽略掉它的存在吧。

http://www.subversion.org.cn/svnbook
http://subversion.tigris.org/faq.zh.html

sudo apt-get install subversion

#sudo apt-get install libapache2-svn(这个是和apache配合使用的,如果不打算使用apache则可不安装)

完成安装后,给系统添加一个用户组(如svn),把想要加入这个组的加一下(至少要把你自己加进吧)

# Add group
sudo addgroup svn
# Append user z as the supplemental Groups to group svn
sudo usermod -G svn -a z

cd svnroot/
mkdir zigbee_paper
sudo chown -R root:svn zigbee_paper/
sudo svnadmin create /home/z/public/share/svnroot/zigbee_paper/

$ svnserve -d --foreground -r /home/svn
# -d -- daemon mode
# --foreground -- run in foreground (useful for debugging)
# -r -- root of directory to serve
# svnserve --daemon --root=#SVNPATH/repos --listen-port=3690
注:不推荐使用root用户启动服务,默认端口号为3690

设置为随系统自动启动

编写启动脚本文件,命名为svn,放到 /etc/init.d/ 中

#!/bin/sh
# description: svnserve auto start-stop script.
#

# svn command home
svn_home=/usr/bin

# svn repository home

svn_repository=/home/svn

# svn owner
svn_owner=root

###
if [ ! -f "$svn_home/svnserve" ]
then
echo "svnserver startup: cannot start"
exit
fi
case "$1" in
'start')
echo "starting svnserve..."
su - $svn_owner -c "$svn_home/svnserve -d -r $svn_repository"
# if the user of script is root,can use the command below
#        $svn_home/svnserve -d -r /svn
echo "start svnserve finished!"
;;
'stop')
echo "stoping svnserve..."
su - $svn_owner -c "$svn_home/killall svnserve"
echo "stop svnserve finished!"
;;
'restart')
echo "restarting svnserve..."
$0 stop
$0 start
;;
*)
echo "usage: svn { start | stop | restart } "
exit 1
esac
exit 0


更改启动脚本文件属性
sudo chmod 755 /etc/init.d/svn


制作符号链接
sudo ln -s /etc/init.d/svn /etc/rc1.d/K99svn
sudo ln -s /etc/init.d/svn /etc/rc2.d/S99svn


注:
rc1,rc2,rc3,rc4,rc5,rc6 文件夹中的文件,是不同运行级别的文件,根据不同的场景,系统会自动执行不同文件夹中的文件;
K 为不执行的文件,S 为执行的文件,执行的时候,按照K或者S后面的序号,从小到大逐一执行,一般自己建立的脚本,序号都命名为 99,可以有多个
执行K文件,实际上是调用脚本中的stop命令;执行S开头的文件,实际上是调用文件中的start命令
S40以后,才是系统网络配置完成的时刻。序号要调整到40后面

SVN 1.5会更加灵活,通过-N选项将会多余,我们使用–depth选项代替它,根据规格,–depth的可能值有:
–depth=empty: 更新不会拉出任何不存在的文件或目录
–depth=files: 更新会拉出所有的文件,但不包括子目录
–depth=immediates: 更新会拉入所有不存在的文件或子目录;但子目录的设置为depth=empty。
–depth=infinity: 更新会拉入所有不存在的文件和目录,子目录的设置为depth=infinity,与目前的缺省更新行为方式相同。

我们可以这样操作:

A 通过命令行操作

1、检出目录images
svn co --depth=empty http://www.iusesvn.com/project1/images images_work_dir

这样就在本地形成了一个工作拷贝目录images_work_dir

2、进入images_work_dir目录,单独更新logo.jpg
svn up logo.jpg

这样,我们就单独检出了logo.jpg,后面就可以对这个文件进行修改、提交等操作。


这三个命令(svn status、svn diff和 svn revert)都可以在没有网络的情况下工作,这让你在没有网络连接时的管理修改过程更加简单,像在飞机上旅行,乘坐火车往返或是在海滩上奋力工作时。

Subversion通过在.svn管理区域使用原始的版本缓存来做到这一点,这使得恢复本地版本而不必访问网络,这个缓存(叫做“text-base”)也允许Subversion可以根据原始版本生成一个压缩的增量(“区别”) 提交.
svn revert ITEM的效果与删除ITEM然后执行svn update -r BASE ITEM完全一样,但是,如果你使用svn revert它不必通知版本库就可以恢复文件。


svn update
$ svn update
U  INSTALL
G  README
C  bar.c
Updated to revision 50.
U和G没必要关心,文件干净的接受了版本库的变化,文件标示为U表明本地没有修改,文件已经根据版本库更新。G标示合并,标示本地已经修改过,与版本库没有重迭的地方,已经合并。但是C表示冲突,说明服务器上的改动同你的改动冲突了,你需要自己手工去解决。
svn status可能返回的状态码(注意,#之后的不是svn status打印的)。
L       some_dir            # svn已经在.svn目录锁定了some_dir
M       bar.c               # bar.c的内容已经在本地修改过了
M       baz.c               # baz.c属性有修改,但没有内容修改
X       3rd_party           # 这个目录是外部定义的一部分
?       foo.o               # svn并没有管理foo.o
!       some_dir            # svn管理这个,但它可能丢失或者不完
~       qux                 # 作为file/dir/link进行了版本控制,但类型已经改变
I       .screenrc           # svn不管理这个,配置确定要忽略它
A  +    moved_dir           # 包含历史的添加,历史记录了它的来历
M  +    moved_dir/README    # 包含历史的添加,并有了本地修改
D       stuff/fish.c        # 这个文件预定要删除
A       stuff/loot/bloo.h   # 这个文件预定要添加
C       stuff/loot/lump.c   # 这个文件在更新时发生冲突

C       stuff/loot/glub.c   # 文件在更新时发生属性冲突
R       xyz.c               # 这个文件预定要被替换
S       stuff/squawk        # 这个文件已经跳转到了分支
K       dog.jpg             # 文件在本地锁定;有锁定令牌
O       cat.jpg             # 文件在版本库被其他用户锁定
B       bird.jpg            # 文件本地锁定,但锁定发生错误
T       fish.jpg            # 文件本地锁定,但锁定丢失
在这种格式下,svn status打印五列字符,紧跟一些空格,接着是文件或者目录名。第一列告诉一个文件的状态或它的内容,返回代码解释如下:
A item

文件、目录或是符号链item预定加入到版本库。
C item

文件item发生冲突,在从服务器更新时与本地版本发生交迭,在你提交到版本库前,必须手工的解决冲突。
D item

文件、目录或是符号链item预定从版本库中删除。
M item

文件item的内容被修改了。
R item

文件、目录或是符号链item预定将要替换版本库中的item,这意味着这个对象首先要被删除,另外一个同名的对象将要被添加,所有的操作发生在一个修订版本。
X item

目录没有版本化,但是与Subversion的外部定义关联,关于外部定义,可以看“外部定义”一节。
? item

文件、目录或是符号链item不在版本控制之下,你可以通过使用svn status的--quiet(-q)参数或父目录的svn:ignore属性忽略这个问题,关于忽略文件的使用,见“svn:ignore”一节。
! item

文件、目录或是符号链item在版本控制之下,但是已经丢失或者不完整,这可能因为使用非Subversion命令删除造成的,如果是一个目录,有可能是检出或是更新时的中断造成的,使用svn update可以重新从版本库获得文件或者目录,也可以使用svn revert file恢复原来的文件。
~ item

文件、目录或是符号链item在版本库已经存在,但你的工作拷贝中的是另一个。举一个例子,你删除了一个版本库的文件,新建了一个在原来的位置,而且整个过程中没有使用svn delete或是svn add。
I item

文件、目录或是符号链item不在版本控制下,Subversion已经配置好了会在svn add、svn import和svn status命令忽略这个文件,关于忽略文件,见“svn:ignore”一节。注意,这个符号只会在使用svn status的参数--no-ignore时才会出现—否则这个文件会被忽略且不会显示!


Collision:

小于号、等于号和大于号串是冲突标记,并不是冲突的数据,你一定要确定这些内容在下次提交之前得到删除,前两组标志中间的内容是你在冲突区所做的修改:
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======

后两组之间的是Sally提交的修改冲突:
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2


svn import temp/ file:///home/z/public/share/svnroot/test/
在导入数据之后,你会发现原先的目录树并没有纳入版本控制,为了开始工作,你还是要运行svn checkout得到一个干净的目录树工作拷贝。

global-ignores选项是一个空格分隔的列表,用来描述Subversion在它们版本化之前不想显示的文件和目录,缺省值是*.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store。
svn status,svn add和svn import命令也会忽略匹配这个列表的文件,你可以用单个的--no-ignore命令行参数来覆盖这个选项。
1、Linux命令行下将文件checkout到本地目录

svn checkout path(path是服务器上的目录)

例如:svn checkout svn://192.168.1.1/pro/domain

简写:svn co

2、Linux命令行下往版本库中添加新的文件

svn add file

例如:svn add test.php(添加test.php)

svn add *.php(添加当前目录下所有的php文件)

3、Linux命令行下将改动的文件提交到版本库

svn commit -m “LogMessage“ [-N] [--no-unlock] PATH(如果选择了保持锁,就使用–no-unlock开关)

例如:svn commit -m “add test file for my test“ test.php

简写:svn ci

4、Linux命令行下的加锁/解锁

svn lock -m “LockMessage“ [--force] PATH

例如:svn lock -m “lock test file“ test.php

svn unlock PATH

5、Linux命令行下更新到某个版本

svn update -r m path

例如:

svn update如果后面没有目录,默认将当前目录以及子目录下的所有文件都更新到最新版本。

svn update -r 200 test.php(将版本库中的文件test.php还原到版本200)

svn update test.php(更新,与版本库同步。如果在提交的时候提示过期的话,是因为冲突,需要先update,修改文件,然后清除svn resolved,最后再提交commit)

简写:svn up

6、Linux命令行下查看文件或者目录状态

1)svn status path(目录下的文件和子目录的状态,正常状态不显示)

【?:不在svn的控制中;M:内容被修改;C:发生冲突;A:预定加入到版本库;K:被锁定】

2)svn status -v path(显示文件和子目录状态)

第一列保持相同,第二列显示工作版本号,第三和第四列显示最后一次修改的版本号和修改人。

注:svn status、svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的,原因是svn在本地的.svn中保留了本地版本的原始拷

posted @ 2013-06-04 22:47  哈哈好玩  阅读(232)  评论(0)    收藏  举报