18

所以我正在和一些朋友一起工作,我们都是 git 的新手,其中一个人提交了大量的外部二进制文件,这会减慢存储库的速度,并占用很大的磁盘空间。

我们刚刚开始了这个项目,所以除了一个自述文件之外,其中并没有什么重要的东西。所以我们想做的是将存储库历史清除为当前状态。

So basicly it looks this:

Head -> A -> B -> C    total disk size 45 MB, 1 file, 300 deleted files

And we want this:

Head -> A              total disk size 1 kB, 1 file, 0 deleted files

显而易见的解决方案是创建一个新的存储库,然后将自述文件复制到新的存储库中。但是,如果有 GIT 命令可以做到这一点,我想学习教育/好奇心。

我一直在尝试使用 Rebase 命令,但它似乎仍然保留旧历史及其数据,这让我感到困惑,因为如果 rebase 不会从存储库中删除数据,那么您最好不要使用它。

我一直在谷歌搜索有关此问题的其他帖子,并且我怀疑您无法使用 git 执行此操作。不过我想确认一下。

是的,它是 github 上的一个远程目录

谢谢你的帮助。

所以对于我的解决方案,我选择这样做:

rebase using tortoisegit
squash all commits
then using git bash:
git reflog expire --all --expire-unreachable=now
git gc --aggressive --prune=now
git push origin master --force

本地存储库历史似乎不想缩小磁盘大小。但是,再次克隆存储库会显示所需的结果和磁盘大小。存储库日志也是如此。

感谢您的帮助。有趣的 Rebase 似乎非常强大。

4

3 回答 3

12

变基(git rebase -i --root如果你没有恢复错误提交,只需删除它的行,如果你这样做了,用恢复提交压缩错误提交)或使用 filter-branch 将清除分支历史记录中的数据,但不会成功完全从存储库中消失。

这是因为,出于安全和可追溯性的原因,git 会保留一个 reflog(使用 可见git log -g)来跟踪您所做的每个提交,无论它是否仍然是祖先图的一部分。

克隆过滤后的 repo 不会克隆隐藏的数据,您也可以使用以下命令将其删除:

git reflog expire --all --expire-unreachable=now
git gc --aggressive --prune=now

通常不建议使用这些命令,并且未引用的提交无论如何都会在 30 天内到期,但由于您的存储库实际上是新的,因此您不会冒太大风险。

于 2013-04-17T10:32:16.277 回答
4

你不需要完全失去你的历史。您可以使用filter-branch. 这是一个非常具有破坏性的命令,因此请先复制一份。此示例将遍历您删除所有jar文件的历史记录。

git filter-branch --tree-filter 'git rm **/*.jar'

调整它以匹配意外添加的任何巨型文件。请注意,修改提交会更改其 ID,因此人们可能希望在此之后重新克隆存储库,以避免严重的冲突。您还需要--force推送回存储库,因为 git 会(正确地)抱怨历史发生了很大变化。

在决定进行垃圾收集之前,您的本地存储库可能不会立即缩小大小。

于 2013-04-17T10:26:45.303 回答
1

您可能想查看Squashing all Git commits into a single commit。这也引用了一个堆栈溢出问题——可能被称为重复问题——在这里:如何将所有 git 提交压缩为一个?

Wincent 在第一个链接中提到的解决方案大约位于页面的一半。在本地进行的快速测试表明它确实像宣传的那样工作。供您参考,Wincent 建议:

git update-ref -d refs/heads/master
git commit -m "Initial import"

FWIW,您可能需要运行git gc --prune=now以清理任何未引用的对象。当你推他新主人时,你需要使用--force. 在尝试任何这些之前,您可能应该创建一个备份。:-)

于 2013-04-17T10:29:18.893 回答