毕业论文
您现在的位置: 版本控制 >> 版本控制市场 >> 正文 >> 正文

程序员必备技能之Git的体系结构与历史

来源:版本控制 时间:2025/5/19
十几年前,Linux之父LinusTorvalds在个人休假时,发现自己掌控下的Linux内核在开发过程中遇到了一些问题,于是郁闷无比,经过多天的琢磨与实践之后研发出一款小工具——Git,以望帮助更多的开发者有效、高速地处理从很小到非常庞大的项目版本管理。万万没想到,经过多年的发展之后,彼时名不经传的Git如今早已占据行业的主导地位,而这其中到底经历了些什么?作者

WillHayJr.译者

梁蕊责编

屠敏截至年,全球知名的IT技术问答网站StackOverflow调查的开发人员中,将近90%的人表示更喜欢使用Git进行版本控制。根据调查,Git在其他所有分布式版本控制系统中占主导地位,并且从年开始使用率几乎增长了20%。然而,Git并不总是像这样普及。让我们一起看看它上升到大众化的历程。早期历史Git诞生于Linux内核社区对可用的VCSs(版本控制系统)的挫败感。Linux内核的发展在当时是相当不寻常的:项目中有大量的贡献者而且贡献者的参与程度和对代码知识库的了解有很大的差异。由于Linux内核不寻常的发展状况,开发人员很难找到适合他们需求的VCSs(版本控制系统)。于是他们选择了BitKeeper和并发修订系统(CVS),每个系统有一组核心开发人员去负责管理内核的开发。BitKeeper提供分布式版本控制,而CVS是一个客户端-服务端版本控制系统,它可以让开发人员“签出”项目的副本,进行更改,然后将他们的改变“签入”到服务端。在年初期,BitKeeper的版权持有人LarryMcVoy宣布撤销允许免费使用BitKeeper软件的许可。他声称,正在创建与BitKeeper反向交互软件的澳大利亚程序设计师AndrewTridgell反向设计了BitKeeper的源代码,这样违背了它的许可。许多依赖BitKeeper免费软件去开发Linux内核的Linux核心开发者现在已经无法继续使用它了。Linux社区与BitKeeper的关系已经开始有了冲突,但是他们希望在离开BitKeeper之前有一个可行的选择。Linux内核主要的开发人员LinusTorvalds在看到没有其他免费的选择可以满足他们的需求之后就开始开发一个新的VCS。在发送到内核邮件列表的电子邮件中,Linus表示了他对BitKeeper有多么满意和BitKeeper为Linux内核开发做了什么,主要是它帮助整个团队更细粒度的保留了一些更改和更改追踪集的视图。值得注意的是,虽然BitKeeper没有成功,但它依然在改进内核开发方式上非常有帮助。早期发展为了向团队提供BitKeeper的替代品,Linus概述了一些新版本控制系统的某些设计标准。他想要保持BitKeeper提供给团队的一些好处,同时进行一些改进。他主要强调了三个主要特征:防止内容腐败的保障措施、高可用性和分布式开发工作流。Linus还强调了补丁不应该超过3秒,引用源控制管理系统,该系统需要花费30秒来推送补丁并且更新相关的元数据。对于从事开发Linux内核的名开发人员来说,这样的一个系统,显然不能很好的扩展。尽管BitKeeper对Git的创建有早期的影响,但Git比BitKeeper允许更多的分布式和本地工作流。项目协作者可以在存储库离线工作,增量提交,确定何时发布他们的工作,选择共享哪些更改,并将他们的更改推送到不同的分支。架构概述一个版本控制系统通常有三个核心功能,所有的这些功能都被Linus内置在Git中。它必须能够存储内容、追踪对内容所做的更改(所有的历史纪录,包括合并元数据)、与项目协作者选择分发内容和提交历史记录。Git使用了有向无环图(DAG)进行内容存储以及提交和合并历史记录。DAG是一个有着有限数量的顶点和边(顶点之间的连接),没有包含循环的有向图(是非周期性的)。非循环意味着没有办法从A节点到B节点,并通过任意数量的边返回到A节点。DAG也必须有拓扑排序,这意味着在一个序列中,所有的顶点都有直接从最开始的节点指向最后节点的边(如下图中箭头从左上角指向右下角所示)。Git还将这种有向无环图结构应用在存储内容上。Git实质上是一个可寻址的文件系统,它由构成层次结构的对象组成,这些层次结构反映了内容的文件系统树。Git有三种主要的原始内容,它用来表示存储库存储的内容:树、blob和提交。所有的内容实质上都作为树或blob对象存储。Blob是存储在存储库中的文件,树对象引用了其他子树或者blob。你可以认为blob是存储内容的文件,而树就像是目录。在另一方面,提交对象有三个主要的属性,它指向了在提交时代表项目顶级快照水平的文件系统树、它还包含对它之前提交的引用,提交作者的字段和可选的提交信息。所有这些对象基元都有40位的SHA哈希。两个相同的对象将会有相同的哈希值,不同的对象将会有不同的哈希值。通过使用SHA哈希作为参考标识,Git能够有效的计算差异。为了防止数据损坏,可以重新计算一个对象的哈希值,以便轻易的识别出损坏或丢失的数据。Git还使用了有向无环图来追踪内容更改的历史记录。如上所述,每一个提交对象都包含它祖先的元数据,也就是说一次提交可以有任意数量的父提交。Git使用有向无环图的特性来存储内容、保留历史追踪记录和合并历史记录,这样允许它保留完整的分支功能,因为文件的历史记录将其目录结构一直链接到根目录和提交对象。分支策略当我们将“feature7”分支合并到master分支时,Git会执行“fast-forward”合并策略,向前移动主分支指针。只有将当前“feature7”分支的提交历史记录要合并到master分支的最新提交时,才会使用“fast-forward”合并。当你所在分支的提交并不是你正在合并的分支的直接祖先时,Git使用不同的合并策略,这意味着你的开发历史不同。在这种情况下,Git使用“递归”策略并执行三向合并。Git创建了文件状态的新快照和指向新快照的分支提交对象。此时这个合并提交对象有两个父类,指向两个分支的头部的提交对象被合并在一起。Git使用非线性内容存储策略和提交历史记录的系统,可以将项目的两个分支无缝的合并在一起。分布和初始化Git使用分布式模型处理项目协作者之间的内容和历史分布,用户可以离线工作并在本地存储库上进行提交。每个协作者都有一个Git存储库的副本,他们可以离线工作,进行更改,提交更改,并且从远程存储库中提取新的更改以保持本地副本最新。当协作者准备好共享他们的更改时,他们可以将这些更改推送到可公开访问的存储库,供其他协作者访问。一旦公共存储库验证了这个提交可以应用于被推送到的分支,就会为公共存储库创建在本地存储库中创建和存储的相同对象,并更新该存储库以供所有协作者访问。要初始化本地Git存储库,请运行Gitinit命令。这将在本地文件系统上创建一个新初始化的存储库,在当前工作目录中创建一个.git目录。.git目录是根工作目录的子目录,并作为实际的本地存储库,包含各种配置文件,对象数据库,分支的引用指针以及可在项目生命周期的各个点运行的其他脚本。一旦你对文件进行了修改,就会创建另一个重要文件,Gitindex,位于.git/index下。Gitindex文件是工作目录和本地存储库之间的暂存区域,在要提交的一个或多个文件中暂存特定的更改。值得注意的缺点Git使用工具包编写的设计理念与Linux社区中使用和构建的命令行工具相同。虽然工具包设计为用户提供了Git大量功能更细粒度,更低级别的访问,但由于大量的命令可能对许多不熟悉命令行工具的人或其他VCS使用者不直观,所以新用户的学习曲线很陡峭。Git还缺乏链接和构建到其他服务和应用的能力。许多在Git上构建或正在构建工具的应用程序开发者抱怨缺乏可连接的库。Git的二进制文件是不可重入的,这意味着它不能在执行过程中被中断,之后安全地再次被调用。这会强制一些使用该二进制文件的应用程序或Web服务执行并调用该二进制文件后,在再次调用它之前等待其完全执行,影响应用程序的速度。有几个项目正在努力弥补这种缺乏可连接库的情况,其中最著名的是libgit2,一个Git的跨平台可连接库实现。Git的另一些问题是它无法处理大文件或者大量的文件。如果你的项目包含很多非文本文件,比如图像,那么经常地更新Git将变得非常慢,使得最大的实际存储库大小只有几GB。最后Git的设计几乎完全符合了Linus和Linux团队所寻找的需求。它满足了Linus描述的VCS的每个核心需求,并且在使用时尽可能优雅且简单地做到尽可能高效。虽然Git存在一些小问题,但它的设计非常好,并且将在未来的许多年内继续成为VCS的首选。原文:

转载请注明:http://www.0431gb208.com/sjszlff/9474.html

  • 上一篇文章:
  • 下一篇文章: