[V 站有 git 大神吗? ]删除仓库的某个时间点之前的历史记录,减少.git 目录大小。 救命啊啊。

2016-08-08 09:48:05 +08:00
 Yancey
安卓仓库。有很多 commits 和分支。想删除某个时间点之前的所有 commits 减少.git 目录大小,找了很多办法。感觉只有 grafts+ filter-brnach 靠谱。不过还是遇到很多问题、
1.要截断的 commits 之前有很多分支。。用 filter-branch 不会删除这些分支,怎么解决?
2.这个仓库是公开仓库。很多人已经 clone 在本地。所以截断操作应该是在服务器还是本地?我试过在本地更改,但是推不到服务器上。如果在服务器操作,怎么将本地的改动变为最小?

示意图如下:
12411 次点击
所在节点    git
56 条回复
zzn
2016-08-08 10:30:15 +08:00
公开项目不应该修改已提交的 commit ,除非让全部人重新 clone

其实很好奇,究竟.git 是有多大? 怎么会有这种需求。。。
Yancey
2016-08-08 10:32:23 +08:00
@bjzhou1990 我就是参考这个。如图的 git 结构,遇到问题是,因为截断点之前还有 commit 。会导致截断后除了 之后想要的 commit 线外。 branch1 branch2 不会被操作。保持原样。 分支混乱。。
Yancey
2016-08-08 10:35:06 +08:00
@zzn 背景是这样。 最开始一个主工程。然后 clone 了好几份工程作为不同的库(这个点我们暂定位 date 点)。后来这些库往不同业务发展。所以想将 date 点之前的所有 commit 删除。毕竟后来分成不同库了, date 之前和这些库完全没有啥关系。。
vitovan
2016-08-08 10:35:52 +08:00
r#15 @Yancey 嗯,刚才想说 --force 来着,如果不能让别人都接受 rebase ,好像确实有些难办:
http://stackoverflow.com/questions/8939977/git-push-rejected-after-feature-branch-rebase

`rebasing feature branches on master and force-pushing them back to remote repository is OK as long as you're the only one who works on that branch.`
jianyunet
2016-08-08 10:36:55 +08:00
既然都已经是公开项目了,在服务器端删掉也必须强推到各客户端啊。最简单的办法还是开一个新仓库做个 rebase
mengzhuo
2016-08-08 10:40:48 +08:00
@Yancey 公开项目只能另开,或者删了再来了。要不然其他人会拉不到原始 commit 各种报错的
bjzhou1990
2016-08-08 10:45:27 +08:00
@Yancey 用 git checkout --orphan 创建新分支,然后在新分支上开发,丢弃原始分支?
Yancey
2016-08-08 10:59:12 +08:00
@bjzhou1990 恩。是个好办法。
我测试还是遇到问题
1. 在服务端。我自己测试的时候是通过 git init --bare 来建仓库的,所以服务端 git checkout --orphan 命令没法使用。。
2. 服务端进行操作后,所有的本地仓库都要克隆一遍。。


我考虑的办法。
假设我们要截断的点 hash 值为 1234abc
在服务端:
echo 1234abc > info/grafts
git filter-branch -- --all
以及后续删除 grafts 和 gc 操作

写个脚本让所有本地克隆的都执行。内容大概是
echo 1234abc > .git/info/grafts
git filter-branch -- --all
删除 grafts
git fetch --all

目的是让本地和服务端改变一模一样。这样本地的分支。没有 push 的 commits 都可以保留


还是遇到问题

在服务端;
执行 git filter-branch -- --all 之前要将所有的 1234abc 之前的分支都删除。

在本地
git filter-branch -- --all 执行的时候 origin/xx 这种分支也会被操作。总之结果很混乱。不是想要的效果


看来真的是无解啊。。
jason19659
2016-08-08 10:59:25 +08:00
删除之后别人的项目跟你的肯定不是一个项目了。
subpo
2016-08-08 11:08:53 +08:00
迷之需求
bjzhou1990
2016-08-08 11:21:33 +08:00
@Yancey 所有 git 操作都应该是本地修改然后提交服务器,不要直接在服务器端修改啊。另外 git filter-branch 里的--all 意思是修改所有分支和 tag ,可以单独指定分支的吧?建议看看 git filter-branch --help ,文档很详细
kukat
2016-08-08 11:35:49 +08:00
@Yancey 编译跟.git 有什么关系?
SpicyCat
2016-08-08 11:45:20 +08:00
我觉得在做这个操作之前,先要反思下你们对 git 的使用。单纯的 git 提交历史长不不会显著增加 git repo 的大小,一般发现 git repo 突然增大,都是误添加了大文件。
因为 git history 太长觉得影响效率是误解。有些大项目,上万的 commit ,太稀松平常了。

具体到你的需求,你想删掉某个时间点以前的 commit ,是肯定能做到的, git rebase -i 就可以。但是那样做以后,我估计你的项目就出错了,因为必然有些文件是在某个 commit 被加进来的,然后你把那个 commit 删除了,那以后某个 commit 要修改那个文件,会出什么现象我也不知道。总之这样做隐患很大。
更不用说你想改的是服务器,会影响所有人,真是要慎重。

另外推荐一款清理 git repo 的工具 https://rtyley.github.io/bfg-repo-cleaner/
不过我一般是用它删除特定文件,可能不太符合你的需求。
Yancey
2016-08-08 12:05:03 +08:00
@SpicyCat 因为是 android 项目。我查了下大文件, 基本是图片或 jar 包。这些图片或 jar 包经过迭代现在很可能已经不再使用了,但是还在仓库历史里面。所以.git folder 比较大。

看来这问题是无解了。
Yancey
2016-08-08 12:05:51 +08:00
@kukat 编译没关系。。这不是编译服务器磁盘小么。装不下所有带.git 文件夹的工程了
9hills
2016-08-08 12:07:00 +08:00
rebase 可以只合并某个范围内的 commit 。但是修改后需要约定下所有人,同时重新拉取
mrcode
2016-08-08 12:20:07 +08:00
可以试试 revert 他会生成一个新的提交, 来抵消掉你指定的提交的更改. 然后 git 垃圾回收就回收掉没用的那部分了
SpicyCat
2016-08-08 12:22:43 +08:00
@Yancey 那么解决问题的方法就是确定哪些图片文件或者 jar 不需要了,利用 bfg(就是我上个回复提到的清理工具)清理一下。 bfg 是把目标文件彻底从 git repo 里删除。
SpicyCat
2016-08-08 12:23:23 +08:00
当然,最好还是新建一个 repo ,保留原有 repo 。
fy
2016-08-08 13:38:57 +08:00
翻出一篇笔记:

git clone git@github.com:jfinal/jfinal.git
git filter-branch --tree-filter 'rm -f WebRoot/WEB-INF/lib/*.jar' --tag-name-filter cat -- --all
git push origin --tags --force
git push origin --all --force

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/297802

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX