对比SVN学习GIT版本管理工具

Posted 彩色蚂蚁

tags:

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

对比SVN学习GIT版本管理工具

作者:刘旭晖 Raymond转载请注明出处

Emailcolorant@163.com

BLOGhttp://blog.csdn.net/colorant/

主页:http://sites.google.com/site/rgbbones/

      

       因为近期工作需要,要掌握git的使用方法,所以决心花点时间学习一下它的各种使用方法,就当是花点时间磨刀吧。所以写这篇文档的目的主要还是为了自己能够系统的学习和理解GIT应用的方方面面,因为之前对SVN算是比较熟悉,所以决定以概念对比的方式来整理这篇文章,尽管,有些地方两者无法直接比较 8 )此外,主要的目的还是为了方便自己积累相关的git使用技巧。文中理解有偏差的地方,还请大家指正。

 

1         概述和参考资料

1.1        GIT相关

Ø       http://www.kernel.org/pub/software/scm/git/docs/

这里面包括了 tutorial 基本的操作 / core-tutorial 底层命令的使用 / user’s manual 完整的用户手册以及其它各种资料,如果你看完了,我的这篇文档你也就不用看了。

1.2        SVN相关

http://svnbook.red-bean.com/ 这里是一份onlinesvn book

或者也可以看tortoiseSVN的帮助文档

 

2         仓库的组织结构及相关概念

 

仓库的组织管理形式这部分,应该说是版本管理工具设计上最核心的内容。对于仓库的内部管理机制,我了解得很少,只能从外部的表象上做一些简单的比较。

 

SVN属于中心式的仓库管理,完整的仓库数据,统一维护在服务器端的(当然,服务器也可以就是你的本机了)仓库中,对于客户端来说,本地取得的数据不是完整的仓库,只是仓库中特定版本的部分或全部数据,同时,客户端还负责维护本地数据的变更情况,在客户端并不拥有仓库完整的历史数据。本地的工作树和仓库是相对独立的。

 

对于Git来说,应该属于分布式的仓库管理,倒不是说仓库的内容分散在不同的server上,只是对仓库而言,没有中心仓库之说,所有的仓库都是平等的。对于一个仓库的不同工作拷贝,每个都拥有完整的历史数据,工作树和仓库基本是合二为一的。

 

SVN中,从仓库checkout的一个工作树,每个子目录下都维护着自己的.svn目录,记录着该目录中文件的修改情况以及和服务器端仓库的对应关系。所以SVN可以局部checkout部分路径下的内容,而不用checkout整个分支。

 

Git仓库中,项目根目录下的.git目录统一管理了所有的仓库数据和当前工作树的相关信息。

 

SVN中,默认采用FSFS的数据库格式,任何提交都是一个版本的递增,所谓分支,tag等概念都只是仓库中不同路径上的一个对象或索引而已,和普通的路径并没有本质的区别。在工作树中,可以同时checkout多个分支的内容。

 

Git中,其内部的对象层级依赖关系或许和SVN类似,但是其工作树的视图表现形式和SVN完全不同。工作树永远是一个完整的分支,不同的分支由不同的head索引去构建,你不可能在工作树中同时获得多个分支的内容。

 

3         基本操作

3.1        仓库创建初始化

SVN中,仓库本身的管理和日常应用,使用的是两套不同的命令。仓库的创建和备份维护等使用的命令是 svnadmin 使用svnadmin create来创建一个新的仓库

 

git中,创建一个新的仓库,可以在一个空目录下,使用git init来实现,它将创建一个.git目录用来维护仓库数据。

 

SVN中,创建仓库的地方并不是你日常使用的仓库的地方,你需要在别的地方checkout出特定的仓库路径作为你的日常工作的目录。在git中,仓库所在的目录也就是你的日常工作目录,没有服务器端和客户端之分。(严格的说 .git目录才是仓库,.git目录外的地方是你的工作目录,对于bare project来说,只有git目录下的内容,工作目录离得内容还是要checkout出来的)

3.2        Checkout仓库

SVN中,使用SVN checkout(co)checkout本地或远程仓库的代码

 

而对于git来说,尽管也有checkout命令,但是由于你需要在本地拥有仓库,所以通常从服务器上checkout代码的第一步是使用git clone来获取一个仓库的拷贝,默认的git clone操作同时还会checkout一份远程仓库上当前active的分支

 

SVN中,其仓库的管理形式决定了你可以只checkout仓库中特定路径/分支下的子目录,而不是整个仓库,而git只能checkout整个分支。

 

3.3        将文件纳入版本管理

SVN中,使用SVN add,这样在以后的commit过程中,每次在提交数据之前,svn都会自动根据这些add过的对象的修改情况,构建一个commit tree

 

git中,因为存在index的概念,要将一个文件纳入版本管理的范畴,首先是要用git-update-index –-add将文件纳入index的监控范围,只有更新到index中的内容才会在commit的时候被提交。另外,文件本身的改动并不会自动更新到index中,每次的任何修改都必须重新更新到index中去才会被提交。 当然,通常会用git add这样的封装脚本来调用git-update-index

 

3.4        检查当前状态

SVN Status 可以显示当前working tree的文件修改状态

 

git git status 命令显示当前index的状态和working tree的状态。

3.5        提交文件

Git commit操作在git命令中属于相对简单的,需要注意的一点就是上面提到的,只有index中的内容才会比提交。

3.6        删除文件

在使用Svn rm删除一个目录的时候,因为每个目录下都存在.svn目录,记录了这个目录于服务器端仓库相关的信息,所以在commit之前,目录里的其它文件会被删除,但是目录及其子目录并不会被真正删除,只有commit以后,目录才会被删除。

 

git中,同样,使用git rm 删除文件。但是git对目录的处理有些奇怪,如果某个目录下的所有文件都被删除以后,该目录就会被自动删除,也就是说你无法保留一个空的目录。你也无法添加一个空目录到仓库里。也就是说git 自动忽略空目录,不知道这样做的目的是什么?

 

3.7        查看log

svn log命令基本上就是用来查看版本提交时的所填写的log信息

 

git log可以做的事情会多很多,毕竟git log是对底层核心命令的再包装,通过它,不仅可以查看log信息,还可以输出特定版本的具体变更内容等等信息。

 

3.8        版本回溯

SVN中,不提供任何从仓库中删除对象的机制,任何的修改都会导致版本的递增,所以,如果想丢弃一个修改,你需要做的事是反向diff你的修改,再提交一个新的版本。

 

git中提供了重置committed tree对象索引的机制,所以,你可以通过例如git-reset这样的操作将当前分支的版本恢复到以前的某个状态。经常看见的例子就是回溯一个版本,然后修改内容,再次提交。不过这样做搞不好很容易出问题。包括在git-push之类的操作时会被reject,需要强行push之类的。

 

如果只是想放弃一个修改,git的文档推荐使用git-revert操作,这个操作基本上和SVN的思路是一样的了,就是提交一个新的版本将需要revert的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容。

 

3.9        放弃当前修改

SVN中,使用SVN revert对目录或文件操作都可以将当前工作树上特定路径的修改恢复到服务器上的版本,放弃当前的修改。

 

Git中,对特定文件使用不带其它参数的git checkout命令可以将文件恢复到index中的状态,如果你想恢复的特定的版本,那么类似: git checkout HEAD file这样的操作,将文件恢复到HEAD tree即最近一次提交的状态。

 

不过git checkout有个问题,不知道是否是故意这样设计的,就是即使用git rm删除的内容,如果没有提交,git checkout以后也会恢复,包括它在index中的状态。这点有些不理解。 理论上index上已经记录这个删除操作,不应该恢复才对。

 

Git中还有一种办法,可以快速彻底的放弃自从上次commit以来的所有变更,git reset –hard HEAD

 

3.10  代码合并

git merge能够自动记住以前merge过的位置和状态,这个比较容易理解,因为通过每个分支的head commit可以跟踪它的对象索引关系。另外,因为其对象管理机制的原因,只能以commit为单位,merge整个分支的所有修改。不能有选择的merge部分路径下的修改。Merge的时候要求indexHEAD是一致的,如果merge成功,内容会直接commit,而工作树上的修改仍会保持。(如果失败,会在工作树上将需要merge的内容和你已有的修改合并,大概不是你所希望的,所以最好不要这样做)

 

merge特定分支的特定版本之前的所有修改,可以通过merge那个版本对应的rev来实现,merge某一段版本区间的修改,考虑到commit需要完整的代码树关系,估计靠git merge来做是没有办法了,需要自己diff / patch代码来实现

 

SVNMerge操作不会记住它的merge历史,换句话说,你可以多次merge同一份代码,但是他的好处是你可以自由的选择merge哪一部分、哪一段版本之间的代码,应该说他基本等同于是diffpatch的组合。不过因为SVN没有index的概念,所以merge的操作会和当前working tree上的修改合并在一起。

 

关于历史信息方面,因为svnmerge实际是patch文件内容本身,所以,不同分支上的历史信息不会在merge以后的主干上体现出来,而gitmerge,如果没有冲突的话,实际是merge commit树的继承关系,所以,所有的历史信息在merge以后的commit中都能够被索引到。

 

 

3.11  获取单纯的代码

svn中,如果不需要任何历史信息,只想要某个版本纯粹的代码(经常会有这种需求,这样做本地数据比较小) 那么,使用svn export命令即可以实现。

 

git中,似乎没有这样的命令,不过,由于git的本地仓库信息完全维护在project根目录的.git目录下,(不像svn一样,每个子目录下都有单独的.svn目录)。所以,只要clonecheckout然后删除.git目录就可以了。

 

4         协同工作和权限控制

4.1        远程提交

对于SVN来说,由于是中心式的仓库管理形式,所以并不存

以上是关于对比SVN学习GIT版本管理工具的主要内容,如果未能解决你的问题,请参考以下文章

Git/SVN 版本管理工具的对比

Git简史及对比SVN区别

SVN和Git对比梳理

用好 Git 和 SVN ,轻松驾驭版本管理

通俗易懂|用好Git 和 SVN ,轻松驾驭版本管理

SVN与GIT工具使用对比

(c)2006-2024 SYSTEM All Rights Reserved IT常识