您现在的位置是:网站首页> 编程资料编程资料
SVN与Git版本控制的优缺点差异全面分析_其它综合_
2023-05-27
321人已围观
简介 SVN与Git版本控制的优缺点差异全面分析_其它综合_
一、集中式vs分布式
1.Subversion属于集中式的版本控制系统
集中式的版本控制系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
Subversion的特点概括起来主要由以下几条:
- 每个版本库有唯一的URL(官方地址),每个用户都从这个地址获取代码和数据;
- 获取代码的更新,也只能连接到这个唯一的版本库,同步以取得最新数据;
- 提交必须有网络连接(非本地版本库);
- 提交需要授权,如果没有写权限,提交会失败;
- 提交并非每次都能够成功。如果有其他人先于你提交,会提示“改动基于过时的版本,先更新再提交”… 诸如此类;
- 冲突解决是一个提交速度的竞赛:手快者,先提交,平安无事;手慢者,后提交,可能遇到麻烦的冲突解决。
好处:
每个人都可以一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限。
缺点:中央服务器的单点故障。
若是宕机一小时,那么在这一小时内,谁都无法提交更新、还原、对比等,也就无法协同工作。如果中央服务器的磁盘发生故障,并且没做过备份或者备份得不够及时的话,还会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,被客户端提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人提取出来。
Subversion原理上只关心文件内容的具体差异。每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容。
2.Git属于分布式的版本控制系统
Git记录版本历史只关心文件数据的整体是否发生变化。Git 不保存文件内容前后变化的差异数据。
实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一连接。
在分布式版本控制系统中,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程。
另外,因为Git在本地磁盘上就保存着所有有关当前项目的历史更新,并且Git中的绝大多数操作都只需要访问本地文件和资源,不用连网,所以处理起来速度飞快。用SVN的话,没有网络或者断开VPN你就无法做任何事情。但用Git的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程的镜像仓库。换作其他版本控制系统,这么做几乎不可能,抑或是非常麻烦。
Git具有以下特点:
Git中每个克隆(clone)的版本库都是平等的。你可以从任何一个版本库的克隆来创建属于你自己的版本库,同时你的版本库也可以作为源提供给他人,只要你愿意。
Git的每一次提取操作,实际上都是一次对代码仓库的完整备份。
提交完全在本地完成,无须别人给你授权,你的版本库你作主,并且提交总是会成功。
甚至基于旧版本的改动也可以成功提交,提交会基于旧的版本创建一个新的分支。
Git的提交不会被打断,直到你的工作完全满意了,PUSH给他人或者他人PULL你的版本库,合并会发生在PULL和PUSH过程中,不能自动解决的冲突会提示您手工完成。
冲突解决不再像是SVN一样的提交竞赛,而是在需要的时候才进行合并和冲突解决。
Git 也可以模拟集中式的工作模式
Git版本库统一放在服务器中
可以为 Git 版本库进行授权:谁能创建版本库,谁能向版本库PUSH,谁能够读取(克隆)版本库
团队的成员先将服务器的版本库克隆到本地;并经常的从服务器的版本库拉(PULL)最新的更新;
团队的成员将自己的改动推(PUSH)到服务器的版本库中,当其他人和版本库同步(PULL)时,会自动获取改变
Git 的集中式工作模式非常灵活
你完全可以在脱离Git服务器所在网络的情况下,如移动办公/出差时,照常使用代码库
你只需要在能够接入Git服务器所在网络时,PULL和PUSH即可完成和服务器同步以及提交
Git提供 rebase 命令,可以让你的改动看起来是基于最新的代码实现的改动
Git 有更多的工作模式可以选择,远非 Subversion可比
二、版本库与工作区
Subversion的工作区和版本库是截然分开的,而Git的工作区和版本库是如影随形的。
1.SVN的版本库和工作区是分离的
Subversion 的工作区和版本库物理上分开:Subversion的版本库和工作区是存储在不同路径下,一般是在不同的主机中,Subversion的企业级部署中,版本库在服务器上,只能通过 https, http, svn 等协议访问,而不能直接被用户接触到。
Subversion的工作区是一份版本库在某个历史状态下的快照,如:版本库最新的数据检出到工作区。
Subversion的工作区中每一个目录下都包含一个名为 .svn 的控制目录(隐藏的目录),该目录的作用是:
① 标识工作区和版本库的对应关系。
② 包含一份该子目录下检出文件的原始拷贝。当文件改动的差异比较或者本地改动的回退时,可以直接参考原始拷贝而无须通过网络访问远程版本库。
Subversion 的 .svn 控制目录会引入很多麻烦:
① .svn 下的文件原始考本,会导致在目录下按照文件内容搜索时,多出一倍的搜索时间和搜索结果。
② .svn 很容易在集成时,引入产品中,尤其是 Web 应用,将 .svn 目录带入Web服务器会导致安全隐患。因为一个不允许目录浏览的Web目录,可以通过 .svn/entries 文件查看到该目录下可能存在的文件。
2 .Git 的版本库和工作区如影随形
Git 的版本库和工作区在同一个目录下,工作区的根目录有一个.git的子目录,这个名为 .git的目录就是版本库本身,它是Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。所以千万要小心删除这个文件。
工作区中其他文件为工作区文件,可能是从 .git 中检出的,或者是要检入的,或者是运行产生的临时文件等。
版本库可以脱离工作区而存在,成为 bare(赤裸)版本库。可以用 –bare参数来创建。但是工作区不能脱离版本库而存在,即工作区的根目录下必须有一个名为 .git 的版本库克隆文件。
Git 的版本库因为就在工作区中,能直接被用户接触到。
① 用户可以编辑 .git/config 文件,修改配置,增添新的源
② 用户可以编辑 .git/info/exclude 文件,创建本地忽略…
Git 的工作区中只在工作区的根目录下有一个 .git 目录,此外再无任何控制目录。Git 工作区下唯一的 .git 目录是版本库,并非 .svn 的等价物,如果删除了 .git 目录,而又没有该版本库的其他镜像(克隆)的话,你破坏了整个历史,版本库也永远的失去了。
Git 在本地的 .git 版本库,提供了完全的改动历史。除了和其他人数据交换外,任何版本库相关的操作都在本地完成,更多的本地操作,避免了冗长的网络延迟,大大节省了时间。例如:查看 log,切换到任何历史版本等操作都无须连接网络。
Git如何保证安全:本地创建一个Git库,因为工作区和库是在同一个目录中,如果工作区删除了,或者所在的磁盘分区格式化了,数据不是全都没有了么?其实我们可以这样做:
① 在一个磁盘分区中创建版本库(最好是用 –bare 参数创建),然后在另外的磁盘分区中克隆一个新的作为工作区。在工作区的提交要不时的PUSH到另外分区的版本库,这样就实现了本地的数据镜像。你甚至可以在本地创建更多的版本库镜像,安全性要比Subversion的一个库加上一个工作区安全。
② 另一个办法:把你的版本库共享给他人,当他人克隆了你的版本库时,你就拥有了一个异地备份。
三、全局版本号和全球版本号
SVN的全局版本号和CVS的每个文件都独立维护一套版本号相比,是一个非常大的进步。在看似简单的全局版本号的背后,是Subversion提供对于事物处理的支持,每一个事物处理(即一次提交)都具有整个版本库全局唯一的版本号。
Git的版本号则更进一步,版本号是全球唯一的。Git 对于每一次提交,通过对文件的内容或目录的结构计算出一个SHA-1 哈希值,得到一个40位的十六进制字符串,Git将此字符串作为版本号。
1. SVN与Git版本号比较
所有保存在Git 数据库中的数据都是用此40位的哈希值作索引的,而不是靠文件名。
使用哈希值作版本号的好处就是对于一个分布式的版本控制系统,每个人每次提交后形成的版本号都不会出现重复。另一好处是保证数据的完整性,因为哈希值是根据内容或目录结构计算出来的,所以我们还可以据此来判断数据内容是否被篡改。
SVN 的版本号是连续的,可以预判下一个版本号,而 Git 的版本号则不是。
因为 subversion 是集中式版本控制,很容易实现版本号的连续性。Git 是分布式的版本控制系统,而且 Git 采用 40 位长的哈希值作为版本号,每个人的提交都是各自独立完成的,没有先后之分(即使提交有先后之分,也由于PUSH/PULL的方向和时机而不同)。Git 的版本号虽然不连续,但是是有线索的,即每一个版本都有对应的父版本(一个或者两个),进而可以形成一个复杂的提交链
Git 的版本号简化:Git 可以使用从左面开始任意长度的字串作为简化版本号,只要该简化的版本号不产生歧义。一般采用7位的短版本号(只要不会出现重复的,你也可以使用更短的版本号)。
四、部分检出
Subversion可以将整个库检出到工作区,也可以将某个目录检出到工作区。对于要使用一个庞大、臃肿的版本库的用户来说,部分检出是非常方便和实际的。
但是Git只能全部检出,不支持按照目录进行的部分检出。
1. SVN的部分检出
在SVN中,从仓库checkout的一个工作树,每个子目录下都维护着自己的.svn目录,记录着该目录中文件的修改情况以及和服务器端仓库的对应关系。所以SVN可以checkout部分路径下的内容(部分检出),而不用checkout整个版本库或分支。
Subversion 有一条命令:svn export ,可以将 subversion 版本库的一个目录下所有内容导出到指定的目录下。Subversion 需要 svn export 命令是因为该命令可以导出一个干净的目录,即不包含 .svn 目录(包含配置文件和文件原始拷贝)。
2. Git的检出
Git 没有部分检出,这并不是说只有将整个库克隆下来才能查看文件。有很多 git 工具,提供直接浏览git库的功能,例如 gitweb, trac 的 git 版本库浏览, redmine 的 git 版本库浏览。
Git-submodule 可以实现版本库的模块化:Git 通过子模块处理这个问题。
子模块允许你将一个Git 仓库当作另外一个Git仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持你的提交相对独立。
Git 为什么没有实现 svn export 的功能?由于git的本地仓库信息完全维护在project根目录的.git目录下,(不像svn一样,每个子目录下都有单独的.svn目录)。所以,只要clone,checkout然后删除.git目录就可以了。
五、更新和提交
1.更新操作
在SVN中,因为只有一个中心仓库,所以所谓的远程更新,也就是svn update ,通过此命令来使工作区和版本库保持同步。
对于git来说,别人的改动是存在于远程仓库上的,所以git checkout命令尽管在某些功能上和svn中的update类似(例如取仓库特定版本的内容),但是在远程更新这一点上,还是不同的,不属于git checkout的功能涵盖范围。
Git使用git fetch和git pull来完成远程更新任务,fetch操作只是将远程数据库的object拷贝到本地,然后更新remotes head的refs,git pull 的操作则是在git fetch的基础上对当前分支外加merge操作。
2.SVN中的commit命令
对于SVN来说,由于是中心式的仓库管理形式,所以并不存在特殊的远程提交的概念,所有的commit操作都可以认为是对远程仓库的更新动作。在工作区中对文件进行添加、修改、删除操作要同步到版本库,必须使用 commit命令。
add 命令,是将未标记为版本控制状态的文件标记为添加状态,并在下次提交时入库。
delete命令,是通过SVN来删除文件,并在下次提交后有效。
Subversion 有提交列表功能,即将某些文件加入一个修改列表,提交可以只提交处于该列表的文件。
3.Git中的暂存区域(stage)
Git 管理项目时,文件在三个工作区域中流转:Git 的本地数据目录,工作目录以及暂存区域。暂存区域(stage)是介于 workcopy 和 版本库HEAD 版本的一种中间状态。所谓的暂存区域只不过是个简单的文件,一般都放在git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。
要将一个文件纳入版本管理的范畴,首先是要用gitadd将文件纳入stage的监控范围,只有更新到stage中的内容才会在commit的时候被提交。另外,文件本身的改动并不会自动更新到stage中,每次的任何修改都必须重新更新到stage中去才会被提交。对于工作区直接删除的文件,需要用 git rm 命令进行标记,在下次提交时,在版本库中删除。
工作区的文件改动(新增文件,修改文件,删除文件),必须用 git add 或者 git rm 命令标识,使得改动进入 stage
提交只对加入 stage 的改动进行提交
如果