内容简介:git的定义是一个内容寻址文件系统。内容、寻址、文件、系统,该来的总会来的…本文旨在通过实践来介绍.git文件夹中的目录及文件功能,属git基础知识。但在此基础上可解决各git使用过程中可能遇到的问题,如“.git文件夹占用空间大”,“git如何找回丢失的对象(提交)”,”git diff 对比依据是什么”等,
git的定义是一个内容寻址文件系统。内容、寻址、文件、系统,该来的总会来的…
本文旨在通过实践来介绍.git文件夹中的目录及文件功能,属git基础知识。但在此基础上可解决各git使用过程中可能遇到的问题,如“.git文件夹占用空间大”,“git如何找回丢失的对象(提交)”,”git diff 对比依据是什么”等,
话不多说,撸起袖子就是干,来看看 .git 是个啥样,这些个货色都是干嘛的。
# 初始化git,查看内容 git init 产生一个.git隐藏文件夹 cd .git ls -F1 # 初始化时的.git长这样 # HEAD # config # description # hooks/ # info/ # objects/ # refs/ # 日常工作中的.git大概长这样 # COMMIT_EDITMSG # config # description # hooks/ # index # info/ # logs/ # objects/ # refs/
随着之后的多种 git操作 ,还会存在如 MERGE_HEAD 、 MERGE_MODE等和 COMMIT_EDITMSG 类似功能的文件,branches(分支信息)、lost-found(存储被悬挂起/丢失的提交对象)、packed-refs(压缩后的refs记录)等和logs、objects类似功能的文件夹。
以上面的.git为例做个简单的介绍:
COMMIT_EDITMSG 最近一次的 commit edit message ;
# 编写提交信息的两种姿势 git commit # 自动打开文件编辑,在文件中输入信息即可 git commit -m msg # 信息都会被保存到 COMMIT_EDITMSG # 如需修改提交信息,不可直接编辑COMMIT_EDITMSG,可执行以下命令 git commit --amend # 自动打开文件编辑,在文件中修改信息即可
description 描述文件,打开后里面提醒该为git仓库创建个描述(Unnamed repository; edit this file ‘description’ to name the repository.)。
config 文件包含项目特有的配置选项,如一些常用项:
- [core] ignorecase 是否忽略文件大小写;
- [remote "origin"] url 配置远程仓库地址;
- [remote "origin"] fetch 远程分支映射关系;
- [user] name 用户名
- [user] email 邮箱
- [alias] 命令别名配置 : cmt = commit
抑或更多其他config参数…
全局配置文件在 ~/.gitconfig ,Windows应该是在Users/Administrator/.gitconfig。
info/ 文件夹用以存储一些有关git仓库的信息,如exclude
# 包含一个全局性排除(global exclude)文件,用以放置那些不希望被记录在 .gitignore 文件中的忽略模式(ignored patterns); echo for git ignore > git-ignore echo for git exclude > git-exclude echo git-ignore > .gitignore git status # On branch test # Untracked files: # (use "git add <file>..." to include in what will be committed) # .gitignore # git-exclude # git-ignore已被忽略,还有2个untracked的文件 cd .git cd info/ vi exclude # 最后一行新增 git-exclude cd ../.. git status # On branch test # Untracked files: # (use "git add <file>..." to include in what will be committed) # .gitignore # git-exclude 已被忽略,只有.gitignore还是untracked
除exclude文件外,还可能会有refs、grafts,attributes等文件
hooks/ 文件夹包含客户端或服务端的钩子脚本(hook scripts),如pre-commit,post-receive等:
vi .git/hooks/pre-commit # 保存以下信息 第一行指定用什么执行 #!/bin/sh echo "Message for pre commit"; exit 1; # 开执行权限 chmod +x .git/hooks/pre-commit # user+group+other 执行x(1)权限 ,备注 r(4,read),w(2,write),x(1,execute),-(0,no permission),s(special) touch commit-hook-test git add . git commit -m “pre-commit test“ # 你会看到以下信息 # Message for pre commit # 如果不exit,则继续执行,详情可参考.git/hooks/下的*.sample文件 # Message for pre commit # [test 038e6ec] pre-commit test # 1 file changed, 1 insertion(+), 1 deletion(-)
logs/ 放置git仓库操作记录的文件夹,包含HEAD文件 和 refs文件夹。
HAED 文件包含对 git分支 的操作记录,如
vi HEAD # 99a10c283c33beed7f31c210a6c8b411d2a31085 5daf6094ea2cc60d17e947c0435096a4bdafe82d yeshou <yeshou@xxx.com> 1535082919 +0800 commit: rm files # 5daf6094ea2cc60d17e947c0435096a4bdafe82d b8e02a5f9c2bf44342d15f5ea1e60ffd9434765a yeshou <yeshou@xxx.com> 1535087285 +0800 checkout: moving from test to master # 先是删除文件后提交了次,再是由test检出到master
refs 文件夹包含 heads 文件夹,remote文件夹。heads 记录本地相关的各 git分支 操作记录,remote 记录远程仓库相关的各 git分支 操作记录
cd heads ls # master master分支操作记录 # test test分支操作记录 cd remote/origin ls # master 远程master分支操作记录 # test 远程test分支操作记录
HEAD 文件指示当前被检出(所在)的分支,如当前在test分支,文件内容则为ref: refs/heads/test。
index 文件是当前版本的文件索引,包含生成当前树(唯一确定的)对象的所虚信息,可用于快速比对工作树和其他提交树对象的差异(各commit和HEAD之间的diff),可用于存储单文件的多个版本以有效的解决合并冲突。可使用git ls-files 查看index文件内容。如:
- git commit 的一次提交从index中的信息生成tree对象,将其存储在对象数据库中,并与本次新的commit做关联,产生本次commit的tree信息(下面的objects介绍中会提到commit和tree)。
refs/ (references) 文件夹存储指向数据(分支)的提交对象指针;其中 heads 文件夹记录内部文件对应名称的分支的提交对象;tags记录内部文件对应名称的标签的提交对象;remotes记录内部文件对应名称的远程仓库分支的提交对象;
举个例子:
cat .git/refs/heads/master # ce1fed3fdbaf12e816e3028055f9feee57b33b45 当前master的提交记录 git checkout -b test # 检出一个新分支 find .git # 多了个 .git/refs/heads/test 文件 git log # commit 63a85dcbc6978f2d43996f5bebc38993c2afadaa (HEAD -> test) # Author: yeshou <yeshou@xxx.com> # Date: Sat Aug 25 13:57:26 2018 +0800 # # branch test : edit test : add line : write d # commit ce1fed3fdbaf12e816e3028055f9feee57b33b45 (master) # Author: yeshou <yeshou@xxx.com> # Date: Sat Aug 25 12:40:35 2018 +0800 # # edit test : add line : write c cat .git/refs/heads/test # 63a85dcbc6978f2d43996f5bebc38993c2afadaa 当前test的最近提交记录 cat .git/refs/heads/master # ce1fed3fdbaf12e816e3028055f9feee57b33b45 依然是当前master的最近提交记录
另两者亦然。
objects/ 文件夹用以存储git仓库中的所有数据内容。
一步步来…
先看看这个文件夹里是怎么存数据内容的,再理解这些数据内容又是什么。
# 为了清晰的看明白objects文件夹中文件的生成,初始化.git rm -rf .git git init cd .git find .git # 这时候objects文件夹下只有pack和info 两个空文件夹 touch test vi test # 输入 a ,保存,退出 git add test find .git # objects 下多了个文件夹,且里面有文件 # .git/objects/44 # .git/objects/44/2406aa9341668f9c43c2d5378a777ad69324a0
验证下这个文件内容是什么,注意,这是个二进制球,呸…是文件,文明观球,呸…是观看。这里我们用传说中git中的手术刀( git cat-file )来解剖git文件。
git cat-file -p 442406aa9341668f9c43c2d5378a777ad69324a0 # 输出 a
9de29bb2d1d6434b8b29ae775ad8c2e48c5391 是个二进制文件,是git对象中的blob对象,它记录了当前版本的该文件的数据内容,并以SHA-1计算产生一个40个字符的校验和。 根据官方描述:这是一个 SHA-1 哈希值——一个将待存储的数据外加一个头部信息(header)一起做 SHA-1 校验运算而得的校验和。
继续操作,修改test
vi test # 第二行输入 b ,保存,退出 git add test find .git # objects 下又多了个文件夹,且里面也有文件 # .git/objects/bf # .git/objects/bf/daa0f1c3415c09d3080063911d155fd7259d18
这次的二进制文件的数据内容是 a (手动换行) b 。
继续走下去:
git commit -m “add test” # wtf,怎么突然生出2个文件夹,来来来,看看内容 # .git/objects/3e # .git/objects/3e/5f95cd5c4f0ff429522b0fdfeda9369f92d89c # .git/objects/fd # .git/objects/fd/1332e4e95f8a64682c1516e175abb66b6f6325 git cat-file -t fd1332e4e95f8a64682c1516e175abb66b6f6325 # commit git cat-file -p fd1332e4e95f8a64682c1516e175abb66b6f6325 # tree对象、作者、提交者、提交日期、提交信息、父对象(有的话带一个或多个父对象) # tree 3e5f95cd5c4f0ff429522b0fdfeda9369f92d89c # author yeshou <yeshou@xxx.com> 1535168447 +0800 # committer yeshou <yeshou@xxx.com> 1535168447 +0800 # add dir-test git cat-file -t 3e5f95cd5c4f0ff429522b0fdfeda9369f92d89c # tree git cat-file -p 3e5f95cd5c4f0ff429522b0fdfeda9369f92d89c # 100644 blob bfdaa0f1c3415c09d3080063911d155fd7259d18 test git cat-file -p bfdaa0f1c3415c09d3080063911d155fd7259d18 # a (换行) b
3e5f95cd5c4f0ff429522b0fdfeda9369f92d89c 也是个二进制文件,是git对象中的tree对象,记录着blob标识符、路径名和在一个tree下的所有文件的元数据。
fd1332e4e95f8a64682c1516e175abb66b6f6325 又是个二进制文件,是git对象中的commit对象,它记录了当前版本的一次提交数据内容,包含tree对象、作者、提交者、提交日期、提交信息、父对象(有的话带一个或多个父对象)。
然后,pack文件夹是干嘛的?
随着objects文件夹下的文件夹和文件不断生成(也就是N多次的commit之后),objects文件夹明显会”长大”,这时开发者可以用 git gc 来对之前的操作的对象做整理压缩。
pack 文件夹内有2个文件 pack-(SHA-1).pack 和 pack-(SHA-1).idx 前者是以压缩形式存储之前记录对象的文件,后者用以存储访问索引的文件。
举个例子:
git gc # Counting objects: 12, done. # Delta compression using up to 4 threads. # Compressing objects: 100% (4/4), done. # Writing objects: 100% (12/12), done. # Total 12 (delta 0), reused 0 (delta 0) find .git # 发现少了很多objects里的文件夹和文件,多了以下2个文件 # .git/objects/pack/pack-2021ec3cb18c796fdfca8ef616fb6a20b1449ab1.pack # .git/objects/pack/pack-2021ec3cb18c796fdfca8ef616fb6a20b1449ab1.idx git verify-pack -v .git/objects/pack/pack-2021ec3cb18c796fdfca8ef616fb6a20b1449ab1.idx # 列出之前存在objects里的所有操作数据内容 # 655a12c9b83a029bb46fa852ea15e6affd1587d8 commit 167 117 510 # ... # 616dfdb2643c725fa1027ecef76d49d482d9e26d tree 32 43 670 # ... # bfdaa0f1c3415c09d3080063911d155fd7259d18 blob 5 14 853 # 也可以通过后面加 | grep keyword 来搜索所需的内容,如下列出所有commit记录 git verify-pack -v .git/objects/pack/pack-2021ec3cb18c796fdfca8ef616fb6a20b1449ab1.idx | grep commit
git gc ( garbage collect )命令将会收集所有松散对象并将它们存入 pack,合并这些 pack 进一个大的 pack,然后将不被任何 commit 引用并且已存在一段时间 (数月) 的对象删除,除此之外还会将所有引用 (references) 并入一个单独文件(上面有提到随着各种操作,.git下还会产生更多文件夹,.git中的packed-refs文件夹就是这时候产生的)。该命令可能通过修改配置中的 gc.auto 和 gc.autopacklimit 来调整操作阈值。注意:git gc 调用的也是 git prune ,如有需求也可关注这个命令。
至于”info文件夹是干嘛的?”这个问题还未知… 官网的描述也没看懂,也没查到或者在项目中实际出现这个文件夹有存在什么文件,要么等遇到再说?
至此git对象中的三个对象已经知道是咋回事了,还剩个tags对象,简单介绍下。
tags对象通常也是一个commit对象,指的是一个指定了开发者可读名称的一个特殊对象,如有需要也可通过 git cat-file 来解析探索。
其间关系大致如下:
|- commit aaaaa… |- tree abbbb… |- blob acccc… (可能是这次修改的) |- blob adddd…(也可能是上次修改的) |- tree aeeee… |- blob affff… |- commit bbbbb…
关系图的话,这个是git官网的… 和上面的结构是一样的。
基于objects的介绍再回过头来看看”内容、寻址、文件、系统”便比较清晰了:以git对象作为内容,通过唯一的校验和寻址,文件形式存储的一个版本控制系统。
了解完这些,主要还是希望能够运用到实际生产中来解决问题。如 “项目中.git文件为什么这么大?怎么处理?”
可能的处理方案:
1. 执行 git gc ,如果压缩后能达到预期效果,则不做过多处理
2.针对历史记录中对某些大文件的引用,则删除对应引用的对象,操作如下
git gc git count-objects -v git verify-pack -v .git/objects/pack/pack-(SHA-1).idx | sort -k 3 -n | tail -5 # 前面用过了git verify-pack,可知第三列信息表示的文件大小,这里用tail取前5个较大文件的记录 git rev-list --objects --all | grep (SHA-1) # 使用 git rev-list --objects -all 来查看指定 (SHA-1) 对象信息 # ce1fed3fdbaf12e816e3028055f9feee57b33b45 xxx.mp4 比如是个视频文件 git log --pretty=oneline --branches -- xxx.mp4 # 找出哪些 commit 修改/操作了这个文件 # 94cbe08e... add xxx.mp4 git filter-branch --index-filter 'git rm --cached --ignore-unmatch xxx.mp4' -- 94cbe08e^.. # 删除文件引用,rewrite 信息... rm -rf .git/refs/original rm -rf .git/logs/ git gc # 删除 .git/refs/original 和 .git/logs/ ,处理其中对xxx.mp4文件仍存在的引用,之后repack仓库 git count-objects -v # 检查下操作后文件大小,或者直接在.git目录下执行 du -h -d 1 查看1级目录/文件的大小
3.若还是难处理,或者不好处理,或者不想删除大文件的引用,则备份一份.git,然后初始化git仓库,操作如下
# 除去备份操作,备份操作使用者自定义 rm -rf .git git init git remote add origin xxx.git # 重新指向新的远程仓库地址,也可根据上文所说修改config文件来指定
参考
关于git hooks,参考Customizing-Git-Git-Hooks
https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
关于更详细的.git文件夹,参考 Gitrepository-layout-objectsinfo
https://git-scm.com/docs/gitrepository-layout#gitrepository-layout-objectsinfo
以上所述就是小编给大家介绍的《如果非得了解下 GIT 系统… C 实践篇》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 【语言模型系列】实践篇:ALBERT在房产领域的实践
- Go Module 工程化实践(三):工程实践篇
- 火爆开发概念之——微服务实践篇
- 实践篇 | 推荐系统之矩阵分解模型
- Apache Pulsar 之 Java Function 实践篇
- 一个极简、高效的秒杀系统(战术实践篇)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Trading and Exchanges
Larry Harris / Oxford University Press, USA / 2002-10-24 / USD 95.00
This book is about trading, the people who trade securities and contracts, the marketplaces where they trade, and the rules that govern it. Readers will learn about investors, brokers, dealers, arbit......一起来看看 《Trading and Exchanges》 这本书的介绍吧!