我们平时使用git很多时候只是拿来主义的用一下,而不一定了解其背后的原理和设计思想,今天系统性的对其进行总结
上图描述了git指令和其操作对象之间的关系
git的组成部分
从图中可以看到,git主要由三个部分组成:
-
工作目录(Workspace ):本地文件系统
-
暂存区( Staging area ):隔离工作目录和Git仓库
-
本地的CMDB (Local repository ):本地的CMDB ,通常是一个 .git 目录
-
远程的CMDB (Remote repository ):和本地CMDB对应的远程目录
而git管理下每个文件将会属于一下三个状态中: -
已修改 (Modified )已修改的文件在工作目录中,和其在git版本库中的文件不同,尚未加入到暂存区
-
已暂存 (Staged )已修改的文件已加入到暂存区
-
已提交 (Committed) 已修改的文件同步到git版本库中
他们之间的关系可由下图所示:
git中的Object Graph——版本之间的演化关系图
Object Graph:版本之间的演化关系图,一条边 A->B表征了“在版本B的基础上作出变化,形成 了版本A”
git的历史记录图中的每个节点表示项目的一个提交版本(也称为修正版本):都是当时所有文件的完整快照。
- 每个commit指向一个父亲
- 多个 commit指向同一个父亲:这些子节点是从父节点中先前共同版本的分支
- 一个commit 指向两个父亲:两个父节点合并的结果
一个分支(branch )只是指向一个提交节点的名称
而头节点指针(HEAD)指向当前的最新的提交节点
- 我们需要记住正在修改的分支。 因此HEAD指针指向当前的提交节点
对于git中每一个提交节点
-
每一个提交节点指向具体文件存储的指针,Git文件系统允许不同的提交节点共用一个实际文件,即与之前commit 中未发生变化 的文件,因此无需重复存储。
-
文件未发生变化,则后续多个版本始终指向同一个文件,文件发生变化了,存储两份不同的文件,两个版本指向不同的文件
-
每个提交节点还储存有日志——谁,在什么时候,附带了什么消息
具体可如下图所示:
git中的分支与合并
**分支(branch )**是版本控制对象的副本,因此可以沿两个分支并行进行修改而相互不受影响
合并(Merge) 是把两个分支合并到一起
举例说明:
对于某一个开发:
假设我们已经commit了
C
0
C_0
C0,
C
1
C_1
C1,
C
2
C_2
C2,当前的master分支指向
C
2
C_2
C2
此时,我们执行检出操作 git checkout –b iss53
就会创建出一个新的分支 iss53
然后在 iss53 上,我们再commit出一个节点
C
3
C_3
C3
然后我们再checkout回原来的master节点
git checkout –b hotfix 创建一个新的hotfix分支,并commit一个
C
4
C_4
C4
此时,如果想合并hotfix分支到master分支中,因为master分支指向hotfix分支的父节点,所以只需要将master分支指向的节点向后移即可
执行:git merge hotfix后
然后我们删除hotfix分支(git branch –d hotfix ),并切换回iss533分支(git checkout iss53 ),并commit一个新的节点,执行后结果如下图所示:
此时再换回master分支(git checkout master),尝试将 iss53分支合并进master之中
将 iss53分支合并进master后产生
C
6
C_6
C6,其父节点为
C
4
C_4
C4和
C
5
C_5
C5,表示是这两个commit节点合并的结果
一些QA
Q:将本地仓库中master分支的最新提交推送至远程仓库的指令:
A:git fetch origin master
git merge
git push origin master
其中origin是远程仓库的网址
Q:用于将github上的某个git仓库设置为本地仓库的远程仓库的指令是:
A:git remote add
Q:用于将当前staging area 中的文件写入git仓库的指令是:
A:git commit
观点
-
一个branch(分支)本质上相当于一个指定特定commit节点的指针
-
可以有两个不同的branch指向同一个commit节点
-
git commit指令相当于在object graph当前分支HEAD指向的commit基础上,派生出一个新的commit节点
-
若说commit相比其他parent来说,某文件f未发生变化,则f在.git中不会重复存储。
-
如果某个commit节点仅存在于远程服务器的object graph,那么当本地向远程git push的时候,会出现错误提示
-
git中commit节点对应的数据结构包含一个tree,tree中包含一组指针,指向本次commit中包含的所有文件