是否可以将未版本控制的文件保存在git存储库中

时间:2010-02-12 13:15:04

标签: git

问题在于:

我在我的托管合作伙伴处创建了裸git存储库,我将其用作我维护项目的所有位置/计算机的参考存储库。

问题是我的项目正在使用sqlite db文件,该文件会不断增长(目前大约为150MB)。 随着时间的推移,我的.git文件夹越来越大(最近大约1GB)。我的托管空间有限。

我需要裸存储库来包含此db文件的HEAD版本,但我真的不需要保留其版本历史记录。

因此,为了获得一些空间,我不时会从历史记录中删除db文件,清理存储库并重新创建裸版本。这很有效,但是非常痛苦。

有没有办法告诉git只保留文件的最后一个版本并删除它的历史记录?

5 个答案:

答案 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)

如果我理解你的问题,我想我有一个简单的解决方案。

  1. 首先将文件备份到某处,
  2. 从工作目录/树中删除它。不是git rm,只是rm。
  3. 做一个提交。
  4. 确保将文件添加到.gitignore。
  5. 在后续提交中,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"

我认为应该这样做。