We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
为什么要做这次分享?我的目标是什么? 为了能用好Git,能解决平时Git中使用中碰到的常见问题
不讲道理只讲规范就是耍流氓 这次先不是重点在How,而是What和Why
到底Git是个什么? The stupid content tracker 傻瓜式内容跟踪器 从代码管理工具角度来说狭隘的一些,其实是内容管理工具 那他是怎么跟踪法的那,需要先了解下Git的内部结构
探索Git的空间组织形式
首先从物理存储角度,一切都在.git这个文件夹中
index 文件 不可通过文件查看器直接查看,是git的暂存区的内存映射文件
HEAD 当前指向分支
object 文件夹
以及Tag等
其实是一个“内容寻址”系统 而前面的objects文件夹其实是一个,键值对数据库(key-value data store)
Key是什么? 就是20个byte组成 其中1个byte用16进制表示,正好高低字节占用2个字符 所以前面objects的文件结构长这样。
对象数据的统一结构
文件头:{type} {lenght} 内容:{deflate压缩算法内容}
数据对象(blob object) 数据对象是对象中最基础的。数据针对的就是你想要进入版本管理的内容数据。万物皆可blob,源代码/图片/视频等等等等 这属于内容本身了,就是内容以压缩的形式存储了
树对象(tree object) 树对象对应文件夹的描述,包含blob数据对象和子树对象。如果你把blob对象想象成叶子,可以能更理解一些。 所以blob object/tree object已经可以描述任何存储形式了
提交对象(commit object) 提交对象是一个很特别的对象。他指向了一个树(tree)来描述当时整个版本的描述。记录下下作者和时间 同时有一个或者多个 parent commit,如果是没有就是第一次提交 parent commit为啥有多个?那是因为有merge操作
tag对象 只有带注释的标签有tag对象,可以指向一个commit。 我们针对分支打tag,本质其实是对这个分支打当前commit打tag 简单tag是没有的
blob object <- tree object <- commit object <- tag object
Git的逻辑分区
Git的暂存区(stage)详解 物理存储是index文件 文件存储结构是
cache_header cache_entry 列表 SHA1签名
cache_entry 列表的存储形式
struct cache_entry { struct cache_time ce_ctime; struct cache_time ce_mtime; unsigned int ce_dev; unsigned int ce_ino; unsigned int ce_mode; unsigned int ce_uid; unsigned int ce_gid; unsigned int ce_size; unsigned char sha1[20]; unsigned short ce_flags; char name[0]; };
这样不是特别会特别大? 不会。首先因为虽然tree是全量的,但是他只是引用,容量并不大。只有修改的文件才会产生一个新版本,我改一行代码,就会产生一个全量的存储,是不是有点浪费。 这里git帮我们想到了,使用git会定时GC obejcts文件夹里面又个pack文件夹,会帮你做压缩,其实他会帮你把历史版本的文件和当前文件做一个压缩,把diff单独diff出来再压缩,等需要的时候再还原出来
时间篇幅有限 不介绍常规使用 只介绍对git有误解的操作
分支只是一个commit的引用 我们分别可以在refs里面head文件夹(本地分支)和remote(远端分支) 打开文件我们可以看到就是一个SHA1,指向最新的commit 所以这里就是一个引用和refs文件夹表意一致
本地分支和远端分支本来并无联系 你管你我管我。只是默认我们在checkout的时候会帮我们--track,--set-upstream-to
guhui@guhuideMacBook-Pro ipad % git checkout origin/main 注意:正在切换到 'origin/main'。 您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以在切换 回一个分支时,丢弃在此状态下所做的提交而不对分支造成影响
因为是分离头指针所以会有警告
学习后正确姿势是git reset commitid 但是三剑客教程里面没有说详细用法,一共有三种mode
如果要搞清楚这三个mode的区别,还是要重新捋一捋工作区(working tree)、缓存区(index file)、指针(HEAD) 其实很多git的操作就是对状态的操作
其实,git工作的过程就是追求状态一致性的过程,我们在完成工作以后,工作区(working tree)、缓存区(index file)、指针(HEAD)的状态都是一致的
好了,前面讲的都是正向工程。 那么git reset commit mode 就是妥妥的逆向工程
初始状态:
--mix 也是默认参数,重置 缓存区(index file),保留 工作区(working tree),指针移动 就是回到了 如图这个状态。 使用场景:我反悔我的提交了,原来的提交太大了,我撤回来只add了一个文件先commit,其他的文件再提交
--soft,保留 缓存区(index file),保留 工作区(working tree),指针移动 就是回到了 使用场景:我反悔我的提交了,上一个提交交了好多文件,但是我只要撤回一个文件的修改。
--hard,重置 缓存区(index file),重置 工作区(working tree),指针移动 简而言之就是“一夜回到解放前” 使用场景:我都提交了点啥垃圾代码,交上去非社死不可,不要了不要了
什么是git rebase变基?
变基的两个方向的主要用法
命令 git rebase <newbase>
git rebase <newbase>
The text was updated successfully, but these errors were encountered:
No branches or pull requests
PPT主要脉络
为什么要做这次分享?我的目标是什么?
为了能用好Git,能解决平时Git中使用中碰到的常见问题
不讲道理只讲规范就是耍流氓
这次先不是重点在How,而是What和Why
到底Git是个什么?
The stupid content tracker 傻瓜式内容跟踪器
从代码管理工具角度来说狭隘的一些,其实是内容管理工具
那他是怎么跟踪法的那,需要先了解下Git的内部结构
探索Git的空间组织形式
首先从物理存储角度,一切都在.git这个文件夹中
index 文件
不可通过文件查看器直接查看,是git的暂存区的内存映射文件
HEAD
当前指向分支
object 文件夹
文件结构不不算复杂 组织形式为 {2位16进字符}文件夹 {38位16进制字符}文件 就是对象数据库,这个后面详细讲
本地分支
远端分支
以及Tag等
回答下前面“追踪”系统怎么个追法
其实是一个“内容寻址”系统
而前面的objects文件夹其实是一个,键值对数据库(key-value data store)
Key是什么?
就是20个byte组成
其中1个byte用16进制表示,正好高低字节占用2个字符
所以前面objects的文件结构长这样。
对象数据的统一结构
文件头:{type} {lenght}
内容:{deflate压缩算法内容}
数据对象(blob object)
数据对象是对象中最基础的。数据针对的就是你想要进入版本管理的内容数据。万物皆可blob,源代码/图片/视频等等等等
这属于内容本身了,就是内容以压缩的形式存储了
树对象(tree object)
树对象对应文件夹的描述,包含blob数据对象和子树对象。如果你把blob对象想象成叶子,可以能更理解一些。
所以blob object/tree object已经可以描述任何存储形式了
提交对象(commit object)
提交对象是一个很特别的对象。他指向了一个树(tree)来描述当时整个版本的描述。记录下下作者和时间
同时有一个或者多个 parent commit,如果是没有就是第一次提交
parent commit为啥有多个?那是因为有merge操作
tag对象
只有带注释的标签有tag对象,可以指向一个commit。
我们针对分支打tag,本质其实是对这个分支打当前commit打tag
简单tag是没有的
blob object <- tree object <- commit object <- tag object
Git的逻辑分区
Git的暂存区(stage)详解
物理存储是index文件
文件存储结构是
cache_header
cache_entry 列表
SHA1签名
cache_entry 列表的存储形式
struct cache_entry {
struct cache_time ce_ctime;
struct cache_time ce_mtime;
unsigned int ce_dev;
unsigned int ce_ino;
unsigned int ce_mode;
unsigned int ce_uid;
unsigned int ce_gid;
unsigned int ce_size;
unsigned char sha1[20];
unsigned short ce_flags;
char name[0];
};
commit对应了根目录的tree,tree包含的所有的文件的引用(SHA1),Git只存内容,文件夹只是“顺便”存储,所以实际上你不能操作把一个空的目录 ,add 到 stage
这样不是特别会特别大?
不会。首先因为虽然tree是全量的,但是他只是引用,容量并不大。只有修改的文件才会产生一个新版本,我改一行代码,就会产生一个全量的存储,是不是有点浪费。
这里git帮我们想到了,使用git会定时GC
obejcts文件夹里面又个pack文件夹,会帮你做压缩,其实他会帮你把历史版本的文件和当前文件做一个压缩,把diff单独diff出来再压缩,等需要的时候再还原出来
其实Stage中存了所有文件的索引,不只你本次add进去的文件,当前版本的所有文件都在!
实际上因为是文件的快照,容量实际很小。基本上没有压力
时间篇幅有限
不介绍常规使用
只介绍对git有误解的操作
分支只是一个commit的引用
我们分别可以在refs里面head文件夹(本地分支)和remote(远端分支)
打开文件我们可以看到就是一个SHA1,指向最新的commit
所以这里就是一个引用和refs文件夹表意一致
本地分支和远端分支本来并无联系
你管你我管我。只是默认我们在checkout的时候会帮我们--track,--set-upstream-to
首先你也可以checkout远程分支
因为是分离头指针所以会有警告
因为merge会产生多个parent
造成“回溯困难”,特别如果是某一个版本出现bug,要从历史中翻出一个健康版本找到问题,会增加复杂度
相对merge,个人分支的提交是直接追加到main分支上,少一个merge的commit,都大大减少复杂度
学习后正确姿势是git reset commitid
但是三剑客教程里面没有说详细用法,一共有三种mode
如果要搞清楚这三个mode的区别,还是要重新捋一捋工作区(working tree)、缓存区(index file)、指针(HEAD)
其实很多git的操作就是对状态的操作
其实,git工作的过程就是追求状态一致性的过程,我们在完成工作以后,工作区(working tree)、缓存区(index file)、指针(HEAD)的状态都是一致的
好了,前面讲的都是正向工程。
那么git reset commit mode 就是妥妥的逆向工程
初始状态:
--mix
也是默认参数,重置 缓存区(index file),保留 工作区(working tree),指针移动
就是回到了
如图这个状态。
使用场景:我反悔我的提交了,原来的提交太大了,我撤回来只add了一个文件先commit,其他的文件再提交
--soft,保留 缓存区(index file),保留 工作区(working tree),指针移动
就是回到了
使用场景:我反悔我的提交了,上一个提交交了好多文件,但是我只要撤回一个文件的修改。
--hard,重置 缓存区(index file),重置 工作区(working tree),指针移动
简而言之就是“一夜回到解放前”
使用场景:我都提交了点啥垃圾代码,交上去非社死不可,不要了不要了
什么是git rebase变基?
变基的两个方向的主要用法
命令
git rebase <newbase>
The text was updated successfully, but these errors were encountered: