定位问题步骤一: 通过文件大小查看
下载的代码--查看各个文件的大小
du -h -d 1./
首先查看包对象的
git count-objects -vH
计算解包的对象数量及其磁盘消耗量
显示所有的分支
git branch -r | awk '{print $1}'
###awk求和、平均值、最大小值
求和 cat data|awk '{sum+=$1} END {print "Sum = ", sum}'
查看各个分支的大小 branch size stats
for name in `git branch -r | awk '{print $1}'`; do echo -n $name" - "; git ls-tree -rl $name | awk '{sum+=$4}END{print sum / 1000000 "MB"}'; done | sort -k3g
定位问题步骤二:通过大文件查看
1.列出blob
找出要清理的大文件
####找出排名前 5 的 pack 记录:
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5
35d21063a704dd90d241ae609af3f3f2ef14b321 blob 117450646 20768943 2317375723
2.blob的名称和hash
列出提交包含的文件--大文件对应的hash和名称
###第一行的字母其实相当于文件的id,用以下命令可以找出id对应的文件名
-- 根据上面提交id看文件
--- 找出大文件所在的位置 git rev-list --objects --all|grep 35d21063a704dd90d241ae609af3f3f2ef14b321
git rev-list --objects --all | grep 35d21063a704dd90d241ae609af3f3f2ef14b321
blob的内容和hash
git cat-file 命令显示版本库对象的内容、类型及大小信息
git cat-file -p 35d21063a704dd90d241ae609af3f3f2ef14b321
git cat-file -p 对象 hash 值 查看对象的内容
3.blob对应的commit
Which commit has this blob?
控制显示的记录格式,常用的格式占位符写法及其代表的意义如下
示例
obj_name="35d21063a704dd90d241ae609af3f3f2ef14b321"
git log --all --pretty=tformat:'%T %h %s' \
| while read tree commit subject ; do
if git ls-tree -r $tree | grep -q "$obj_name" ; then
echo "$obj_name" $commit "$subject"
fi
done
##中文意思为,安静模式,不打印任何标准输出。如果有匹配的内容则立即返回状态值0。
'%H': commit hash
4.commit相关的分支
git branch --contains 553095e --all
5. 查看log
git log --follow src/plng_nod237.txt
查看大文件
git bash窗口执行下面这段命令会依次对历史提交中的文件大小进行排序
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| sed -n 's/^blob //p' \
| sort --numeric-sort --key=2 \
| cut -c 1-12,41- \
| $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest
git-rev-list - 以反向时间顺序列出提交对象
--objects 打印列出的提交引用的任何对象的对象ID
git cat-file 命令显示版本库对象的内容、类型及大小信息
linux numfmt 命令--转换数字
通过对历史提交进行排序可以看到大部分都是因为这两个文件夹里面的文件导致项目变大
解决方式
方式一: 没合并到主分支的情况下,删除相应分支和使用到该commit 的分支
方式二: 使用filter-branch抹掉错误提交的大文件提交记录,彻底清理.git目录
####处理大文件 filter-branch 改写了commit历史
git filter-branch --index-filter 'git rm --cached --ignore-unmatch crawel.pdf '
# git stash
git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch crawel.pdf' --tag-name-filter cat -- --all
–prune-empty 选项告诉git,如果因为重写导致某些commit变成了空(比如修改的文件全部被删除),那么忽略掉这个commit。
–index-filter 选 项指定重写的时候应该执行什么命令,要执行的命令紧跟在它的后面,在这里就是git rm --cached --ignore-unmatch
–tag-name-filter 表示对每一个tag如何重命名,重命名的命令紧跟在后面,当前的tag名会从标注输入送给后面的命令,用cat就表示保持tag名不变。
紧跟着的-- 表示分割符,
最后的 -–all 表示对所有的文件都考虑在内
说明
维护着一个微型的文件系统,其中的文件也被称作数据对象。所有的数据对象均存储于项目下面的 .git/objects
Git维护两个主要的数据结构:
对象库(object store)和索引(index)
:块(blob)、目录树(tree)、提交(commit)和标签(tag)
blob, 就是单个的文件; blob对应的commit的哈希值
tree, 就是一个文件夹 tree对象解决文件名的问题
原理说明:
使用filter-branch抹掉错误提交的大文件提交记录,彻底清理.git目录
1.出现原因:
大文件放到了项目下,提交的时候又push到远程仓库去了,虽然后来把文件删掉了重新提交,
但Git保存了每个文件的前生后世 防止哪天又要找回你删除过的文件,
导致项目下的.git子目录依然存在这些大文件的提交记录,占用大量空间
git版本保存导致大文件仍会被记录用于之后回滚需要
.pack 是包文件,这个文件包含了从文件系统中移除的所有对象的内容
.idx是索引文件,这个文件包含了包文件的偏移信息
2.解决方式
用filter-branch,这个命令就可以修改历史提交记录,从而达到清理错误提交记录。
需要提交就再执行
git add 都会生成一个Git对象,称为blob 对象,存放在objects目录下
将Blob对象合并成一个包文件,同时会生成一个索引文件,索引文件中包含了每个Blob对象在包文件中的偏移信息,Git在打包的过程中使用了增量编码方案
删除pack中无用的大文件缓存
查看提交记录
git 功能
版本控制-多人协作的并行开发
Git会把代码以及历史保存在本地,但最终还是要提交到服务器上的远程仓库,通过远程仓库为中介,进行协同开发
开发Samba的Andrew -试图破解BitKeeper的协议
rsync(Remote Sync,远程同步)是由Andrew Tridgell 于1996年开发的一款开源软件
2002年到2005年,linus顶着开源社区精英们的口诛笔伐,选择了一个商业版本控制系统BitKeeper作为linux内核的代码管理工具
2005年4月,Andrew Tridgell(Samba的作者)试图对BitKeeper进行反破解,以开发一个能与BitKeeper交互的源码工具
反编译 BitKeeper 并利用了其未公开的接口
规范和约定
多人协作的并行开发-遵循一定的规范和约定
git 分支管理策略
Git Flow 是最早出现也是最经典的一种分支管理策略,它由两个长期分支和三种类型的临时分支组成
Master
Develop Release Feature Hotfix
feature -xxx
Github flow 的最大优点就是简单,对于"持续发布"的产品,可以说是最合适的流程
它的假设:master分支的更新与产品的发布是一致的。也就是说,master分支的最新代码,默认就是当前的线上代码。
实际代码合并进入master分支,并不代表它就能立刻发布:有些公司有发布窗口,商店的APP提交审核以后,等一段时间才能上架
GITLAB FLOW分支
develop分支以外,再建立不同的环境分支。
比如,"开发环境"的分支是develop,"预发环境"的分支是pre-production,"生产环境"的分支是production
git 更新策略-整合
git diff HEAD -- readme.txt命令可以查看工作区和版本库
cherry-pick的合并不同于merge和rebase,它可以选择某几个节点进行合并
git-版本
版本发布
部署和回滚 Deploy
git 基本
git1.本地有三个工作区域:工作目录(working directory)、暂存区(stage/index)、资源库(Repository或Git directory).
以及远程的git仓库(Remote directory)
2.文件的四种状态: Untracked : 未跟踪
Unmodify : 文件已经入库,未修改
Modified :文件已修改,仅仅是修改:通过git add 可进入暂存staged状态。使用git checkout 则丢弃修改过,返回到unmodify 状态
Staged : 暂存状态 执行git commit 则将修改同步到库中 执行git reset HEAD filename 取消暂存,文件状态为Modified
3.Branch 和 HEAD 以及 commit history--引用+节点
提交历史、分支、HEAD等状态
当前工作目录就是HEAD指向的节点: 提交节点
HEAD也可以指向一个分支,间接指向分支所指向的节点
HEAD从分支上取下来直接指向某个节点,此过程就是分离HEAD : git checkout节点哈希值
git reset HEAD~N
建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev
4.解决冲突
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容
git命令-上层命令
git help
git config/ git log/ git tag /git show /git init
git status /git add /git commit / git clone /git fetch/git pull/git push
git branch / git checkout /git reset /git remote
git merge/git rebase /git cherry-pick
git diff/ git rm /git stash /git rm /git mv /git grep /git bisect /git rsync
gitgnore 忽略文件
配置文件- \.git\config
当前目录下多了一个.git的目录
新版本的Git提供了新的git switch命令来切换分支
上层命令通过组合底层命令或直接操作底层数据对象,使 Git 底层实现细节对用户透明,从而为用户提供了一系列简单易用的命令集合
示例01-创建本地参股-创建全新的仓库
mkdir items
cd items
# git init命令把这个目录变成Git可以管理的仓库
git init
touch ReadME.md
git add ReadME.md
git commit -m "first commit"
# #为远程仓库地址创建别名
git remote add origin git@gitlab.com.test/items.git
# #查看当前别名所对应的远程仓库地址
git remote show origin
#默认只推送当前分支
git push
# 不带任何参数的git push,默认只推送当前分支,这叫做simple方式,
# 还有一种matching方式,会推送所有有对应的远程分支的本地分支,
#如果当前分支与多个主机存在追踪关系,则可以使用 -u 参数指定一个默认主机 git push -u orign master
示例02.-克隆远程目录
git clone
#查看远程所有分支
git branch -a
#新建分支并切换到指定分支 git checkout -b本地分支名 origin/远程分支名
git checkout -t origin/develop/branch_1
# #查看当前别名所对应的远程仓库地址
git remote show origin
其他命令
git stash list/ git stash apply /git stash drop
git stash pop
使用diff命令生成patch文件,后使用apply命令应用patch到分支,从而实现修改复刻
# 生成补丁
git diff > commit.patch
# 检查补丁
git apply --check commit.patch
# 应用补丁
git apply commit.patch
format-patch命令是对指定版本范围内每次commit的修改生成对应的patch文件
git apply
git format-patch
git am可以一次合并一个文件,或者批量合并一个目录下所有的patch
搭建git服务器
人少用 每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里
人过用用Gitosis来管理公钥
Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目
Git 底层实现原理
Git 本质上是一个内容寻址的文件系统 将文件和目录进行区分存储。使用轻量级数据结构
上层命令(Porcelain Commands)
底层命令(Plumbing Commands)
对象数据库(Object Database)
底层命令
几个核心的底层命令,如:update-cache、write-tree、read-tree、commit-tree、cat-file、show-diff
目前版本底层命令 git update-cache、 git write-tree、 git read-tree、 git commit-tree、 git cat-file、 git show-diff
对象数据库(Object Database)
基于 Key-Value 的内容寻址文件系统(Content-addressable File System)
Ext 文件系统中,使用 Block 存储所有类型的内容;使用一个 Inode 记录一个文件或目录存储内容时占用的所有 Block 的序号,最终通过硬盘控制器进行索引
在 Git 文件系统中,使用 Object 存储所有类型的内容,也称为 Git 对象,
Git 对象模型主要包括以下 4 种对象
二进制对象(Blob Object)
树对象(Tree Object)
提交对象(Commit Object)
标签对象(Tag Object
引用:
HEAD 引用
标签引用 轻量标签 和 附注标签
远程引用
存储模型
git 的确采用了增量存储 git verify-pack 这个底层命令来查看 analyze-git 中的索引文件
git gc 命令来进行打包
参考
https://stackoverflow.com/questions/223678/which-commit-has-this-blob/223890#223890
git项目大小优化笔记,删除历史提交中的大文件 http://t.zoukankan.com/fuhua-p-15527023.html