分支和合并
Git 跟其他版本控制系统***的优势就在于其高级的分支模型。
Git 允许而且 鼓励 你在本地使用多个完全独立的分支。这些分支的创建,合并和删除几乎都可以在几秒内完成。
这意味着你可以轻松的做如下操作:
- 无痛的上下文切换 创建分支试验一个想法,提交几次,切回你原来分支的状态,应用一个改动 patch,切回你原来正在试验的状态,将刚才应用的 patch 合并过来。
- 基于角色的代码支线 你可能会有一个分支仅仅包含那些只存在于生产环境上的代码,另外有一个独立的分支用以合并测试环境代码,还有若干个更小一些的分支用于日常开发工作
- 基于特性的工作流 为每一个新的特性创建新的分支,你可以方便平滑的在这些分支之间无缝切换,当这些特性的改动完成的时候,你可以将其合并入主分支,并把特性分支删掉。
- 任意试验 创建一个分支专门用来试验,当觉得试验不理想的时候,直接删除掉即可,放弃掉之前的试验内容。这时候不会有任何其他人察觉到这个试验(甚至在这期间你还可以推送其他不相关的分支)
尤其是当你推送至远程仓库的时候,你不必推送所有分支,你可以选择只推送少数你愿意分享的分支,当然如果你愿意,也可以推送所有分支。这一点倾向于让开发者在试验很多新的想法的时候免除发布自己的未成熟的试验计划的顾虑。
当然,也有一些其他的系统可以部分实现上述的功能和优势,只是具体的执行会变的困难和容易出错。Git 让这些工作变得难以置信的简单,它在开发者学习其使用的同时就改变了开发者的工作模式。
轻量和快速
Git 很快。Git 基本上所有的操作都在本地执行,这对于那些必须跟服务器通信的集中式系统是一个巨大的速度优势。
Git 一开始是为了管理 Linux Kernel 的源代码设计的,这意味着他从***天诞生就拥有了处理大型仓库的高效优势。Git 使用 C 语言编写,减轻了使用更高级别编程语言的 Runtime 带来的性能损耗。Git 最开始的两个重要的设计目标就是性能和速度。
压力测试
让我们看一下与 SVN (一个通用的集中式存储版本控制系统,跟 CVS 和 Perforce 很像)相比下的常规操作的性能测试指标。这里指标是值越小,速度越快。
为了测试,我们在亚马逊的 AWS 的同样的可用区上新建了两个 Large 类型的计算服务器实例。每一个计算实例上都安装 Git 和 SVN。 我们把 Ruby 的源代码仓库拷贝到了 Git 和 SVN 的计算服务器示例上,两者都执行通用的操作。
在有些情况下,两者的命令和实际效果并不能完全对应起来。在这里,我们在常用的操作中选择相似效果的匹配情况。例如,对于“提交”的测试,在 Git 中我们也是计算 Push 的时间的。然而在大多数情况下,你可能实际上并不会在提交后马上就推送到服务器上,这在 SVN 上是不可分割的操作。
下面表格中所有的时间单位都是秒。
操作 | 描述 | Git | SVN | 性能倍数 |
---|---|---|---|---|
提交文件 (A) | Add, commit and push 113 modified files (2164+, 2259-) | 0.64 | 2.60 | 4x |
提交图片 (B) | Add, commit and push 1000 1k images | 1.53 | 24.70 | 16x |
对比当前变动 | Diff 187 changed files (1664+, 4859-) against last commit | 0.25 | 1.09 | 4x |
对比最近的变动 | Diff against 4 commits back (269 changed/3609+,6898-) | 0.25 | 3.99 | 16x |
对比标签 | Diff two tags against each other (v1.9.1.0/v1.9.3.0 ) | 1.17 | 83.57 | 71x |
提交历史 (50) | Log of the last 50 commits (19k of output) | 0.01 | 0.38 | 31x |
提交历史 (全部) | Log of all commits (26,056 commits – 9.4M of output) | 0.52 | 169.20 | 325x |
提交历史 (文件) | Log of the history of a single file (array.c – 483 revs) | 0.60 | 82.84 | 138x |
更新 | Pull of Commit A scenario (113 files changed, 2164+, 2259-) | 0.90 | 2.82 | 3x |
Blame | Line annotation of a single file (array.c) | 1.91 | 3.04 | 1x |
你需要注意的是,这已经是 SVN ***的运行场景了 — 一个没有任何负载的服务器,客户端和服务器之间的网络带宽达到 80MB/s。上文中的所有指标在受网络波动,或者在一个更差的网络环境下 SVN 的表现都更差,然而 Git 这边几乎所有的指标都不受影响。
很明显,在这些最常用的版本控制工具的操作中,甚至是在SVN 的理想使用环境下,**Git 在很多方面都大幅领先**。
一个 Git 比 SVN 慢的地方是初始化 clone 仓库。在这种情况下,Git 是在下载整个仓库历史而不是仅仅是***版本的代码。上文中的表格所示,仅仅执行一次的操作影响并不是很大。
操作 | 描述 | Git(Shallow Clone) | Git | SVN |
---|---|---|---|---|
Clone | Git Clone 以及 shallow clone(浅 clone) vs SVN checkout | 21.0 | 107.5 | 14.0 |
大小(M) | 客户端在 clone/checkout 后的文件大小 (以 M 为单位) | 181.0 | 132.0 |
另外一个有趣的点是,Git 和 SVN 在 Clone 或者 Checkout 到本地后的文件大小几乎差别不大,要知道对于 Git 来说,本地可是包含了整个项目历史。这也展示了 Git 在文件压缩和存储上的超高效率。
分布式
Git 最棒的特性之一就是分布式。这意味着,你要 clone 整个仓库而不是仅仅 checkout 分支的***头部版本。
多个备份
在日常的使用场景中 Git 往往有多个备份。这意味着就算在使用一个中央存储式的工作流,每一个用户都在本地有一个服务器上的完整备份。这里的任意一个版本都可以在服务器端数据损坏或者丢失的时候推送回服务器以挽救损失。事实上,只要你的仓库不是只有一个 copy,Git 就不会存在单点问题。
任意工作流
因为 Git 拥有分布式特性和极好的分支系统,你可以在此基础上轻松实现大量的工作流模型。
Subversion(SVN) 风格工作流
集中式存储的工作流非常常见,特别是对于那些从传统的集中式代码版本管理系统转过来使用 Git 的人。Git 一样可以提供这种工作形式:每次 Push 必须要更新到远程仓库的***版本。所以说大家还是像以前一样使用集中式存储的工作流往同一个服务器上 Push 代码依然没问题。
整合管理者工作流
另外一个常见的 Git 工作流是整合工作流。主要的仓库有一个单一的开发者维护(维护者)。其他若干开发者从这个仓库 clone,然后推送到他们自己的完全独立的仓库里面,***请求维护者从主要仓库 Pull 那些他们在各自的仓库里面的改动。这种形式往往在 GitHub 上以开源的形式进行协作。
维护者和负责人工作流
对于一些更为复杂的项目来讲,像 Linux 内核这样的开发工作流也是很有效的。在这个模型中,负责人(lieutenants)负责整个项目的一些特定的子系统,他们合并所有跟那个子系统关联的变动。另外一个维护者(dictator,字面理解:独裁者)只能从他管辖的负责人这里获取变更,并将这些变更推送到主要仓库。然后所有人都从这个仓库获取更新。
数据校验
Git 的数据模型确保了项目内的每一个字节,每一个 bit 的一致性。提交的每一个文件都会使用校验和计算摘要,检出的时候也使用这个摘要值。没有任何可能会出现从仓库中获取的内容跟你存储的内容有任何差异。
在不改变 ID(校验和)的情况下也不可能出现改变任何文件,日期,提交说明或者任何其他在 Git 仓库中的数据。这就意味着,如果你有一个 commit ID,你不但可以确定这个版本的代码跟他提交的时候是一模一样的,而且这个版本之前的历史也没有发生任何改变。
大多数中央存储的版本控制系统默认不提供这样的校验整合。
暂存区域
不像其他系统, Git 有一个概念叫做“暂存区域”或者“index”。这是一个在提交执行之前的临时的区域可以用来格式化和审阅改动内容的。
一个 Git 优于其他系统的功能是我们可以快速的暂存一些改动的文件,在工作目录中只提交部分改动的文件,或者文件改动的部分内容,以及在提交的时候在命令行里列出改动的文件列表。
暂存区域允许你仅仅暂存部分的文件改动,在你意识到你忘了提交其中一个文件之前,对文件进行两个逻辑上不相关的修改的日子已经一去不复返了。现在你可以仅仅暂存你当前提交需要改动的文件,其他的改动在下次提交再暂存。这个特性可以扩展到对文件进行的任何更改。
当然,Git 也允许你忽略掉暂存区域这个过程,你可以轻松的在 commit 命令后面添加 ‘-a’ 选项来直接将所有改动提交。Git 会自动帮你先暂存到暂存区域,再执行提交。
免费和开源
Git 是一个使用 GNU GPL2.0 协议的开源软件。Git 选择 GPLv2 来确保你可以自由的分享和改造自由软件,而且能确保使用它的任何用户都是自由免费的。