CI/CD_Git-大文件问题定位和排查

定位问题步骤一: 通过文件大小查看

下载的代码--查看各个文件的大小

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
posted @ 2022-05-30 11:21  辰令  阅读(616)  评论(0编辑  收藏  举报