前言
最近温习 Git 的相关知识,进行系统性的学习,将相关知识总结记录下来,跟大家分享一下。主要参考资料为 《Pro Git》。
1. 版本控制
1.1 什么是版本控制?
无论是编写代码还是编辑文档,用户都需要一种机制来追踪修改历史,以便在错误操作时回退到之前的版本,这种机制就是版本控制。
版本控制用来记录和管理一个或多个文件内容变化,以便将来查阅特定版本修订情况。
你可以对任何类型文件进行版本控制。版本控制系统(VCS,Version Control Syste),可以将某个文件回溯到之前的状态,甚至将某个项目回退到某个时间点的状态。
1.2 版本控制系统的目标
版本控制系统的目标:
- 允许开发者同时工作。
- 不会重写每个人的改变。
- 维持每个版本的全部历史。
2. 版本控制系统的分类
2.1 本地版本控制系统
核心模型:复制整个项目目录,在本地计算机上保存文件的不同版本。
- 优点:简单。
- 缺点:难以协同工作,无法撤销恢复。
针对无法撤销修复问题,大多采用某种简单数据库来记录文件历次更新差异。
如 RCS(Revision Control System),它的工作原理基本上就是保存并管理文件补丁(patch)。
文件补丁是一种特定格式的文本文件,记录着对应文件修订前后的内容差异。根据每次修订后的补丁,rcs 可以通过不断打补丁,计算出各个版本的文件内容。
文件补丁是修改文件本身的某个数据,达到一劳永逸的效果,与内存补丁不同的是:内存补丁是在程序运行时对其数据修改,可以理解为动态,而文件补丁是静态。
文件补丁是直接修改可执行文件的二进制数据,文件补丁实施起来很简单。
如果数据是加密的,你就要对其算法进行研究,这时候内存补丁是很好的选择。
2.2 集中式版本控制系统
核心模型:集中化的版本控制系统(Centralized Version Control System,CVCS),诸如 CVC,Subversion 等,都有一个集中管理的服务器,保存所有文件的修订版本,不同系统的开发者之间可以协同工作。
- 优点:便于协同工作,管理员易于管理。
- 缺点:中央服务器的单点故障。
2.3 分布式版本控制系统
核心模型:分布式版本控制系统(Distributed Version Control System,DVCS)。在这类系统中,像 Git 等,除了中央仓库之外,还有本地仓库。客户端并不仅仅提取最新版本的文件快照,而是把整个仓库完整的镜像下来。服务器故障可以用镜像恢复。每一次提取操作,实际上都是一次对代码仓库的完整备份。
允许多个开发者在各自独立的代码仓库中工作,并能够容易地合并或提交各自的修改。在分布式版本控制系统中,并没有一个中央服务器来维护所有版本的历史。相反,每个开发者都拥有一个包含全部历史变更的本地仓库的副本。
分布式版本控制系统中本地仓库是有版本管理功能的,离线时,也可以做提交、回滚等操作。而集中式版本控制系统脱离服务器做不了这些操作。
- 优点:多数情况为本地操作,速度较集中式更快,没有联网也可以进行提交代码、查看代码历史等操作。
- 缺点:每个机器都有一个本地仓库,初始化项目相对较耗时,占用内存相对较高。。
3. Git 起步
3.1 Git 概述
Git 是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。
使用 Git 时,所有人的电脑中的东西都是一样的。使用 Git ,有个中心服务器,仅仅是为了方便交换大家的修改。这个服务器的地位和我们每个人的 PC 是一样的。可以将它当做一个开发者的 pc ,目的为了代码间交流容易便捷。没有它大家一样可以工作,只不过不同 PC 之间交换修改不方便而已。
3.2 Git 特点
3.2.1 直接记录快照
Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。Git 不保存前后变化的差异数据,而是存储了项目在某个时间点的完整状态。
实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每当你在 Git 中提交修改,Git 会纵览一遍所有文件的指纹信息,并为当时的全部文件制作一个快照,这个快照包含了提交时刻每个文件的状态。然后会保存一个指向这次快照的索引。若文件没有变化,为了提高性能,Git 只会对上次保存的快照作一链接。
文件指纹是一个用于标识文件内容的唯一标识符。它是根据文件的内容计算出来的固定长度的字符串。文件指纹可以用于数据完整性校验、文件去重、数据比对等场景。Git 会计算每个文件的哈希值,这个哈希值是通过文件的内容计算得出的,可以看作是文件的唯一标识符或指纹。如果某个文件自上次提交以来没有发生变化,Git 就不会再次保存这个文件的内容,而是会创建一个指向之前保存的快照的链接。这样做的目的是为了节省空间和提高性能,因为不需要重复存储相同内容的文件。
这种设计使得Git在处理大型项目和大量历史数据时非常高效,因为它避免了重复计算和存储变更差异的开销。同时,这也使得Git在处理合并冲突时更加直观和强大,因为它可以基于完整的文件快照来进行合并操作。
3.2.2 离线操作
在 Git 中的绝大多数操作都只需要访问本地文件和资源,不需联网,本地执行,速度快。
如果用 CVCS 的话,差不多所有操作都需要连接网络。
3.2.3 保持数据完整性
在保存到 Git 之前,所有数据都要进行内容的校验和计算,并将此结果作为数据(每个文件或目录)的唯一标识和索引,保证数据的准确性和一致性。
Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成。
Git 的工作完全依赖于这类指纹字串,Git 内部的引用、存储和检索机制都是基于这些哈希值的。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。
3.2.4 文件的三种状态(重中之重)
Git 内部只有三种状态:已修改(modified)、已暂存(staged) 和 已提交(committed) 。
- modified : 已修改,表示修改了某个文件,但还没有提交保存。
- staged: 已暂存,表示把已修改的文件放在下次提交时要保存的清单中。
- committed: 已提交,表示该文件已经被安全地保存在本地数据库中了。
Git目录:如果使用 git clone 克隆一个项目,Git 目录指的就是 .git 目录,是 Git 用来保存元数据和对象数据库的地方。每次克隆镜像仓库时,实际就是拷贝的这个目录里的数据。
工作目录: 从项目中取出某个版本的所有文件和目录,用以开始后续工作的目录。这些文件实际上都是从 Git 目录中的压缩对象数据库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。
暂存区域: 暂存区域只不过是个简单的文件,一般都放在 Git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。
Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。
基本的 Git 工作流程:
- 在工作目录中修改某些文件。
- 对修改后的文件进行快照,然后保存到暂存区域。
- 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。
4. 附录 —— Git 命令大全
git 命令大全,不断更新:
# 用户信息配置
$git config --global user.name "zhang"
$git config --global user.email zhang@example.com
# 查看配置信息
$git config --list
$git config --global user.name
# 在工作目录初始化新仓库
$git init
# 从现有仓库克隆
$git clone [url]
# 将项目添加至远程仓库
$git remote add [shortname] [url]
# 查看文件状态
$git status
# 跟踪文件、将文件添加到暂存区
$git add
# 提交命令,进入文本编辑器方式
$git commit
# 提交命令,简化
$git commit -m ""
# 查看提交历史
$git log