我有一个git存储库,当刚签出时,即使在最浅的配置中也需要大约2.3 GiB,其中1.9 GiB在.git/objects/pack
内。工作树文件只有.5 GiB。
考虑到我有一个遥控器,我可以根据需要重新获取所有对象,问题是:
.git
内部删除什么(以及如何),然后使用简单的git命令从遥控器安全地重新获取所有内容?稍微测试一下,我发现如果我删除.git/objects/pack/
下的所有内容,则会使用简单的git fetch
从遥控器重新下载。
有一些抱怨如下:
error: refs/heads/master does not point to a valid object!
error: refs/remotes/origin/master does not point to a valid object!
error: refs/remotes/origin/HEAD does not point to a valid object!
但随后.git/objects/pack
重新填充,并且git fetch
的进一步电话不再抱怨。
像这样核对.git/objects/pack*
这样安全吗?
假设:
目的是尽可能地减少工件从连续集成管道中占用的空间量,但保留足够的信息,以便可以在开发人员工作站中将这些工件下载并恢复到正常工作状态(和正常情况下)命令。
答案 0 :(得分:0)
删除.git/
中的内容只是打破了局面。它包含项目的完整历史记录,这些包文件是git如何节省空间的。有很多,更好的方法来减少你的回购的大小。
首先是运行垃圾收集,git gc
。这将做很多事情来减少磁盘上存储库的大小。你不应该这样,它会定期运行,但它可能会有所帮助。
如果没有,请尝试浅层克隆,只能获得历史记录的一部分。这只会克隆来自master
的最新100次提交。
git clone --depth=100 <remote>
同样,你可以克隆一个分支。
git clone --single-branch --branch master <remote>
稍后可以使用git-fetch
“深化”这些内容。
但最好的办法是减少回购的大小。 Git在太空中非常有效,而且演出非常多。它表明存储库中有很多非常大的二进制文件,图像,视频,电子表格和压缩文件...... git无法有效压缩。要处理此问题,有两个工具git-lfs(大文件支持)和BFG Repo Cleaner。
git-lfs允许您将旧版本的大型文件存储在云存储中,而不是存储在每个人的.git
目录中。这可以极大地减少存储库的大小......继续。
BFG Repo Cleaner可让您轻松重写历史记录,包括删除大文件的选项。
将它们组合在一起,您可以使用BFG Repo Cleaner将现有的大文件更改为使用git-lfs。这可以极大地减少存储库的大小。例如,这会将所有*.mp4
更改为使用git-lfs。
$ java -jar ~/bfg-1.12.15.jar --convert-to-git-lfs '*.mp4' --no-blob-protection
Instructions for that can be found here
另一个重要的事情是 不压缩文件 。你提到了持续集成工件,我愿意打赌它们是压缩的。 Git将自己进行更高效的压缩,并且它可以确保历史记录中只有一个文件的副本,但它只能在文本上执行。在提交之前解压缩tarball和zipfiles。
如果绝对无法减小存储库的大小,那么剩下的选择就是让每个人共享一个.git
目录。您可以使用--git-dir
选项或设置GIT_DIR
。
git --git-dir=/path/to/the/.git log
这是 糟糕的 主意。虽然每个人都可以拥有自己的结账,但他们都将共享相同的存储库状态。如果一个开发者进行了更改,其他开发人员将会看到它,但现在使用不同的工作目录。
例如,dev1添加了一个文件。
$ touch this
$ GIT_DIR=~/tmp/foo/.git git add this
$ GIT_DIR=~/tmp/foo/.git git st
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: this
然后dev2突然看到了这一点。
$ GIT_DIR=~/tmp/foo/.git git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: this
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: this
他们共享相同的暂存区域,但不是相同的工作副本。开发者将不断绊倒对方。
如果git clone --depth=1
仍然产生太大的回购,那么每次结账时只会有很多数据。你无能为力。如果浅层克隆上的.git
是2演出,那么结帐将会更大。
至于在.git
上进行手术的想法,也许你可以通过删除一些对象来逃避,并希望git fetch --deepen
可以修复它,但是在多个开发者中保持这个...这是一个维护噩梦。
此时,您可以完全删除.git
。现在您已经有效地导出了最新的提交。 There's various ways to do this directly
或者只是停止浪费时间和金钱并购买更大的硬盘。花在这上面的每个人小时都是你可以购买的硬盘。
答案 1 :(得分:0)
尽可能地减少工件从连续集成管道中占用的空间量,但保留足够的信息,以便可以在开发人员工作站中将这些工件下载并恢复到正常工作状态(和正常情况一样) )命令尽可能
我不完全了解您的情况,但一种经常被遗忘的减少网络数据大小和服务器内存使用的方法是:
--reference <path>
。在正常的开发条件下(文本文件,并非每次提交都更新它们的所有fof),它比使用浅克隆更有效。
至于你提出的问题,我认为尝试保存从存储库中删除任何内容是没有意义的。大多数数据用于包装,这是必需的,休息是无关紧要的。
PS:存储库只能通过git本身在临时存储中初始化:
CACHE_REPO=/tmp/repo
if ![ -d "$CACHE_REPO" ]; then
git clone --single-branch --no-checkout --branch=_BRANCH_ _REMOTE_ "$CACHE_REPO"
fi
_BRANCH_
是master
或您肯定不会强行推进的其他分支。你可以试着把它变浅,它可能会也可能不会起作用,我不确定。
答案 2 :(得分:0)
- 我可以从内部删除什么(以及如何).git我可以使用简单的git命令从遥控器安全地重新获取所有内容吗?
如果您不想担心.git
的内部以及某些内容是否可恢复,您可以保存足够的信息以再次检查它,并将工作区恢复到功能类似的状态比在CI中运行时管道
在这样的文件中添加(让我们称之为degit.sh
)
#!/bin/bash
set -ex
GIT_REMOTE=$( git remote get-url origin )
GIT_BRANCH=$( git rev-parse --abbrev-ref HEAD )
GIT_COMMIT=$( git rev-parse HEAD )
# TABs, not spaces, indenting the block below:
cat <<-EOF > .gitrestore
set -ex
test ! -e .git
tmpclone=\$( mktemp -d --tmpdir=. )
git clone $GIT_REMOTE -n --branch=$GIT_BRANCH \$tmpclone
( cd \$tmpclone ; git reset --hard $GIT_COMMIT )
mv \$tmpclone/.git .
rm -rf "\$tmpclone"
rm -f \$0
EOF
rm -rf .git
然后,在您的Continous Integration(C.I。)工作空间的每个git repos的根目录中,调用它以便生成.gitrestore
文件。
看起来像这样:
set -ex
test ! -e .git
tmpclone=$( mktemp -d --tmpdir=. )
git clone git@example.com:example/repo.git -n --branch=example-branch $tmpclone
mv $tmpclone/.git .
git reset --hard example-commit-hash
rm -rf "$tmpclone"
rm -f $0
请注意,成功运行后它会自行破坏。你不想运行它两次。
现在您的开发人员可以获取C.I.每个存储库中的工件和运行:
bash .gitrestore
它的存储库看起来非常像C.I.管道有,除了遥控器的更新视图,它允许开发人员比较C.I.她拥有的东西。
这假设只有C.I.机器受空间限制,而不是开发人员机器(她的带宽都没有)。
如果要在开发人员端节省空间/带宽,可以传递--depth=1
,它将仅克隆指定的分支(即,它隐含--single-branch
并将历史记录限制为单个提交。