Git笔记一:一个svn用户第一次接触git

前言

一直以来接触的团队和项目都是选用svn做版本控制(游戏行业)因此一直都没有机会接触git。因为svn和git的理念差的太多,对于那些一个版本控制都没接触的新人来讲,直接一张白纸的去学git要比拿svn对照着学要来的没有历史包袱。所以很多教程都是直接讲git,甚少会直接拿svn和git做对比。我觉得像我这样的长期习惯svn的用户转学git也是不少的。svn用户转学git最痛苦的就是svn的固有概念会很影响自己去接受git概念,老是会拿来对比拿来套。然而由于没有引导和清晰的对比,越套越无法理解git或误解git,所以我把自己svn转git时对比这两种版本控制工具的心得笔记写一写。

这个文章本质上是我学习git官方教程的注解笔记。每段笔记都会附上相应的git官方教程的文档超链。

一个svn用户第一次接触git

参考文档:起步-关于版本控制

svn与git的最大差异是什么?

网上各种教程都说svn是集中式git是分布式这就是最大的差异。我当初也是道听途说的这么认为,但是直到我自己去接触git后才发现分布式并不是git相较于svn的最大差异和亮点。

git的最大的亮点是他的版本历史的组织形式

svn与git的版本历史组织形式差异

svn的版本历史是一维的线性历史

svn的版本号是数字,一个整形。svn确定版本新旧是通过版本号的大小来确定的,版本号数值越大就越新,整形数字天然就可以标志提交版本的先后关系属性。一维、且线性,一个版本必然只有一个上一个版本和一个下一个版本。

git是单向链表+图的麻花式单向历史

git没有合并的时候就像单向链表,不断的往前演进。有合并的时候就会变成形成像图一样交错。但是演进方向依然是单向的。

git每一个提交都是一个版本快照,这个提交对象由一个hash命名,这个hash就是git的版本号。hash码不同于整形数字,数字的大小能够标识版本的先后关系,而hash是无大小的,因此git的在提交对象内定义了一些字段属性,其中有个parent字段指向了上一个版本的版本提交对象的hash码,以此来确定提交的先后。

由于git的版本记录是链表结构,因此git可以直接通过改变节点的父节点的方式实现合并(三方合并)。

所以可以这么说:

  • SVN是用数组的方式管理每一个版本,版本号是数组下标,其大小定义了提交的前后,提交的历史是一维线性的一条线。
  • Git是用链表的方式管理每一个版本,版本号是hash码,通过链表串起每个提交实现有向记录,提交的历史是像麻花一样的,交错但是演进方向是一致往前的。

svn与git的对比

版本控制实现方式

svn

本质上是数据库+linux patch的原理去实现。通过记录每一修改的文件diff保存位patch,来记录差异。如果要更新到最新就通过apply应用一些列的patch补丁到最新版本,如果要回滚或回到某个版本就用revert反向apply补丁。合并操作也是把branch的提交打一遍patch然后把最新的文件与主干diff创造新patch应用到trunk上。

git

通过文件快照的方式,不记录两个版本之间的diff,只记录两个版本变化的文件。要更新到某个版本就直接前往目标版本的快照。合并就是把提交历史链表汇入主线,并创造一个新的提交快照表示这次合并。

版本历史记录组织形式

svn

trunk: c1 <--- c2 <--- c3 <--- c5

git

master: c1 <--- c2 <--- c3 <--- c5
branch:           \____ b1 ____/

创建分支

svn

master: c1 <--- c2 <--- c3 <--- c5
branch:          ↓____ b1

svn相当于在c2版本的时候把trunk拷贝当作是新项目branch去维护。这时候的branch是没有之前trunk的c1、c2提交记录的,是个纯净的项目仓库。

git

master: c1 <--- c2 <--- c3 <--- c5
branch:           \____ b1

git是链表,直接从c2开始叉开一条新链作为branch维护。branch仍然有master的c1、c2记录。

合并

svn

trunk: c1 <--- c2 <--- c3 <--- c5 <-- c6
        ↓
branch:b1 <--- b2 <--- b3 <--- b4
----------------------------------------------------------
trunk: c1 <--- c2 <--- c3 <--- c5 <-- c6_m <--- c7
        ↓                              ↑
branch:b1 <--- b2 <--- b3 <--- b4 <-- -- <--- b5

branch从trunk的c1提交开始切出,然后修改到b4后合并到trunk。branch b1~b4所有提交差异迭代后当作trunk的一次c6_m提交到trunk。c6_m有b1~b4的所有差异,c6_m就是一次合并提交。

git

master: c1 <--- c2 <--- c3
branch:           \____ b1
----------------------------------------------------------
master: c1 <--- c2 <--- c3 <--- c5_m
branch:           \____ b1 ____/

branch从master的c2开始切出,提交了b1,然后合并到master,这时候会产生一个c5_m提交。由上图可见b1那条路线汇入了master,这意味着b1也是master的提交记录之一,而c1~c5_m也是branch的提交记录。这就是git与svn的最大差别。svn主干、分支之间的提交记录是隔离独立的,合并是把分支里的一系列提交的总差异当作补丁重新应用到另一个分支上。git因为其历史记录是链表,而且版本控制用文件快照实现,每个提交就是完整快照,不存在patch式的apply过程。所以git的合并可以直接把分支的提交历史通过链表指向的方式修改连接起来。在git里,master和branch是可以共享提交的。

真实的合并-GIT
虚假的合并-SVN

万物皆分支

在SVN里要创建分支成本是很高的,项目如果大的话相当于把项目拷贝一份然后当作另一个项目去迭代维护,然后就是SVN版本库都在服务端,所以其分支也是要在SVN服务器上创建的,无法创建到本地,那就更麻烦了。而SVN的特性决定了主线和分支是独立演化的两个项目,合并操作不过是把两个项目的差异打了个超大的patch apply 提交到另一个项目而已。因为SVN的中心化、一维线性版本控制、创建分支高成本的关系,其项目大多采用先锋主干/主线多稳定分支的维护模式,也就是主干是最不稳定提交最频繁的仓库,等主干/主线新版本功能开发完毕后就从主干/主线创建出分支用于测试和修复bug作为预览版,等测试稳定后打tag创建release版,期间分支的修改都合并到主干/主线。
先锋主干多稳定分支

Git由于创建分支的成本很低,无论主干/主线还是分支都共享一套git提交快照仓库,通过链表来连接记录关系。由于分布式设计每个用户本地都有git完整仓库,支持用户创建本地分支。基于链表的提交历史特性,提供了三方合并。所以git里万物皆分支,你clone了别人的项目,本地的master就是个分支,远程仓库的master也是个分支。你fork了别人的项目你的远程仓库master也是个分支。所以git的项目多采用守护主干多先锋分支模式。

守护主干多先锋分支

群魔乱舞的git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值