删除.git目录中可重新下载的所有信息

删除.git目录中可重新下载的所有信息,git,Git,我有一个git存储库,当刚签出时,即使在最浅的配置中也需要大约2.3 GiB,其中1.9 GiB位于.git/objects/pack内。工作树文件大约为.5 GiB 考虑到我有一个遥控器,如果需要,我可以从中重新获取所有对象,问题是: 我可以从.git内部删除哪些内容(以及如何删除),然后使用简单的git命令从远程安全地重新获取这些内容 经过一点测试,我发现如果我删除.git/objects/pack/下的所有内容,它将通过一个简单的git fetch从远程重新下载 有些投诉如下: err

我有一个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*
安全吗

假设:

  • 在repo或任何形式的git操作(比如在stage中添加/删除对象)中没有仅本地提交,只是在浅层模式下签出特定的分支
  • 远程服务器不会重写签出分支的历史记录
  • 我无法控制远程存储库本身的内容。这是我的项目的一个依赖项,但它是一个快速变化的依赖项,只能作为git使用,我需要在持续集成设置中自动使用的说明。关于如何修改存储库本身以使其占用更少空间的提示不会有帮助
  • 正如我前面提到的,1.9Gib是我感兴趣的一个分支的浅克隆。由于它的历史很长(开源项目已经有10多年了),所以它比非浅层的时候要大得多
  • 在同一个持续集成管道中还签出了其他存储库,我希望在所有这些存储库中应用相同的冗余减少和远程信息

其目的是尽可能减少工件从连续集成管道占用的空间量,但保留足够的信息,以便在开发人员工作站上下载这些工件并将其恢复到正常工作状态,所需的时间尽可能少(并且尽可能正常)尽可能使用命令。

删除
.git/
中的内容只会破坏一切。它包含项目的完整历史记录,这些包文件是git节省空间的方式。有很多更好的方法来减少回购的规模

首先是运行垃圾收集,
gitgc
。这将有助于减少磁盘上存储库的大小。您不必这样做,它会定期运行,但可能会有所帮助

如果没有,尝试一个浅层克隆,在那里你只能得到部分历史。这仅从
master
克隆最近的100次提交

git clone --depth=100 <remote>

另一件重要的事情是不要压缩文件。你提到了持续集成工件,我敢打赌它们是压缩的。Git将自己进行更高效的压缩,它可以确保历史上只有一个文件副本,但它只能对文本进行压缩。在提交之前,打开柏油球和拉链


如果您绝对无法减小存储库的大小,那么剩下的选项是让每个人共享一个
.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
$点击此按钮
$GIT\u DIR=~/tmp/foo/.GIT GIT添加这个
$GIT\u DIR=~/tmp/foo/.GIT GIT st
论分行行长
要提交的更改:
(使用“git重置磁头…”取消分级)
新文件:这个
然后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\u DIR=~/tmp/foo/.GIT-GIT-status
论分行行长
要提交的更改:
(使用“git重置磁头…”取消分级)
新文件:这个
未为提交而暂存的更改:
(使用“git add/rm…”更新将提交的内容)
(使用“git签出--…”放弃工作目录中的更改)
删除:本
他们共享相同的暂存区域,但不是相同的工作副本。开发人员将不断地互相绊倒


如果git clone--depth=1仍在生成太大的回购,那么每次签出中都有大量数据。你对此无能为力。如果浅克隆上的
.git
是2 Gig,那么签出量将更大

至于在
.git
上执行手术的想法,也许您可以删除一些对象,并希望
git fetch--deependent
可以修复它,但在多个开发人员之间保持这个功能。。。这是一场维护噩梦

此时,您不妨完全删除
.git
。现在您已经有效地导出了最新的提交

或者停止浪费时间和金钱,买更大的硬盘。花在这上面的每一个人小时都是你本可以买到的硬盘

尽可能减少工件从连续集成管道占用的空间量,但保留足够的信息,以便在开发人员工作站上下载这些工件并将其恢复到工作状态,所需的命令尽可能少(且尽可能正常)

我不完全理解您的情况,但减少网络数据大小和服务器内存使用的一种经常被遗忘的方法是:

  • 分发一些稳定的存储库(只包括未重写的分支),然后
  • 克隆时使用use
    --reference
正常发展公司
$ 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
$ 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
CACHE_REPO=/tmp/repo
if ![ -d "$CACHE_REPO" ]; then
  git clone --single-branch --no-checkout --branch=_BRANCH_ _REMOTE_ "$CACHE_REPO"
fi
#!/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
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
bash .gitrestore