开源工具技巧GitMAC + LINUX + VIM + GIT + Latex + Markdown

Git 之旅——不那么深入理解 Git

2020-12-22  本文已影响0人  QinGeneral
image

初期形态

代码管理的最早形态是使用类似现在百度同步盘的方式同步、管理代码。但是代码冲突问题时有发生,只能人工解决。

之后出现了改善工具:

# 生成差异文件
diff -u hello1 hello2 > diff.txt

# 根据 hello1、diff 生成 hello2
cp hello1 hello3
patch hello3 < diff.txt

# 根据 hello2、diff 生成 hello1
cp hello2 hello4
patch -R hello4 < diff.txt

Linus 在 1991~2002 年使用 diff、patch 维护 Linux 代码差异。

diff、patch 缺陷:无法处理二进制文件。Git 解决了此问题。

开山鼻祖 CVS Concurrent Versions System

CVS(ConcurrentVersionsSystem)诞生于1985年,是由荷兰阿姆斯特丹 VU 大学的 DickGrune 教授实现的。当时 DickGrune 和两个学生共同开发一个项目,但是三个人的工作时间无法协调到一起,迫切需要一个记录和协同开发的工具软件。于是 DickGrune 通过脚本语言对 RCS(Revision Control System)(一个针对单独文件的版本管理工具)进行封装,设计出有史以来第一个被大规模使用的版本控制工具。

—— 蒋鑫. Git权威指南 (Chinese Edition) (Kindle 位置 559-562). 机械工业出版社. Kindle 版本.

CVS 存在的问题:

CVS 成功地为后来的版本控制系统确立了标准,像提交说明(commitlog)、检入(checkin)、检出(checkout)、里程碑(tag)、分支(branch)等概念在CVS中早就已经确立。

—— 蒋鑫. Git权威指南 (Chinese Edition) (Kindle 位置 578-579). 机械工业出版社.

SVN Subversion

SVN 优化了很多特性,如:

这些优化也使得它在版本控制工具中成为最佳选择之一。但 SVN 本质上是一种集中式版本管理工具,这种版本控制太依赖于服务器,如果服务器出现问题,版本控制将不可用;如果网络较差,提交代码将变得十分漫长。

除了以上集中式版本控制系统固有问题之外,再加上 SVN 本身设计的一些问题,使用其进行版本管理也并存在很多不如意之处。比如:

Git

BitKeeper 和 Git 由来

BitKeeper 是一种分布式版本控制系统。分布式版本控制系统优势:不要中央版本库,每个人都可以自己本地查看提交日志、提交、创建里程碑和分支、合并分支、回退等操作,而不需要网络连接。

分布式版本控制系统和集中式版本控制系统区别粗略的讲,就像是分封制和郡县制的区别。

假设现在要书写史书,集中式即郡县制,郡县制背后是强大的中央集权,相当于中央的史书绝对权威,各个郡县对史书进行修改后必须上报中央才能生效。距离首都近的城市还好,提交修改十分便捷,如果海南要提交对史书的修改,得数月才能跑到首都,进行修改。要想拉取新的分支,写写野史,必须先上报中央,批准后才能进行。这里的离首都的距离,就相当于网速,任何修改、提交、拉分支必须经过网络和中央仓库交互后才能进行。

分布式则相当于春秋战国时期,诸侯做大,诸侯每个人都有一份史书,都可以在自己的国家进行修改。任何修改的提交,甚至想要创建新的分支,写写野史,也无须上报周天子,在自家就可以完成。想同步到周天子时再派人去周天子那里同步一下即可。

这就是集中式和分布式版本控制系统的根本区别。

2005 年发生的一件事最终导致了 Git 的诞生。在 2005 年 4 月,AndrewTridgell(即大名鼎鼎的 Samba - Wikipedia 的作者)试图对 BitKeeper 进行反向工程,以开发一个能与 BitKeeper 交互的开源工具。这激怒了 BitKeeper 软件的所有者 BitMover 公司,要求收回对 Linux 社区免费使用 BitKeeper 的授权。迫不得已,Linus 选择了自己开发一个分布式版本控制工具以替代 BitKeeper。

—— 蒋鑫. Git权威指南 (Chinese Edition) (Kindle 位置 663-666). 机械工业出版社. Kindle 版本.

基本知识

image

目录结构

mkdir demo
cd demo
git init
ls -l .git

# output
# 
# config
# description
# HEAD
# hooks/
# info/
# objects/
# refs/

剩下的四个文件很重要,是 Git 的核心组成部分:

接下来通过拆解 git addgit commitgit checkout 命令,结合 HEADrefs/heads/masterobjects/ 文件变化,探索一下 Git 的背后。

实践操作

git checkout : HEAD

cat .git/HEAD
# output
# ref: refs/heads/master

git checkout -b test

cat .git/HEAD
# output
# ref: refs/heads/test

git add filename : 工作区文件添加到暂存区


# 生成 object
git hash-object -w filename

# 添加到暂存区
git update-index --add filename

# 上述两个命令相当于
git add filename
# 查看暂存区
git ls-files --stage

# 上述命令相当于
git status

git commit : 将暂存区文件提交


# 保存当前目录结构
git write-tree

# 保存快照 commit,-p 可指定父快照
echo "first commit" | git commit-tree 90f3b20385d2b20cf85477a65e4ef7e2eff71353 [-p id]

# git log 无内容,因为当前 HEAD 没有绑定到刚刚提交的快照
git log

# HEAD 对应 refs/head/master,将快照 id 放到该文件即可
echo 785f188674ef3c6ddc5b516307884e1d551f53ca > .git/refs/heads/master

git log

# 以上命令相当于
git commit -m "first commit"

总结

objects/ 中的对象类型

tree 对象相当于 Linux 中的目录,blob 对象相当于 Linux 中的文件。tree 和 blob 关系如下图:

image

refs/heads/master.git/objects 各个类型对象之间的关系:

image

命令拆解与文件转换关系

image
git checkout -b test

git checkout 切换分支,本质上是对 HEAD 文件的内容修改,令其指向 refs/ 中的不同文件。

git add

git add 分为两步:

  1. 将工作区中的文件转为 objects/ 中的 blob 对象,并以 SHA1 命名
  2. 将该对象的 SHA1 记录到 index 文件中
git commit

git commit 分为三步:

  1. 根据 index 中的记录,生成 objects/ 中的 tree 对象
  2. 根据生成的 tree 对象创建 commit 对象
  3. 把 commit 对象的 SHA1 放入 refs/heads/master

HEADrefs/heads/masterobjects/ 关系

image

问题

Git 是保存差异吗?

经过实践操作和搜索发现,Git 每次修改文件都会生成一份完整的 blob 文件,而非保存差异。只是会在和远程仓库交互的时候,会进行压缩和差异处理来决定上传差异文件还是完整的文件。

就是说平常 Git 存储的完整文件——松散 loose 对象格式,但是 Git 会时不时对这些文件进行打包,删除原始文件,当向远程服务器推送的时候也会执行这个操作。自己可以执行 git gc 主动触发这一操作。

详细解答可以看:Git 内部原理 - 包文件

谈谈学习

  1. 以终为始:任何学的东西都得落到产出
  2. 实践:要想掌握一种方法,实际上是拥有对应的强大的神经元通路,其实就是通过神经元通路不断冲刷来形成的。正如鲁迅先生所说:世界上本来是没有路的,走的多了才产生了路。神经元通路也是如此
    1. 多种形式学习:画图、写文字梳理逻辑、讲出来、看视频
      1. 主动学习
      2. 被动学习


        image
    2. 刻意练习:练习中感觉不舒服,正是建立新的神经通路的时候
  3. 反馈
  4. 总结、联想:神经连接越多,记忆越深刻

练车:每个动作都是刺激新的通路产生,并且实践的时候反馈非常及时,比如说倒车入库,压线就是压线了,对就是,错就是错,能够马上知道行为的正确与否,并做出纠正动作的决策。

重构:不仅要读重构之法,也要亲手写代码去实践。

参考资料

上一篇 下一篇

猜你喜欢

热点阅读