【原创】协同合作 -- Git使用介绍

发布于 2017年04月18日 作者 4T-Shirt 分类 技术开发

0. 前言

经过2016年的业务快速发展,目前Mogu-Tech团队在项目研发上,从最开始的0项目,到目前完成或者正在完成的项目大概有:20个后台项目,25个前端项目。业务的积累和代码的积累呈现出了指数型的增长。而随着业务的进一步加速,功能的丰富,团队人员的扩张,代码的爆炸式增长,对代码进行适当性管理是重要而紧急的任务。

目前Mogu-Tech团队使用的SVN版本控制工具,在当前情况下是合适的,但并不是完美甚至不是极好的。而随着不断的演化,对于代码进行分布式版本控制是在所难免的,而这正是SVN的一个不足之处。经过谨慎和对未来的长期考虑,Mogu-Tech团队决定将代码版本管理工具,从SVN切换到Git上,进一步讲,是从集中化的版本控制,切换到分布式的版本控制

本文将从三方面对Git进行介绍:Git是什么,不同场景下的Git使用,以及Git的分支概念。

1. Git ?

Git是什么

Git是当今最先进最高级的开源分布式版本控制工具,由Linux内核创始人Linus Torvalds开发而成。传闻Linus花了不到一周的时间就开发完成了第一版的Git,此处献上膝盖。Git的研发最先主要用于Linux内核代码的版本控制,后续逐渐被计算机领域的各种平台广泛采纳使用。

Git 与 SVN

小明是个程序猿,一直使用的代码版本管理工具是svn,现在他决定切换到git,他最直接的感受就是git延长了代码提交的步骤,如下所述:
svn提交代码过程:对修改的代码执行 svn commit 命令即可将代码上传到远程服务器。
git提交代码过程:对修改的代码执行 git add 命令创建快照,执行 git commit 到本地仓库,再执行 git push 到远程仓库。
从svn和git的代码提交过程来看,可以发现svn的提交步骤比git的提交步骤简单,但是简单并不意味着简洁。对于提交过程,svn将代码文件提交到集中式服务器,而git选择的是提交文件快照到相应的分布式服务器。git相比于svn具备以下几个优点:

  1. 同步内容小

    svn同步的是文件,git同步的是快照(可以理解为对文件的压缩以及索引)。因此不管是切换分支或者是提交内容,git同步的数据量是远远小于svn。

  2. 内容完整性

    进行内容存储时,git采用的是SHA-1哈希算法,这样即使出现磁盘故障或者网络问题时,版本库的破坏也会比svn的小很多;

  3. 速度

    在进行代码克隆,更新,提交,分支切换时,svn操作的是相关文件,而git操作的是版本内容。比如svn要切换到3个不同分支,需要复制3个分支的文件下来,而git操作的是每个版本的文件快照,而文件快照是git对相应的文件进行处理,压缩,通过快照建立索引可以快速定位发生变化的文件以及内容。因此涉及到同步或者提交内容时,git的性能会比svb优越很多。

  4. 分布式

    这是git和svn的核心区别。分布式意味着,开发人员可以随时随地进行代码提交、分支操作、查看历史版本等操作。即使在无网络情况下,也可以将代码提交到本地仓库,等网络连接情况下再提交到远程服务器。

对于很多开发者而已,svn的优点很明显,傻瓜式的操作,但缺点也比较突出,svn不适合应用于大型协同团队负责的多版本系统。而git更加适合使用于分布式的版本控制系统中,可以更好的解决分支切换,分布式开发,代码合并等实际系统常见的代码管理场景。

Git可视化平台

常见的Git可视化代码管理平台有:GitHubGitLabBitBucket,如下所示: 14925037651.png14925037702.png14925037733.png

以上相关的代码管理平台,底层采用的代码版本控制工具都是Git,开发者可以直接在这些平台上完成Git的相关操作。其中GitLab经常被公司或者个人用于本地搭建属于自己的GitLab管理平台。

2. Git 常用命令介绍

Git虽然是个分布式版本控制工具,但并不可怕。对于普通开发者而言,上手使用Git有几个核心关键节点。

1. 清楚操作的文件当下属于何种状态;
2. 清楚当前是在哪个分支版本下进行开发;
3. 熟悉公司使用的Git研发流程;
4. 使用Git手册,熟悉Git基本操作命令;

文件状态 

14925037944.png

如上图所述,git将文件的状态划分为四种状态:

  1. Untracked

    未跟踪状态。 最常见的例子为,新增的文件默认处于该状态。

  2. Unmodified

    未修改状态。顾名思义,文件未被修改。或者文件刚被提交,也是处于该状态。

  3. Modified

    修改状态。顾明思议,只要被git跟踪的文件,发生了编辑,都处于该状态。

  4. Staged

    暂存状态。git提交的内容是文件快照,因此在提交内容前,需要将要进行提交的文件进行文件快照化。处于该状态的文件便可以进行最终的commit。

14925038485.png

如图所示,为git不同状态的标识Demo,其中Unmodified状态不会进行显示,表示其他文件处于Unmodified状态。
上述的四种状态,分布隶属于2个区:工作区和暂存区。
工作区:包括Untracked,Unmodified,Modified等状态,主要用于对文件的操作的区域。主要使用checkout,进行状态还原。 暂存区:指的是Staged状态,主要存储文件的快照。主要使用reset进行暂存区与工作区之间的状态还原。

当前分支

Git适用于分布式的版本控制中,在实际使用中,我们经常会在多个分支下进行代码开发和管理。当前分支指的是用户当前的开发分支。

关于分支的具体介绍,将在第三节当中进行介绍。

Git流程

 14925039636.png

上图所示,为Mogu-Tech正在尝试的版本控制开发流程。

  1. 1个项目仓库默认拥有1个主干,从主干上根据不同迭代阶段的项目需求业务大小,会陆续有几个保持稳定长久运行的分支;

  2. 每一个长运行的分支,将是一个大的版本迭代,在生产发布时,合并到主干分支,进行一个版本发布,并对该发布分支进行Tag标记;

  3. 同时每一个长稳定运行的分支,允许拥有多个主题分支和bug fix分支,由具体的开发人员而定;

  4. 开发环境:开发者可以独立运行自己的开发分支(主题/bug fix);测试环境:运行长稳定分支;预发/生产环境:将分支合并到主干,发布主干;

基本操作

本节将会介绍实际Git操作过程中,不同阶段的git操作命令。 14925040137.png

上图所示,一个项目的普通开发者参与一个项目的版本控制,可以主要分为3个步骤:1.项目初始化;2.项目版本内容修改;3.远程推送至服务器。

A. 项目初始

克隆项目至本地: git clone https://github.com/tensorflow/tensorflow.git 
获取远程所有分支: git fetch origin 
切换至某个分支: git checkout branch_dev 
拉取分支最新快照: git pull origin branch_dev 

B.1 项目版本内容修改 - 提交

状态查询: git status 
生成文件快照,存储于暂存区(支持Regex): git add FILENAME.txt 
提交快照至本地仓库(支持Regex): git commit FILENAME.TXT -M "commit log" 

B.2 项目版本内容修改 - 删除/还原/其他

删除文件: git rm -rf deleted_dir_name 
配置不进入版本控制的文件: 1. vi .gitignore 2.输入不加入版本控制的文件名称 3.提交gitignore到仓库 
版本的还原: 详见文件状态章节 

C 项目推送至远程服务器

拉取分支最新快照: git pull origin 0.0.1 
代码合并: git commit README.md -i -m "进行提交,表示冲突已处理好" 
推送至远程服务器: git push origin 0.0.1 
14925040428.png

上图所示,为在拉取远程分支快照至本地时,发生远程代码和本地代码发生冲突。详见 红线 标出。如何处理代码冲突,详见下图。 14925040679.png

打开冲突的文件,冲突的内容,将会有相应的标识。
1.  <<<<<<<HEAD 至 ======= 表示冲突内容中,属于当前分支的部分;
2.  ======= 至 <<<<<<<169a29b 表示冲突内容中,属于其他分支/远程服务器的部分;

开发者只需对标识出来的冲突部分进行处理,执行  git commit README.md -i -m "进行提交,表示冲突已处理好"  即可表示解决好了冲突并进行了提交。

149250409110.png

上图所示,为项目的master/owner的两个核心操作,当然master/owner也具备普通开发者相关的开发者权限。

A. 初始化项目 149250411211.png

作为owner/master可以直接在gitlab上进行远程的Git项目创建。如上图所示。 149250413512.png

创建Git项目之后,可根据实际情况,进行仓库内容的初始化,如上图所示。

B. 分支合并到主干

分支打标签,并推送至远程: 1. git tag v0.0.1; 2. git push origin v0.0.1 
合并分支到主干,并推送至远程: 1. git checkout master; 2. git merge 0.0.1; 3. git push origin master 
删除分支,并推送至远程: 1. git branch -D 0.0.1; 3. git push origin :0.0.1 
一般来说,进行重大版本迭代和发布时。需要对当前分支进行标签化,然后合并到主干进行发布,至于该分支是否删除,根据实际情况而定。

3. Git 分支

分支是分布式版本控制的一个核心部分,更是协同开发的关键。分支的概念允许开发者在多个分支上进行独立的代码开发,本节主要介绍下Git的分支。理解好Git分支,有助于我们更好的进行团队的协同开发。 149250416313.png

上图所示为,用户在一个远程服务器上,查看某个Git项目的当前分支。

单个分支

默认情况下,初始化一个Git项目时,会创建一个master的主干分支。 149250418414.png

上图所示,为master主干分支的提交情况。

  1. HEAD->MASTER::当前的分支指针,指向Master,表示当前位于主干分支上;

  2. MASTER->265bda:265bda...可以理解为是一个提交记录id,表示当下master主干分支最新的提交记录;

  3. 265bda->a1dcd7->...:表示当前主干分支的提交记录顺序链

查看当前位于哪个分支: vi .git/HEAD 
查看分支的提交记录: git log ,如下图所示,展示了一个分支的提交记录情况
149250420415.png

分支并行

149250422716.png

上图所示为,从主干上创建一个新的分支0.0.1,并切换到0.0.1时,0.0.1分支的提交记录情况。
可以发现,从老分支上新拉一个分支时,虽然新的分支没有做任何提交记录,但却会主动继承老分支的所有提交记录,从而拥有老分支的所有文件快照。这是git的一个神设计体现。

149250424517.png

上图所示,为开发者在新的分支0.0.1上进行分支开发和提交,创建了一个新的提交记录6015e9,而该提交只是发生在0.0.1分支上,并不会主动同步到老分支上。开发者完全可以放心的在新分支上进行开发,待功能完成之后,再合并到老分支上,不影响老分支的独立使用。

149250426518.png

上图所示,为开发者主动将0.0.1分支合并到master主干分支,提交记录的变化。可以发现,分支的合并,其实某种意义来说,就是提交记录的合并。通过合并提交记录,将多个分支的代码进行合并,使得老分支拥有新分支的提交记录。

分支基本操作

获取远程服务器的所有分支: git fetch origin 
查看本地分支列表: git branch 
本地创建新分支: git branch 0.0.1 
分支切换: git checkout 0.0.1 
本地创建分支,并切换到新分支: git checkout -b 0.0.1 
分支删除: git branch -D 0.0.1 
分支合并: git merge 0.0.1 
查看当前分支的提交记录: git log 
分支间的提交记录对比: git log 0.0.1 ^master  (查看提交记录在0.0.1上的,但不位于master分支的)
分支文件内容差异: git differ 0.0.1 master 

本节介绍的分支概念,只是Git分支概念的一小部分,随着项目的不断扩张,人员的不断增加,开发者会更加体会到git分支的精妙之处,也会体会到git分支更加深层的操作。

总结

本文的目的,主要是对git初学者如何快速使用和理解git进行了介绍。围绕几个方面的内容:git是什么,不同场景下的git操作,以及git分支概念。通过理解这几方面的内容,希望不仅有助于我们快速的执行git操作,更能理解git背后的设计思路。

知其然,知其所以然。

参考

  1. GIT基本知识: https://en.wikipedia.org/wiki/Git

  2. Pro-Git简体版:http://iissnan.com/progit/

  3. 内部Git: git clone git@gitlab.moguyun.com:books/techbooks.git 


评论(0)

暂无评论