#iOS系列开发-版本控制工具Git的使用

作为一个开发者,与团队之间默契的配合是很重要的,我们所写的代码在无论是在公司还是在个人来说都是一份不可随意丢弃的东西,但是如果只是单纯的开发,我们很难做到今天能够知道上周写完后的项目代码,我们往往需要备份一份,比如我们今天开发出1.0版本的应用,为了留档,我们可能会保存一份完整代码在服务器,之后再拷贝一份继续新的开发,但是这样只能留存部分我们关注的版本,且一份代码就是一份文件,我们的项目有个100M 那么只是单纯的10个备份就有1G了,这样下去,多大的硬盘都不够用. 很万幸,我们拥有版本控制工具. 你可能或多或少的听过这个,比如GIT 比如SVN 在这里我就简单的讲讲GIT的使用方式

相比同类软件,Git有很多优点。其中很显著的一点,就是版本的分支(branch)和合并(merge)十分方便。有些传统的版本管理软件,分支操作实际上会生成一份现有代码的物理拷贝,而Git只生成一个指向当前版本(又称"快照")的指针,因此非常快捷易用。

在这里我先使用工具演示一般,之后我会把对应的终端命令也展示出来,你只需一一对应即可

为了比较容易的做演示,我会在osChina或者在GitHub上创建一个新的远程项目仓库来代替我们所在公司的git服务器的地址(我们的公司可能会自己部署服务器,比如使用gitlab,gerrit等).

1.创建项目远程仓库(如果在公司,公司基本都是已经搭建好的,你只要有地址就好了)



这里我们就能看到一个可以克隆或者下载的仓库的地址, OK,至此,我们就等于是到公司入职了,公司老大说我们创建了一个新的项目,并且项目的仓库地址给你了,你只要努力开发,把代码放进去就好了.

只有一个地址!我们改如何做? 这里我就先使用sourcetree这个工具做直接可视化的演示,后面再自己找终端命令匹配.


选择从URL克隆输入我们刚才获取到的地址,输入指定到我们本地的目标路径和名称 我们就可以看到我们的桌面出现了一个文件夹,跟我们创建的仓库比对一下

是的这个文件夹就是仓库的拷贝!,我们只要在这个本地仓库里面写代码,写完之后推送到远程仓库即可, OK,我们将我们创建好的一个iOS(或者任意的)项目直接拖进去,或者创建一个新的项目,项目路径直接指定到这个文件夹也可以. 这里我采用创建到指定的该文件夹,项目创建完成之后


我们会发现很多的M,A...这里M表示的是修改,A表示的是新增,D表示的是删除.. 我们先不管,我们打开sourcetree,会发现文件状态的变化 选中所有的之后,我们即可提交 我们会发现 那么我们点击推送 你会发现新的变化 此时我们就把我们本地创建好的项目推送到老板给你的服务器去了! 这样做有什么好处呢?简单点,我的电脑坏了,换了一个电脑我就不需要那U盘巴拉巴拉的拷贝了,直接还是克隆一份从服务器即可,我们本地就会有一个和远程一样的拷贝了. 如果你是单人开发,不会有任何问题了.你每一次提交的版本你都会有记录 但是,如果是多人合作开发,我们就会出现我想要推送到远程的时候发现远程的和我们本地的不一样,在此之前别人也推送了代码.那么我们只要在提交之后,推送之前先抓取一下就可以了,保证我们的代码除了本人修改的部分,其余的都和远程的一样即可. 我们也要养成习惯,在修改代码前都先抓取一下,这样随时保证我们本地的代码是最新的. 我们继续, 我现在扮演的角色是项目组老大,我是负责搭建框架的人. 并且我已经搭建完成了项目 我把搭建完成之后的项目推送到远程 本次提交时一个阶段性的,我可以打一个标签,并且推送到远程,让所有人都知道 这样,我可以根据标签来定位某一个阶段性的代码.

接下来是工作重点了,master是主分支,是公司的核心主干,我们不可能让任意的开发人员都在这个主干上开发代码并且提交的,作为一个开发人员我们应该在另外一个主干上开发代码,等待开发完成之后把代码在合并到主分支上

很幸运的事,我们的git也会考虑这样的事情.并且为我们预备好了,如果我们使用的话.

一、主分支Master


首先,代码库应该有一个、且仅有一个主分支。所有提供给用户使用的正式版本,都在这个主分支上发布。 Git主分支的名字,默认叫做Master。它是自动建立的,版本库初始化以后,默认就是在主分支在进行开发。(很显然,这样任何人都在这里干事情,很容易乱掉)

二、开发分支Develop

主分支只用来分布重大版本,日常开发应该在另一条分支上完成。我们把开发用的分支,叫做Develop。


什么意思呢? 我们直接转成可视化的, 我们会发现,本地多出来一个develop的分支,远程则没有,没关系,我选择推送 这样远程也就会多出来一个develop了 多出来一个分支能干什么呢? 此时我的角色是公司里面的攻城狮,我修改我要修改的代码 我们到sourcetree中提交 在推送的时候我们选择只推送develop分支到develop分支 经过多次开发,终于在develop中的我把1.0完成了 攻城狮跟老大说,项目开发完成了,于是老大审核过后,准备把它放到公司主干上留作备份 我们选择添加一个阶段性的标签,并且将内容推送, 然后我就开开心心的根据master的进行发布版本了, 工程师继续新的开发在develop,不影响master的内容. 当时细心的你会发现合并后的master是这样的 会把develop的记录都合并过来 那么怎么能做成这样的呢?

其实也很简单,你可以在合并的时候多选择一个选项即可 也就是选择快进式合并


你会看到一个大的合并到主分支上的效果,这就是我们想要的

那么git就这么简单吗? 并不是. 还记得上面创建develop的时候多出来的某些信息吗? 从初始化的第一个界面中,还有三类分支的命名规则:feature、release、hotfix,这就是未来承接具体开发工作的分支类型,从名称中就能准确把握他们的用途。

  • 功能(feature)分支
  • 预发布(release)分支
  • 修补bug(fixbug)分支

第一种是功能分支,它是为了开发某种特定功能,从Develop分支上面分出来的。开发完成后,要再并入Develop。


对应到source中就是 现在就可以在这个分支上修修补补了,经过一系列艰苦卓越的工作,这个功能开发完成了,就要合并到develop。功能分支只能合并到develop,因为这些都是临时分支,你可以根据项目需要选择是否推送到远程 提交完成之后,你会发现已经合并到develop中去了,只要提交到远程即可

第二种是预发布分支,它是指发布正式版本之前(即合并到Master分支之前),我们可能需要有一个预发布的版本进行测试。

预发布分支是从Develop分支上面分出来的,预发布结束以后,必须合并进Develop和Master分支。它的命名,可以采用release-*的形式。

所有特性的开发工作都是为了产品功能的更替,当一个或多个特性开发完成,可以进行发布了,就要准备创建release分支。

Release分支是为上线做准备的,它的命名也要遵守项目的版本命名规则,这个名字在最终合并到master时会自动变成版本标签。



这个release分支也是测试工作的目标对象,,经过一系列艰苦卓越的测试、调整工作,这个release完成了,达到了可上线的状态,就要合并到master和develop。



接下来只要把master推送到远程即可了,

最后一种是修补bug分支。软件正式发布以后,难免会出现bug。这时就需要创建一个分支,进行bug修补。

修补bug分支是从Master分支上面分出来的。修补结束以后,再合并进Master和Develop分支。它的命名,可以采用fixbug-*的形式。



比如我现在的是2.1版本,然后我在develop中开发2.2版本... 然后发现2.1版本有一个bug


经过一系列艰苦卓越的工作,这个bug修复完成了,就要合并到master和develop, 偶尔的我们会发现合并会出现冲突, 那么我们就要解决冲突 <<<<<是当前分支中的内容 >>>>>是其他分支的内容 此时我们能看到我们都需要 那么就把不需要的描述删除,把需要的保留,修改下那个文件就好

三类临时性分支中,hotfix和release的结果都要合并到master和develop中,为什么?因为它们的修改结果持续影响这后续的开发和维护,必须合并以保证代码的一致性。

当然这个临时性分支的逻辑只是sourcetree给我们提供的一种方式,我们如果使用纯粹的终端命令行,我们就需要自己来掌控这些,

对应的上面的终端命令行 你可以看看 Git常用命令

比如Git创建Develop分支的命令:

git checkout -b develop master

将Develop分支发布到Master分支的命令:

// 切换到Master分支 git checkout master // 对Develop分支进行合并 git merge --no-ff develop

这里稍微解释一下,上一条命令的--no-ff参数是什么意思。默认情况下,Git执行"快进式合并"(fast-farward merge),会直接将Master分支指向Develop分支。 使用--no-ff参数后,会执行正常合并,在Master分支上生成一个新节点。为了保证版本演进的清晰,我们希望采用这种做法。 .... 具体自己可以参考命令行

此外作为iOS开发,我们的Xcode也集成了git功能


我们也可以使用这个工具.配合使用,效果差不多.