由于二进制测试文件和java git
文件的历史包含,我们有许多.jar
存储库已经增长到难以管理的大小。
我们正要进行git filter-branch
这些存储库的练习,在它们被使用的任何地方重新克隆它们(从每个部署数十次到数百次,取决于回购)并给予{{3我想知道是否还有其他解决方案。
理想情况下,我想在不重写每个存储库的历史记录的情况下将问题文件外部化。理论上这应该是可能的,因为你检查相同的文件,具有相同的大小和相同的哈希值,只是从不同的地方(远程而不是本地对象存储)获取它们。到目前为止,我找到的任何潜在解决方案似乎都不允许我这样做。
从problems with rewriting history开始,我能找到最接近问题解决方案的是git-annex,但就像删除大文件一样,这需要重新编写历史记录来转换原始git add
成git annex add
。
从那里开始,我开始查看How to retroactively annex a file already in a git repo上列出的其他项目,因此我检查了what git-annex is not,git-bigfiles和git-media。不幸的是,我们不能使用git
的 git-bigfiles 分支,因为我们是Eclipse 商店,并使用git
和{{的混合3}}。它看起来不像 git-media 或 git-fat </ em>也可以做我想要的,因为虽然你可以用外部等价物替换现有的大文件,但你仍然会需要重写历史记录才能删除已经提交的大文件。
那么,是否可以在不重写历史记录的情况下缩小.git存储库,或者我们是否应该回到使用git filter-branch
和一大堆重新部署的计划?
顺便说一下,相信这个应该可能,但可能与git
当前git-fat实施的限制相同。
Git已经支持同一个blob的多个可能位置,因为任何给定的blob都可以在EGit(.git/objects
)或shallow clone(.git / objects)中,所以理论上您只需要将git-annex
这样的内容挂钩到该级别而不是更高级别(例如,如果您愿意,可以按需下载概念远程blob )。不幸的是,我找不到任何人已经实施或甚至建议这样的事情。
答案 0 :(得分:9)
排序。您可以使用Git's replace feature来保留大膨胀历史记录,以便仅在需要时下载。它就像一个浅层克隆,但没有浅层克隆的限制。
这个想法是你通过创建一个新的root提交来重新启动分支,然后挑选旧分支的提示。通常,您会以这种方式丢失所有历史记录(这也意味着您不必克隆那些大.jar
个文件),但如果需要历史记录,您可以获取历史提交并使用git replace
将它们无缝地缝合在一起。
有关详细说明和演练,请参阅Scott Chacon's excellent blog post。
这种方法的优点:
.jars
和所有内容,你仍然可以。这种方法的缺点:
这种方法仍有一些与重写历史相同的问题。例如,如果您的新存储库如下所示:
* modify bar (master)
|
* modify foo <--replace--> * modify foo (historical/master)
| |
* instructions * remove all of the big .jar files
|
* add another jar
|
* modify a jar
|
并且有人在他们合并的历史分支中有一个旧分支:
* merge feature xyz into master (master)
|\__________________________
| \
* modify bar * add feature xyz
| |
* modify foo <--replace--> * modify foo (historical/master)
| |
* instructions * remove all of the big .jar files
|
* add another jar
|
* modify a jar
|
然后,大型历史提交将重新出现在您的主存储库中,并且您将返回到您开始的位置。请注意,这并不比重写历史记录更糟糕 - 有人可能会在预重写提交中意外合并。
可以通过在共享存储库中添加update
挂钩来拒绝任何会重新引入历史根提交的推送。
答案 1 :(得分:8)
不,这是不可能的 - 您将不得不重写历史记录。但是这里有一些指示:
git filter-branch
更容易使用。您无需再次克隆!只需运行这些命令而不是git pull
,您就可以了(用您的远程和分支替换origin
和master
):
git fetch origin
git reset --hard origin/master
但请注意,与git pull
不同,您将丢失尚未推送到服务器的所有本地更改。
git pull
,git merge
和git rebase
(以及{{1} })。然后让每个人都参与一个关于如何处理这种重写情况的快速培训(5-10分钟应该足够了,基本的注意事项和不应该)。git rebase --onto
本身不会造成任何伤害,但会导致许多标准工作流程造成伤害。如果人们没有采取相应行动并合并旧历史,如果你不及时注意到,你可能只需要重新编写历史记录。答案 2 :(得分:4)
我不知道可以避免重写历史的解决方案。
在这种情况下,使用 BFG- repo cleaner 等工具清理rpeo是最简单的解决方案(git filter-branch
更容易)。
答案 3 :(得分:2)
老实说,我想不出办法做到这一点。如果你考虑Git“承诺”你作为一个用户,关于数据完整性,我想不出你可以从存储库中删除文件并保持相同的哈希的方法。换句话说,如果你问的是可能的,那么Git的可靠性就会低得多......