集中式 or 分布式
集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS)
缺点:最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。要是中央服务器的磁盘发生故障,碰巧没做备份,或者备份不够及时,就会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端偶然提取出来的保存在本地的某些快照数据就成了恢复数据的希望。但这样的话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
分布式版本控制系统( Distributed Version Control System,简称 DVCS )面世了,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份。更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。
特点
直接记录快照,而非差异比较
其他系统在每个版本中记录着各个文件的具体差异,而Git并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。Git 的工作方式就像下图所示。
文件的三种状态
工作区(Working Directory),暂存区和版本库
工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的 learngit 文件夹就是一个工作区
暂存区:英文叫 stage, 或 index。一般存放在 ".git 目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是Git的版本库。Git 版本库(repository)只是一个简单的数据库,其中包含所有用来维护与管理项目的修订版本和历史的信息。在Git中,跟大多数版本控制系统一样,一个版本库维护项目整个生命周期的完整副本。然而,不同于其他大多数 VCS,
Git 版本库不仅仅提供版本库中所有文件的完整副本,还提供版本库本身的副本。
Git 可使用四种主要的协议来传输数据
本地传输,SSH 协议,Git 协议和 HTTP 协议。
远程仓库通常只是一个裸仓库(bare repository) — 即一个没有当前工作目录的仓库。因为该仓库只是一个合作媒介,所以不需要从硬盘上取出最新版本的快照;仓库里存放的仅仅是 Git 的数据。简单地说,裸仓库就是你工作目录中 .git 子目录内的内容。
下面分别介绍一下哪些情形应该使用(或避免使用)这些协议。
值得注意的是,除了 HTTP 协议外,其他所有协议都要求在服务器端安装并运行 Git。
本地协议
最基本的就是本地协议(Local protocol),所谓的远程仓库在该协议中的表示,就是硬盘上的另一个目录。这常见于团队每一个成员都对一个共享的文件系统(例如 NFS)拥有访问权,或者比较少见的多人共用同一台电脑的情况。
/path/to/repo.git file:///oath/to/repo.git
虽然这两种格式基本上是相同的,但是两者之间有一个微妙而重要的区别。前者使用文件系统中的硬链接来直接共享当前版本库和远程版本库之间相同的对象;后者则复制对象,而不是直接共享它们。为了避免与共享版本库相关的问题,建议使用 file://的形式。
SSH (Secure Shell)协议-默认协议
Git 使用的传输协议中最常见的可能就是 SSH 了。这是因为大多数环境已经支持通过 SSH 对服务器的访问 — 即便还没有,架设起来也很容易。SSH 也是唯一一个同时支持读写操作的网络协议。另外两个网络协议(HTTP 和 Git)通常都是只读的,所以虽然二者对大多数人都可用,但执行写操作时还是需要 SSH。SSH 同时也是一个验证授权的网络协议;而因为其普遍性,一般架设和使用都很容易。
通过 SSH 克隆一个 Git 仓库,你可以像下面这样给出 ssh:// 的 URL:
$ git clone ssh://user@server/project.git
或者不指明某个协议 — 这时 Git 会默认使用 SSH:
$ git clone user@server:project.git
如果不指明用户,Git 会默认使用当前登录的用户名连接服务器。
- 优点
使用 SSH 的好处有很多。首先,如果你想拥有对网络仓库的写权限,基本上不可能不使用 SSH。其次,SSH 架设相对比较简单 — SSH 守护进程很常见,很多网络管理员都有一些使用经验,而且很多操作系统都自带了它或者相关的管理工具。再次,通过 SSH 进行访问是安全的 — 所有数据传输都是加密和授权的。最后,和 Git 及本地协议一样,SSH 也很高效,会在传输之前尽可能压缩数据。
- 缺点
SSH 的限制在于你不能通过它实现仓库的匿名访问。即使仅为读取数据,人们也必须在能通过 SSH 访问主机的前提下才能访问仓库,这使得 SSH 不利于开源的项目。如果你仅仅在公司网络里使用,SSH 可能是你唯一需要使用的协议。如果想允许对项目的匿名只读访问,那么除了为自己推送而架设 SSH 协议之外,还需要支持其他协议以便他人访问读取
Git 协议
这是一个包含在 Git 软件包中的特殊守护进程; 它会监听一个提供类似于 SSH 服务的特定端口(9418),而无需任何授权。打算支持 Git 协议的仓库,需要先创建 git-export-daemon-ok 文件 — 它是协议进程提供仓库服务的必要条件 — 但除此之外该服务没有什么安全措施。要么所有人都能克隆 Git 仓库,要么谁也不能。这也意味着该协议通常不能用来进行推送。你可以允许推送操作;然而由于没有授权机制,一旦允许该操作,网络上任何一个知道项目 URL 的人将都有推送权限。不用说,这是十分罕见的情况。
- 优点
Git 协议是现存最快的传输协议。如果你在提供一个有很大访问量的公共项目,或者一个不需要对读操作进行授权的庞大项目,架设一个 Git 守护进程来供应仓库是个不错的选择。它使用与 SSH 协议相同的数据传输机制,但省去了加密和授权的开销。
- 缺点
Git 协议消极的一面是缺少授权机制。用 Git 协议作为访问项目的唯一方法通常是不可取的。一般的做法是,同时提供 SSH 接口,让几个开发者拥有推送(写)权限,其他人通过 git:// 拥有只读权限。Git 协议可能也是最难架设的协议。它要求有单独的守护进程,需要定制 — 我们将在本章的 “Gitosis” 一节详细介绍它的架设 — 需要设定 xinetd 或类似的程序,而这些工作就没那么轻松了。该协议还要求防火墙开放 9418 端口,而企业级防火墙一般不允许对这个非标准端口的访问。大型企业级防火墙通常会封锁这个少见的端口。
HTTP/ HTTPS 协议
HTTP 或 HTTPS 协议的优美之处在于架设的简便性。基本上,只需要把 Git 的裸仓库文件放在 HTTP 的根目录下,配置一个特定的 post-update 挂钩(hook)就可以搞定。此后,每个能访问 Git 仓库所在服务器上 web 服务的人都可以进行克隆操作。
在 Git 版本1.6.6中, HTTP协议得到显著改善,与 Git 原生协议效率基本相同。
推荐 Git 学习网站
Git教程 - 廖雪峰的官方网站
https://www.liaoxuefeng.com/wiki/896043488029600
Learn Git Branching
https://learngitbranching.js.org/?locale=zh_CN
Git - Book
https://git-scm.com/book/zh/v2
Pro Git(中文版)
http://git.oschina.net/progit/index.html