3

我有一个存储库已经变得太大以至于无法使用。基本上我的存储库超过 2GB,克隆时间太长。我现在想缩小它,但仍然可以回到某些特定的旧版本......缩小将涉及重写历史,所以我很好。有克隆的人将不得不在新的 repo 克隆中的新分支之上 rebase/cherrypick/copyfiles。

  • 我在这个存储库中有二进制文件,但我需要它们(将其视为软件运行的必需资源)。所以我不能真正使用 filter-branch 或BFG来删除一些大的二进制文件,因为在恢复到过去的提交时我可能需要它们。
  • 我不关心以前的旧/已经合并的分支(例如:功能分支),但我关心一些特定的提交(例如过去发布分支的负责人)
  • 由于我将修改(~many~)非常旧的提交,我现在不知道如何正确解决合并冲突(就像基本的 rebase/cherrypick 可能发生的那样)所以我正在寻找一个不会产生任何冲突的解决方案,或者只产生可以自动解决的冲突。
  • 我想保留所有当前的分支,以便在克隆上进行工作的人可以对它们进行 rebase/copychanges。
  • 我想在我的新提交之间拥有相关历史记录,以匹配旧回购的历史记录(就像提交被压扁一样)。当前分支的历史将从这些旧的压缩提交之一开始。

我认为它是不需要的旧存储库历史的壁球。到目前为止,我为我的案件提出的可能流程(我错过了一些步骤,但我仍然不确定这是否会达到我的想法)是:

  • 克隆现有仓库的镜像。
  • 从我想保留的旧提交创建孤立分支。这将创建包含所有需要的文件的无父压缩提交。
  • 以某种方式将它们链接到重新创建旧的回购历史 => 如何?合并/变基/重置+提交孤儿?
  • Cherrypick 每个当前分支的提交列表(使用间隔),并将它们应用于压缩其第一个分歧提交的父级的最新提交 => 如何自动找到将樱桃选择的提交间隔应用于哪个提交?这会在没有冲突的情况下工作吗?
  • 将标签移动到新树。删除以前的树。git 垃圾收集。

这在没有任何冲突的情况下可行/可行吗?这在任何情况下都有效(git commit tree 可能非常复杂)?有什么更好的安全和自动压缩历史的解决方案吗?

在我看来,这种类型的维护任务对于一个长期运行的项目来说会发生,所以我假设其他大型项目已经使用了某种类型的解决方案。但是我想可能有一个我不知道的 git init (或其他命令)选项,可以从旧仓库为此用例创建一个新仓库?

更新:我在这里找到了解决方案的开始:https ://wincent.com/wiki/Editing,_amending,_or_squashing_the_root_commit_in_a_Git_repository 但我想在我的历史记录中以全自动方式(即没有冲突)多次执行此操作。 .

4

3 回答 3

1

好的,经过几天的反复试验,这是我认为最好的解决方案:

1) 从您要用作新根的提交中,执行 acheckout --orphan创建一个孤立分支,并提交您为此版本更改的文件。

2) 对于您要保留的每个提交 C,checkout提交 C,reset到先前的新提交 B',提交以 B' 作为父提交以进行 C' 新提交。(感谢forvaidya的链接)

3) 您现在需要将现有分支重新链接到您保留的最后一次提交。在旧历史中找到该提交。从那里,列出所有将它(或其任何父级)作为直接父级的提交。然后,您可以使用新git replace --graft的提交来替换他们的旧父级。

不过,为此想出一个万无一失的脚本将非常有用……如果我这样做了,我会在这里发布。

警告:步骤 3) 仅在您使用 git 2.X 时有效。1.X git 客户端不会在提交图中看到更改。

于 2014-10-26T09:37:37.440 回答
1

您可以只克隆部分 repo:

git clone --depth depth 

这称为浅克隆。

这是不久前Atlassian 博客上的一篇文章,它提供了处理大型 repo 的其他策略。

于 2014-10-24T20:02:12.253 回答
0

Git 浅克隆是一个答案,但对于浅克隆,您无法推送。

就壁球而言,壁球仅适用于未发表的历史,此链接可能有用http://www.awanitech.com/git-squash.html

推送后完成的任何壁球都需要在不同的分支上提交,因为它不是 FF 推送。这种壁球不会对存储库大小产生影响。

如果你准备好强制推送(历史重写);然后你可以做过滤器分支并减小尺寸。

如果您的错误版本在完全不同的分支上;您可以创建一个 git 包并将其作为精简存储库。

于 2014-10-25T13:54:24.450 回答