当前位置:   article > 正文

Git高级用法_git 高级用法

git 高级用法

Git高级用法

Git官方文档:Git - Reference (git-scm.com)

中文版Git - Book (git-scm.com)

Git原理部分,这篇我觉得写得挺好的:http://teohm.com/blog/learning-git-internals-by-example/

git for-each-ref Git官方教程 _w3cschool

一、git filter-branch

参考文档:

https://git-scm.com/docs/git-filter-branch

Git - 维护与数据恢复 (git-scm.com)

Git - Git 对象 (git-scm.com)

git filter-branch是一个可以用来清洗整个历史记录的工具。

下面我们通过Git仓库大文件清理来介绍下命令:

1.找出大文件或误添加的文件

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print $1}')"
  • 1

找出占空间最大的前5个数据对象对应的文件。

git gc

git 会定期运行git gc命令,收集所有松散对象并将它们放到包文件中,将多个包文件合并为一个大的包文件,移除与任何提交都不相关的陈旧对象。就是把objects下面的文件压缩到packed-refs下。

Git往磁盘保存对象时默认使用的格式叫松散对象(loose object)格式(放在.git/objects文件夹下)。Git时不时地将这些对象打包至一个叫packfile的二进制文件(放在.git/objects/pack文件夹中)以节省空间并提高效率。当仓库中有太多的松散对象,或是手工调用git gc命令,或推送至远程服务器时,Git都会这样做。

松散对象一般是由本地的git add, git commit产生的。

关于Git对象可以查看官方文档的内部原理部分。

为了获得指定引用的正确 SHA-1 值,Git 会首先在 refs 目录中查找指定的引用,然后再到 packed-refs 文件中查找。 所以,如果你在 refs 目录中找不到一个引用,那么它或许在 packed-refs 文件中。

git verify-pack

如何找出哪个文件或哪些文件占用了空间?如果你执行git gc 命令,所有对象将被放入一个包文件中,你可以通过运行git verify-pack命令,对输出内容的第三列(即文件大小)进行排序,从而找出大文件。

$ git verify-pack -v .git/objects/pack/pack-29…69.idx \
  | sort -k 3 -n \
  | tail -3
dadf7258d699da2c8d89b09ef6670edb7d5f91b4 commit 229 159 12
033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5 blob   22044 5792 4977696
82c99a3e86bb1267b236a4b6eff7868d97489af1 blob   4975916 4976258 1438
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

git rev-list

为了找出大对象具体是哪个文件,可以使用rev-list命令。git rev-list是Git底层命令,你可以获取所有提交的SHA-1值列表。git rev-list类似git log,但它默认只输出SHA-1值。如果你传递 --objects 参数给 rev-list 命令,它就会列出所有提交的 SHA-1、数据对象的 SHA-1 和与它们相关联的文件路径。

$ git rev-list --objects --all | grep 82c99a3
82c99a3e86bb1267b236a4b6eff7868d97489af1 git.tgz
  • 1
  • 2

2.从仓库中删除文件或文件夹

git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch "bigfile"' \
  --prune-empty --tag-name-filter cat -- --all
  • 1
  • 2
  • 3

这里–force是为了防止有另外的一个filter-branch正在运行,所以–force会强行终止别的filter-branch。如果要删除的是文件夹,则要在‘git rm --cached’命令后面加上-r,表示递归。

*git filter-branch --index-filter* 让每个提交的文件都复制到索引(.git/index)中

然后运行过滤器命令:*git rm --cached --ignore-unmatch 文件名 ,*让每个提交都删除掉“文件名”文件

然后--prune-empty 把空的提交“修剪”掉

然后*–tag-name-filter cat* 把每个tag保持原名字,指向修改后的对应提交

最后-- --all 将所有ref(包括branch、tag)都执行上面的重写

3.删除缓存下来的ref和git操作记录

这些缓存对象给你提供了撤销操作的一次机会

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
  • 1
  • 2

4.垃圾回收

上面2步把大文件的索引都切断了,这个时候进行垃圾回收,就可以很明显看到效果了。回收空间,清理本地仓库不可达对象。

–aggressive会更加多的优化仓库,但也更加消耗时间。

–prune= 修剪比指定时间更老的松散对象。

git gc --aggressive --prune=now
  • 1

可以看到直接运行git gc, 只是把松散对象压缩到pack中。但是git gc --prune会将不可达的松散对象从仓库中移除掉。

5.推送仓库

这时候普通的push是不行的,需要强制推送。

git push --force
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/387351
推荐阅读
相关标签
  

闽ICP备14008679号