关于 Git 的那些事

导语

本文主要介绍了 Git 的基本概念以及如何使用 Git 统计代码量,同时介绍了 Tortoise Git 这款 Git 界面使用工具。

一、Git简介

Git 是一种分布式版本控制系统( Distributed Version Control System,简称 DVCS),客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份。

Git 主要有以下几个特点:

1、直接记录快照,而非差异比较。

Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。这类系统(CVS,Subversion 等)每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容。Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。

2、近乎所有操作都是本地执行。

在 Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。例如,如果要浏览项目的历史更新摘要,Git 不用跑到外面的服务器上去取数据回来,而直接从本地数据库读取后展示给你看。所以任何时候都可以马上翻阅,无需等待。

3、时刻保持数据完整性。

在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成。

4、多数操作仅添加数据。

常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,都会使回退或重现历史版本变得困难重重。在别的 VCS 中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在 Git 里,一旦提交快照之后就完全不用担心丢失数据。

综上所述 Git 更像是个小型的文件系统,但它同时还提供了许多以此为基础的超强工具。而不只是一个简单的版本控制系统工具。

二、Git 的工作流程

基本的 Git 工作流程如下:

1. 在工作目录中修改某些文件。

2. 对修改后的文件进行快照,然后保存到暂存区域。

3. 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。

更为简洁的说明如下图所示:

对于任何一个文件,在 Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。

由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。每个项目都有一个 Git 目录,它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。

从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。这些文件实际上都是从 Git 目录中的压缩对象数据库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。

所谓的暂存区域只不过是个简单的文件,一般都放在 Git 目录中。我们可以从文件所处的位置来判断状态:如果是 Git 目录中保存着的特定版本文件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。

三、Git 分支

在 Git 中,分支是一个很重要的概念。Git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。Git 会使用 master 作为分支的默认名字。在若干次提交后,提交这有一个指向最后一次提交对象的 master 分支,它在每次提交的时候都会自动向前移动。Git 是通过创建一个新的分支指针来创建分支的。

Git 标识你在当前哪个分支的原理是,有一个名为 HEAD 的特别指针指向你当前所在的分支。该指针与其他的版本控制系统(比如 SVN)里的 HEAD 概念大不相同。在 Git 中,它是一个指向你正在工作中的本地分支的指针。运行创建分支的命令,仅仅是建立了一个新的分支,但不会自动切换到这个分支中去,下图中,新建一个 testing 分支之后,仍然在 master 的分支。

如果需要切换分支,需要使用命令来进行分支的切换。切换上图中的 testing 分支,这样 HEAD 就指向了 testing 分支,如下图所示:

每次提交分支之后,HEAD 随着分支一起向前移动,如下图所示:

由于 Git 中的分支实际上仅是一个包含所指对象校验和(40 个字符长度 SHA-1 字串)的文件,所以创建和销毁一个分支就变得非常廉价。说白了,新建一个分支就是向一个文件写入 41 个字节(外加一个换行符)那么简单,当然也就很快了。

这和大多数版本控制系统形成了鲜明对比,它们管理分支大多采取备份所有项目文件到特定目录的方式,所以根据项目文件数量和大小不同,可能花费的时间也会有相当大的差别,快则几秒,慢则数分钟。而 Git 的实现与项目复杂度无关,它永远可以在几毫秒的时间内完成分支的创建和切换。

下面以一个简单的例子来做下说明:

1. 开发某个网站。

2. 为实现某个新的需求,创建一个分支。

3. 在这个分支上开展工作。

假设此时,需要紧急修补一个问题,那么可以按照下面的方式处理:

1. 返回到原先已经发布到生产服务器上的分支。

2. 为这次紧急修补建立一个新分支,并在其中修复问题。

3. 通过测试后,回到生产服务器所在的分支,将修补分支合并进来,然后再推送到生

产服务器上。

4. 切换到之前实现新需求的分支,继续工作。

Git 的分支主要有以下几种类型:

1、长期分支

长期分支一般指的是最为稳定的分支,分支内的代码一般比较老旧。一般来说,在 master 分支中保留完全稳定的代码,即已经发布或即将发布的代码。与此同时,一般会有一个名为 develop 或 next 的平行分支,专门用于后续的开发,或仅用于稳定性测试,当该分支一旦测试过后至稳定状态,便可以把它合并到 master 里。

也可以把该过过程类比为流水线经过测试的提交对象集合被遴选到更稳定的流水线,如下图所示:

2、特性分支

一个特性分支是指一个短期的,用来实现单一特性或与其相关工作的分支。特性分支在任何规模的项目中都可以使用。

3、远程分支

远程分支是对远程仓库中的分支的索引。它们是一些无法移动的本地分支;只有在 Git 进行网络交互时才会更新。远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置。

一次 Git 克隆会建立你自己的本地分支 master 和远程分支 origin/master,它们都指向 origin/master 分支的最后一次提交。你在本地 master 分支做了些改动,与此同时,其他人向远程代码库中推送了他们的更新,那么服务器上的 master 分支就会向前推进,而于此同时,你在本地的提交历史正朝向不同方向发展。不过只要你不和服务器通讯,你的 origin/master 指针仍然保持原位不会移动。

此时可以运行命令来同步远程服务器上的数据到本地。该命令首先找到 origin 是哪个服务器,从上面获取你尚未拥有的数据,更新你本地的数据库,然后把 origin/master 的指针移到它最新的位置上。

四、Git 常用命令

这里大概介绍下 Git 的常用命令:

命令

含义

git clone

克隆代码

git add

添加文件/分支

git commit

提交文件/分支

git status

显示已修改的文件/分支

git branch

查看当前分支

git checkout

切换分支

git fetch

推送文件/分支

git rm

移除文件

git mv

移动文件

git log

查看 log 信息

git pull

从代码库中拉取最近的代码

五、Git 统计代码

这里来说明下如何通过 git log 的命令来统计一段时间内的代码修改量,首先说明下 git 是如何进行代码数量统计的,注意是有一下的四点:

1、增加空白行/增加换行符后,增加的行数加 1。

2、删除换行符后,删除的行数加 1。

3、修改了某一行后,增加和删除的行数同时加 1

4、统计的代码指标只有增加的和删除的行数,没有修改的行数,与 svn 不一样。

接着介绍如何通过命令来实现一段时间内代码量的修改:

1、首先需要将要统计代码的通过 git clone 将代码从远程代码仓库拷贝至本地:

需要注意的是,如果建立的这个代码仓库的性质为 public 的话,则可以直接通过 git clone 路径的方式来进行代码的克隆。如果性质为 private 的话,如果使用 git clone 路径的方式则需要输入用户名以及密码来进行代码克隆的操作,如下图所示:

这种方式有一种不方便的地方,在每进行一次 git 命令的操作的时候就需要输入用户名以及密码。

还有一种方式是可以通过 git clone 用户名 密码 路径的方式来进行代码的克隆,例如项目的 git 路径为:http://git.code.oa.com/项目名称.git 那么使用的 git clone 的具体方式为:git clone http://用户名:密码@http://git.code.oa.com/项目名称.git 来进行代码仓库克隆到本地的操作,如下图所示:

需要注意的是:用户名和密码是写到 http//之后,用户名和密码之间使用冒号隔开,密码与后面的路径之间用@符号间隔。

此处就有一个需要处理的问题就是,有时可能用户的密码中有包含@这个符号,那么就需要将该字符进行转译的处理,此处的@相当于@这个字符串。

2、跳转至完成克隆的本地代码文件夹中,进行拉取最新代码的处理。

当命令行中提示代码已经克隆到本地完成之后,需要使用 cd 命令跳转至生成的本地代码文件夹中。

需要注意的是,默认登录进来的分支是 master 分支,即主分支。然后在执行 git pull 指令来拉取最新的代码:

如果有更新则会直接更新,如果没有则会提示用户目前的代码已经是最新的。此处代码克隆有一点需要说明的是:对于同一个项目,他的 git 代码路径一旦新建之后则不会改变,此后如果需要获取最新的代码,则只需要跳转至该项目的文件夹下,执行 git pull 命令即可拉取到最新的代码。

3、使用 git log 命令拉取一段时间的代码修改量

(1) 统计 master 分支的代码修改量使用 git log 命令拉取一段时间的代码修改量的具体命令为:

git log --after=2017-02-14 --before=2017-02-16 --pretty=tformat: --numstat | awk '{ add = $1 ; subs = $2 ; loc = $1 - $2 } END { printf "added lines: %s removed lines : %s total lines: %sn",add,subs,loc }'

其中 after 和 before 这两个参数是用户用来设置需要统计代码量的时间范围,表示统计的时间区间为(2017-02-14, 2017-02-16),此处统计的时间量为开区间,不包括 2017-02-14 和 2017-02-16 的量,即统计的为 2017-02-15 这一天的量。Pretty 参数表示对输出的值进行格式的设置,awk 为 linux 系统中自带的一个强大的文本分析工具,通过后面指定的方式计算出代码的增加和删除的量,同时输出到命令行中。下图中直接得到修改的值:

(2) 统计其他分支的代码修改量

由于进入项目之后,默认进入的是 master 的分支,有可能会有需要统计其他的分支的情况,此时需要先进行分支的切换,然后再进行统计。

首先执行 git branch 指令来查看当前有哪些分支,命令行中给出当前项目中全部的分支,其中绿色的表示你当前所在的分支。

需要切换至其他的分支,运行 git branch v1.2.0(分支名) 的命令,进行分支的切换,再运行 git branch 进行验证,表明分支切换成功:

此时,则与统计 master 的步骤一致,先执行 git pull 命令,然后再运行 git log 的令:

最后有一点需要重点说明的是:进行使用 git log 进行代码量统计之前,一定要先执行 git pull 的命令,确保此时本地的代码是与远程代码仓库保持一致的,然后才能确保统计的结果是准确的。

六、Git 常用工具介绍

这里再来介绍一款好用的 Git 工具,Tortoise Git,也称为小乌龟 Git。小乌龟 Git 只支持 Windows 系统, 有一个前辈小乌龟 SVN, TortoiseSVN 和 TortoiseGit 都是非常优秀的开源的版本库客户端. 分为 32 位版与 64 位版.并且支持各种语言,包括简体中文(Chinese, simplified; zh_CN)。

通过http://download.tortoisegit.org/tgit/这个链接来下载安装包进行安装,此处对于安装的过程就不详细的进行说明了,这里说明安装完成之后的一些简单的操作界面。

1、克隆代码到本地

在需要保存的文件夹中点击右键,选择 git clone 的命令,点击之后,在出现的窗口中的 URL 中填写代码仓库的地址,然后直接点击 ok,则克隆命令开始执行:

下图表示克隆完成:

同时指定的文件夹中出现拷贝的代码文件夹:

进入文件夹之后,点击右键,然后选择 Tortoise Git 之后,右侧的列表中给出 Git 不同命令。

如果需要统计代码修改量,则需要先选择 pull,下图表示已经更新成功:

然后再选择 show log,如下图所示:

其中第 1 个地方表示当前代码的分支,第 2 处统计的时间段,第 3 处表明当前时间段的修改量,第 4 处是查看具体统计的结果,点击之后,计算之后出现最后的修改的结果:

如果需要切换分支,则直接点击第 1 处的 master,然后选择分支:

回到查看 log 界面,则分支进行了转换:

七、总结

本篇文章主要讲了下 Git 的一些基本的概念以及如果使用 git log 的命令来进行一段时间段的代码量统计,其中还可以统计不同作者修改的代码量,其中关于 git log 统计的其他的功能在这里就不细说了。同时还简单地说明小乌龟 Git 的使用方法。笔者对于这两者的研究还在继续中,请各位大牛们多多指教。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

姚姝娜的专栏

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏熊二哥

Git快速入门

由于GIT刚刚开始使用不久,经常会在Merge时出现没有change-id的情况,在结合gerrit使用时,经常出现不能提交的情形,使得自己很困扰。最近有次熬夜...

19010
来自专栏生信技能树

linux系统环境变量一文就够

Linux是一个多用户的操作系统。每个用户登录系统后,都会有一个专用的运行环境。 通常每个用户默认的环境都是相同的,这个默认环境实际上就是一组环境变量的定义。 ...

3465
来自专栏贺贺的前端工程师之路

第一次发布自己的npm包

在做表单的时候,会遇到很多的表单项的验证工作,几乎很多验证都是重复的,有一个比较好的lodash库来做了这些工作,但是里面有些方法和实际的业务工作有些不符。比如...

932
来自专栏Java3y

Linux用户和权限管理看了你就会用啦

没想到上一篇能在知乎获得千赞呀,Linux也快期末考试了,也有半个月没有写文章了。这篇主要将Linux下的用户和权限知识点再整理一下。

1900
来自专栏北京马哥教育

最实用也最容易被遗忘的 Linux 命令行使用技巧

作为一个日常在Linux环境下工作的工程师,每天都要大量使用Linux命令行。有时候我们会在网上翻查命令行的使用技巧,但是一旦未能及时进行练习,很快就会把这些...

2877
来自专栏云知识学习

Windows Server 2008 用户管理

”用户”是计算机的使用者在计算机系统中的身份映射,不同的用户身份拥有不同的权限,每个用户包含一个名称和一个密码;

34812
来自专栏漏斗社区

工具| 诸神之眼nmap定制化之初识篇

Nmap是学习网络安全必备的一款工具,有着强大的信息收集能力,有本书甚至因此称它为“诸神之眼” 。Nmap不仅仅是一个端口扫描器那么简单,它还有着一个强大的脚本...

3618
来自专栏BeJavaGod

权限框架 - shiro 自定义realm

上篇文章中是使用的默认realm来实现的简单登录,这仅仅只是个demo,真正项目中使用肯定是需要连接数据库的 首先创建自定义realm文件,如下: ? 在shi...

3125
来自专栏LEo的网络日志

shell技巧分享(三)

3128
来自专栏张戈的专栏

Linux系统zip压缩命令详细参数,附文件排除选项的正确用法

这次给博客添加了纯代码缓存之后,发现缓存文件竟然达到了 50 多 MB!而我的服务器每次还需要同步至七牛,文件体积的增加都会增加文件远程同步备份的时间。因此,我...

2775

扫码关注云+社区