Git 工作原理

2020-12-25 From 程序之心 By 丁仪
<p> Git 是最先进的开源分布式版本控制系统,最初由 Linus 为解决 Linux 的代码管理而发明。版本控制系统(Version Control System, VCS)有很多实现,比如早期的 CVS,主要用于控制、协调文件的一致性。目前使用最多的主要是 SVN 和 Git。 p>

SVN vs Git

<p> SVN 是 subversion 的缩写,使用一个中央版本库来进行集中控制并记录文件变更历史支持多个分支并行开发,采用了客服端/服务模式,文件的各个版本、分支都储存在服务器上。SVN 采用的是 Copy-Modify-Merge(拷贝-修改-合并)模式对文件进行管理p> <p> 在 Copy-Modify-Merge 模式下,当用户修改文件时,先将服务器文件 update 到本地,然后在本地对副本进行修改修改完成后,再将副本 commit 到服务器。如果 commit 前其他用户修改了文件,则文件版本号发生冲突,需要先 update 到本地进行合并,才能继续 commit。 p> <p> 与 SVN 不同,Git 是分布式版本管理系统。从 Git 服务器 clone 文件到本地,成为本地仓库,包含了全部文件和变更记录,与之相对的服务器仓库被称为远程仓库。当用户修改文件时,直接对本地副本进行修改修改完成后把改动 commit 到本地仓库,需要同步时再 push 改动到远程仓库。由于使用本地仓库,Git 减少了很多网络开销,使得性能比 SVN 有极大的提升,即使在断网情况下也能继续工作p> <p> 大多数 VCS 应用是基于增量的版本控制,即存储了文件信息和对每个文件所做的更改。而 Git 是基于快照的版本控制,在每个版本都记下文件的快照,并存储对快照的引用。为了提高效率,如果文件没有更改,Git 不会再次存储该文件,而只是指向已经存储的先前相同文件的链接。因此,本质上,Git 是一套内容寻址(content-addressable)文件系统p> <p> p>

Git 仓库

<p> Git 中的文件和操作都以 Git 对象来保存。Git对象分为 BLOB、tree 和 commit 三种类型,BLOB对象可以存储几乎所有的文件类型,tree对象是用来组织BLOB对象的一种数据类型,commit对象表示每一次的提交操作。commit对象存储了对tree对象引用,tree对象存储了对BLOB对象引用进行版本控制所需要的所有数据都在 .git 文件夹中,如图所示。 p> <p>


p> <p> .git 文件夹核心文件包括:config文件、objects文件夹、HEAD文件、index文件以及refs文件夹。 p>

  • config文件:主要记录针对该项目的一些配置信息,例如是否以bare方式初始化、remote的信息等;
  • objects文件夹:主要包含git对象,保存在以其sha-1值的前两位为子文件夹、后38位为文件名的文件中。为了节省磁盘空间,会定期对Git对象进行压缩和打包,并存储在pack文件夹中,相关的查找信息存储在info文件夹中;
  • refs文件夹:存储指向分支的 commit 对象的指针。其中heads文件夹存储本地每一个分支最近一次commit的sha-1值,每个分支一个文件;remotes文件夹记录最后一次推送到远程仓库的每个分支的值;
  • HEAD文件:存储当前分支在 refs 中的信息,如ref: refs/heads/master;
  • index文件:存储暂存区域(staging area)的信息内容包括文件的时间戳、文件名、sha-1值等;

Git 文件状态

<p> Git 的文件有已提交(committed)、已修改(modified) 和已暂存(staged)三种状态p> <p> 与之对应,Git 中还有工作区(Working Directory)和暂存区(Staging Area)。工作区存放从仓库 checkout 出来的文件,用户可以进行修改。下次将要 commit 的文件信息存储在暂存区。commit 操作实际上是从暂存区 commit 到本地仓库中。 p> <p> p>

Git 命令

<p> 在 Git 中,包括 porcelain 命令(高层命令)和 plumbing 命令(底层命令)两种类型。按照最初的设计,Git 是一个工具集,底层命令用于以 UNIX 风格使用或由脚本调用。高层命令用于方便用户进行操作。我们平时使用的都是高层命令,内部实际上封装了底层命令调用p> <p> Git 的常用命令如图所示。首次从远程仓库创建本地仓库使用 clone 命令使用 checkout 命令从本地仓库切换分支到工作区;增加文件后,使用 add 命令提交变更到暂存区;修改完成后,使用 commit 命令提交变更到本地仓库;需要同步时,使用 push 命令推送变更到远程仓库;远程仓库变化后,使用 pull 命令拉取变更到工作区。以上这些命令都是高层命令p> <p>


p> <p> 当我们执行 git add 高层命令时,内部实际上封装了 git hash-object 和 git update-index 两个底层命令。其中 git hash-object 将需要暂存的文件进行 key-value 转化生成 git 对象存储到 objects 文件夹中,获取了这些文件的 key,git update-index 命令把这些文件存储到暂存区。 p> <p> 当我们执行 git commit 高层命令时,内部实际上封装了 git commit-tree key –p key2 底层命令。该命令创建 commit 对象,并挂载到前继对象之后。 p>

本文来源:程序之心,转载请注明出处!

本文地址:https://chengxuzhixin.com/blog/article/200064.html;jsessionid=46115CC4478500EE0B6F56407F064222

发表感想

© 2016 - 2022 chengxuzhixin.com All Rights Reserved.

浙ICP备2021034854号-1    浙公网安备 33011002016107号