首页 > 技术文章 > Git自学(3)-- Git 原理及基本概念详解

ay2021 2021-07-21 10:14 原文

0、写在前面

经过Git自学(1)-- Win10 安装 Git 详细教程(超详细纯小白教程)
Git自学(2)-- Git安装后首次配置与第一次使用Git和Github管理自己的代码(超详细纯小白图文教程)的实际操作后,对Git和Github的使用流程有了初步的了解,下面首先深入了解下Git的原理,然后对Git常用命令进行介绍。

1、Git是什么?

Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

2、版本控制简史

2.1 什么是“版本控制”?

什么是“版本控制”?我为什么要关心它呢? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。

如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。 有了它你就可以将选定的文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。

使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。 但额外增加的工作量却微乎其微。

2.2 本地版本控制系统

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。

为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
请添加图片描述
其中最流行的一种叫做 RCS,现今许多计算机系统上都还看得到它的踪影。 RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。

2.3 集中化的版本控制系统

接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。 这类系统,诸如 CVS、Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。 多年以来,这已成为版本控制系统的标准做法。
请添加图片描述

这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

这么做最显而易见的缺点是中央服务器的单点故障。 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。

并不是说服务器故障了就没有办法写代码了,只是在服务器故障的情况下,编写的代码是没有办法得到保障的.试想 svn 中央服务器挂机一天.你还拼命写了一天代码,其中 12 点之前的代码都是高质量可靠的,而且有很多闪光点.而 12点之后的代码由于你想尝试一个比较大胆的想法,将代码改的面目全非了.这样下来你 12 点之前做的工作也都白费了,有记录的版本只能是 svn 服务器挂掉时保存的版本!

如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。 本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端偶然提取出来的保存在本地的某些快照数据就成了恢复数据的希望。但这样的 话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。只要 整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

2.4 分布式版本控制系统

于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
请添加图片描述

更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

请添加图片描述

分布式的版本控制系统在管理项目时,存放的不是项目版本与版本之间的差异。它存的是索引(所需磁盘空间很少,所以每个客户端都可以放下整个项目的历史记录)。
分布式的版本控制系统出现之后,解决了集中式版本控制系统的缺陷:

  1. 断网的情况下也可以进行开发(因为版本控制是在本地进行的)。
  2. 使用 github 进行团队协作,哪怕 github 挂了,每个客户端保存的也都是整个完整的项目(包含历史记录的!!!)。

在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。(近乎所有操作都是本地执行) 如果你习惯于所有操作都有网络延时开销的集中式版本控制系统,Git 在这方面会让你感到速度之神赐给了 Git 超凡的能量。 因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。

举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来——它只需直接从本地数据库中读取。 你能立即看到项目历史。如果你想查看当前版本与一个月前的版本之间引入的修改, Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。

这也意味着你在离线或者没有 VPN 时,几乎可以进行任何操作。 如你在飞机或火车上想做些工作,就能愉快地提交(到你的 本地 副本,还记得吗?), 直到有网络连接时再上传。

3、Git 简史

同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。

Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。

到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:

  • 速度
  • 简单的设计
  • 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
  • 完全分布式
  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统,可以应付各种复杂的项目开发需求。

4、Git 三种状态:committed、modified 和 staged

Git 有三种状态,你的文件可能处于其中之一: 已提交(committed)已修改(modified)已暂存(staged)

  1. 已修改表示修改了文件,但还没保存到数据库中。
  2. 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  3. 已提交表示数据已经安全地保存在本地数据库中。

如果 版本库(.git目录) 中保存着特定版本的文件,就属于 已提交 状态。
如果文件已修改并放入暂存区,就属于 已暂存 状态。
如果自上次检出后,作了修改但还没有添加到暂存区域,就是 已修改 状态。

5、Git 工作区、暂存区和版本库

在这里插入图片描述

这会让我们的 Git 项目拥有三个阶段:工作区暂存区以及 版本库(.git目录)。

  1. 工作区:工作区是对项目的某个版本独立提取出来的内容。 这些从 Git
    仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。就是你在电脑里能看到的目录。
  2. 暂存区:英文叫 stage 或 index。暂存区是一个文件,保存了下次将要提交的文件列表信息,一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
  3. 版本库(本地仓库)隐藏目录 .git,这个不算工作区,而是 Git 的版本库。Git 版本库是 Git 用来保存项目的元数据和对象数据库的地方。这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。

在这里插入图片描述

  • 图中左侧为工作区,右侧为版本库(本地仓库)。在版本库中标记为 "index" 的区域是暂存区(stage/index),标记为 "master" 的是master 分支所代表的目录树。
  • 图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用master 来替换。
  • 图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
  • 当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
  • 当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
  • 当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
  • 当执行 git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。
  • 当执行 git checkout . 或者 git checkout -- <file>命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。
  • 当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未添加的改动,也会清除暂存区中未提交的改动。

6、Git 基本操作图

Git 最常用的 6 个命令:git clonegit pushgit addgit commitgit checkoutgit pull

在这里插入图片描述

  • workspace:工作区
  • staging area:暂存区/缓存区
  • local repository:版本库或本地仓库
  • remote repository:远程仓库

具体命令详解待整理成系统的实操后下次写。

在这里插入图片描述

推荐阅读