1. 前言
以前对git的理解与使用仅限于利用github进行备份、下载git上的优秀项目等,对git的命令与使用方法都没有用心学习过,只是每次使用时临时在上网查找。这种对git的应用方式完全没有发挥出Git的版本管理功能,更不能提高工作效率。借助这此对git的版本管理的需求,我对git的基础理论进行学习,主要学习材料为Pro Git(中文版)。撰写本博客的主要目的是在学习完Pro Git后,对Git的基础理论进行整理,梳理学习知识,也算是对学习过程的一份总结。Git的初始下载、配置、与github的交互等基础操作不在本次整理范围之内,以前我参考的博文如《如何用git上传代码到github详细步骤》等等都有详细的介绍。按这些教程操作能正常的运用起Git,但对Git内的文件状态变化、分支管理、版本管理等等都没有更多的了解与应用。
2. Git基础
2.1 版本控制
- 直接记录快照,而非差异比较
Git和其他版本控制系统的主要差别在于,Git只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。其他版本控制系统如CVS、Subversion等每次记录有哪些文件作了更新,以及都更新了哪些行的内容。Git并不保存这些前后变化的差异数据。实际上,Git更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。了提高性能,若文件没有变化,Git不会再次保存,而只对上次保存的快照作一次链接。Git的工作方式如下图所示。
- 近乎所有操作都是本地执行
在Git中的绝大多数操作都只需要访问本地文件和资源,不用连网。Git在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。 - 时刻保持数据完整性
在保存到Git之前,所有数据都要进行内容的检验和(checksum)计算,并将此结果作为数据的唯一标识和索引。即,不可能在你修改了文件或目录后,Git还一无所知。如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git都能立即察觉。
Git使用SHA-1算法计算数据的检验和,通过对文件的内容或目录结构计算出一个SHA-a哈希值,作为指纹字符串。该字符串由40个十六进制字符。所有保存在Git数据库中的东西都是用此哈希值索引的,而不是靠文件名。 - 多数操作仅添加数据
常用的Git操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,才会使回退或重现历史版本变得困难重重。在Git里,一旦提交快照之后就完全不用担心丢失数据,要养成定期推送到其他仓库的习惯。
2.2 Git 基本工作原理
以下关于文件状态的概念非常重要,也是我整理此篇博客的重点之一。对于任何一个文件,在Git内都只有三种状态:已提交(committed)、已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示了某个文件,但还没有提交保存;已暂存表示已修改的文件放在下次提交时要保存的清单中。Git管理项目时,文件流转于三个工作区域:Git的工作目录,暂存区域,以及本地仓库。
每个项目都有一个Git目录(一般用git clone,就是.git的目录),它是Git用来保存元数据和对象数据库的地方,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。这些文件实际上都是从Git目录的压缩对象库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。
暂存区只不过是个简单的文件,一般都放在Git目录中,这个文件也叫做索引文件,标准说法还是暂存区域。
基本的Git工作流程如下
- 在工作目录中修改某些文件。
- 对修改后的文件进行快照,然后保存到暂存区域。
- 提交更新,将保存在暂存区域的文件快照永久转储到Git目录中。
2.3 取得Git仓库
在工作目录中初始化新仓库:git init。初始化后,在当前目录下会出现一个名为.git的目录,所有Git需要的数据和资源都存放在这个目录中。如果目前目录下有几个文件想要纳入版本控制,先用git add命令告诉Git开始对这些文件进行跟踪,然后git commit进行提交。
从现在仓库克隆:git clone。对于已存在的开源项目,使用git clone命令把该项目的Git仓库复制一份出来 。git clone命令会保存下载下来的所有版本记录,然后从中取出最新版本的文件拷贝。如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在git clone命令末尾指定新的名字。
3 记录每次更新到仓库——文件状态变化
工作目录下的所有文件都不外乎两种状态:已跟踪或未跟踪。已跟踪的文件是指本来就被纳入版本管理的文件,在上次快照中有它们的记录,工作一段时间后,它们的状态可能是未更新,已修改或者已放在暂存区。而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存区域。初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪文件,且状态为未修改。
在编辑过某些文件之后,Git将这些文件标为已修改。逐步将这些修改过的文件放到暂存区域,直到最后一次性提交所有这些暂存起来的文件,如此重复,如下图所示。 (这个图必须细细理清)
- 检查当前文件状态。要确定哪些文件处于什么状态,可以用git status命令。
- 跟踪新文件。使用命令git add开始跟踪一个新文件。git add 的潜台词就是把目标文件快照放入暂存区域,同时未曾跟踪过的文件标记为需要跟踪。
- 暂存已修改文件。git add 命令是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。
- 忽略某些文件。创建一个名为.gitignore文件,列出要忽略的文件模式。
- 查看已暂存和未暂存的更新。git status和git diff。