问题在于:
我在我的托管合作伙伴处创建了裸git存储库,我将其用作我维护项目的所有位置/计算机的参考存储库。
问题是我的项目正在使用sqlite db文件,该文件会不断增长(目前大约为150MB)。 随着时间的推移,我的.git文件夹越来越大(最近大约1GB)。我的托管空间有限。
我需要裸存储库来包含此db文件的HEAD版本,但我真的不需要保留其版本历史记录。
因此,为了获得一些空间,我不时会从历史记录中删除db文件,清理存储库并重新创建裸版本。这很有效,但是非常痛苦。
有没有办法告诉git只保留文件的最后一个版本并删除它的历史记录?
答案 0 :(得分:5)
简答:不。
更有用的答案:Git不会单独跟踪文件,因此要求它丢弃单个文件的历史记录意味着它必须在每次提交时完全重写其所有历史记录,这会导致所有类型丑陋的问题。
您可以将文件存储在带注释的标签中,但这不是很方便。它基本上是这样的:
ID=`git hash-object -w yourfile.sqlite`
git tag -a -m "Tag database file" mytag $ID
这绝不会为您在工作树中方便地更新(甚至创建)数据库文件...您必须使用钩子脚本来模拟它。
完全披露:我不完全确定是否实际上可以推送未被正常历史记录覆盖的标记blob。我怀疑它不是,在这种情况下,这个配方会比实用的要少得多。
答案 1 :(得分:4)
听起来你正在寻找解决错误问题的方法。
大型二进制文件通常需要存储在存储库中,但我不认为SQLite数据库是您真正需要以二进制形式存储在存储库中的。
相反,您应该将模式保留在版本控制中,如果您还需要保留数据,请将其序列化(格式化为XML,JSON,YAML ...)和版本。构建脚本可以创建数据库,并在必要时将数据反序列化。
由于Git可以有效地跟踪基于文本的序列化格式,因此即使您认为不需要访问它们,也不必担心保留过去版本的空间开销。
答案 2 :(得分:3)
您可以从头开始使用.gitignore
配置文件。
而且......(来自this thread:BjörnSteinbrink的荣誉!)
使用filter-branch删除父项 在你要保留的第一次提交时, 然后放弃旧的残骸。
假设
$drop
是哈希值 你要放弃的最新提交。至 保持理智和简单,确保 你要保留的第一个提交, 即。$drop
的孩子不是合并 承诺。然后你可以使用:git filter-branch --parent-filter "sed -e 's/-p $drop//'" \ --tag-name-filter cat -- \ --all ^$drop
以上重写了所有人的父母 提交“后”
$drop
。使用gitk检查结果。
然后,清理所有旧的残骸。
首先,备份引用来自 filter-branch:
git for-each-ref --format='%(refname)'refs/original | \ while read ref do git update-ref -d "$ref" done
然后清理您的reflog:
git reflog expire --expire=0 --all
最后,重新包装并放弃所有 旧的无法访问的对象:git repack -ad git prune#对于重新包装的对象-ad可能已经遗留下来
那时,一切都在前进 包括$ drop应该是 走了。
答案 3 :(得分:0)
如果我理解你的问题,我想我有一个简单的解决方案。
在后续提交中,GIT将不再尝试添加该文件。请注意,您仍将在先前的提交中存储该文件。只是你不会将它添加到你将来做的每一个提交中。为了从之前的提交中删除它,您需要具有比我更多GIT经验的人的建议。
答案 4 :(得分:0)
将sqlite.db添加到.gitignore。
使用当前分支签入当前数据库以进行(潜在)推送:
branch="$(sed 's,.*refs/heads/,,' "$(git rev-parse --git-dir)"/HEAD)"
objectname=$(git hash_object -w "$(git rev-parse --show-toplevel)/sqlite.db")
git tag -f db_heads/$branch $objectname
推动分支时:
git push origin $branch +db_heads/$branch
获取分支时:
git fetch origin $branch tags/db_heads/$branch:tags/db_heads/$branch
签出分支时:
git checkout $branch
git cat-file -p db_heads/$branch >"$(git rev-parse --show_toplevel)/sqlite.db"
我认为应该这样做。