如何将已经克隆的Git代码库转换为浅层存储库?
该Git代码库是通过我的控制范围之外的脚本下载的,因此我无法进行浅层克隆。
这样做的原因是为了节省磁盘空间。(是的,我的磁盘空间非常有限,因此即使一个浅层存储库节省的空间不多,也是必须的。)
我已经尝试过
git repack -a -d -f -depth=1
但实际上,这使得存储库变得更大了。
如何将已经克隆的Git代码库转换为浅层存储库?
该Git代码库是通过我的控制范围之外的脚本下载的,因此我无法进行浅层克隆。
这样做的原因是为了节省磁盘空间。(是的,我的磁盘空间非常有限,因此即使一个浅层存储库节省的空间不多,也是必须的。)
我已经尝试过
git repack -a -d -f -depth=1
但实际上,这使得存储库变得更大了。
首先,您可能需要删除标签(因为它们会阻止已标记提交的垃圾回收),例如:
git tag -d $(git tag -l)
然后,这对我起作用了:
git pull --depth 1
git gc --prune=all
这仍然会留下 reflog,就像标签引用其他可能占用空间的提交一样。请注意,除非必须,否则不要删除 reflog:它包含用于从错误中恢复的本地更改历史记录。
下面的注释中有关于如何删除 reflog 的其他命令,以及一个类似问题的链接,其中有更长的答案。
如果您仍然使用了大量空间,请确保已删除标签,这应该是在删除 reflog 之前首先尝试的。
git log
只显示一个提交,git branch
只显示一个分支)。但是.git
文件夹仍占用2.5 GB的空间。使用--depth 1
克隆的同一存储库大约占用1 GB的空间。你有什么建议来减少磁盘使用量吗? - Dzmitry--prune=all
来进行垃圾回收。这会立即删除多余的对象。 - fuzzyTewgit pull --depth=1
命令会保留非 HEAD 标签,这些标签不会被 git gc --prune=all
命令删除。我需要使用 git tag -d $(git tag -l)
命令来垃圾回收这些引用。 - v1brigit reflog expire --expire=all --all
。这个命令被推荐在 https://dev59.com/5loT5IYBdhLWcg3wxx3g。另外,上面提到的 git tag
命令也是必需的。 - Wayne Piekarski您可以按照以下方法将git仓库转换为浅仓库:
git show-ref -s HEAD > .git/shallow
git reflog expire --expire=0
git prune
git prune-packed
在进行这个具有破坏性的操作之前,请务必备份。同时请注意,不支持从浅层仓库进行克隆或提取!要真正地删除所有历史记录,您还需要在修剪之前删除对先前提交的所有引用。
.git
文件到git目录(git rev-parse --git-dir
)。此外,您可以使用git describe --always HEAD~5
代替show-ref -s HEAD
来保留最新的提交。
同时,还有git fetch --unshallow
来取消浅克隆。 - blueyedgit prune
已经执行了 git prune-packed
。同时请注意,如果您希望存储所有分支,它们必须在 .git/shallow
文件中列出其 tip。以下命令适用于我,但我不知道它是否始终有效:find .git/refs -type f | xargs cat | sort -u > .git/shallow
。 - fuzzyTewgit prune
命令之前,您可能需要从 .git/packed-refs
中删除不必要的引用。 - ryenus从特定日期开始转换为浅层复制:
git pull --shallow-since=YYYY-mm-dd
git gc --prune=all
同样适用:
git fetch --shallow-since=YYYY-mm-dd
git gc --prune=all
git fetch --depth 1; git gc --aggressive --prune=all
也起作用了。这样做似乎相当于使用 git clone --depth 1
进行浅克隆。 - Night Train你目前不在任何分支上。 请指定您要反基于哪个分支。
的信息。 - rubo77创建本地 repo 的浅克隆:
git clone --depth 1 file:///full/path/to/original/dir destination
请注意,第一个“address”应该是file://
,这很重要。此外,git将假定您的原始本地文件file://
地址为“remote”(“origin”),因此您需要更新新存储库并指定正确的git remote
。
将@fuzzyTew的回答和该回答下的评论结合起来:
git pull --depth 1
git tag -d $(git tag -l)
git reflog expire --expire=all --all
git gc --prune=all
想要在整个磁盘上运行此命令以节省空间吗?- 那么请运行此fd
命令:
fd -HIFt d '.git' -x bash -c 'pushd "$0" && ( git pull --depth 1; git tag -d $(git tag -l); git reflog expire --expire=all --all; git gc --prune=all ) && popd' {//}
或者只使用常规的find
命令:
find -type d -name '.git' -exec bash -c 'pushd "${0%/*}" && ( git pull --depth 1; git tag -d $(git tag -l); git reflog expire --expire=all --all; git gc --prune=all ) && popd' {} \;
git clone --depth 1
将现有仓库转换为浅仓库的方式)在执行git repack
时可能会失败。dscho
)完成。gitster
--于提交 ea100b6中合并,2018年11月6日)
repack -ad
: prune the list of shallow commits
git repack
can drop unreachable commits without further warning, making the corresponding entries in.git/shallow
invalid, which causes serious problems when deepening the branches.One scenario where unreachable commits are dropped by
git repack
is when agit fetch --prune
(or even agit fetch
when a ref was force-pushed in the meantime) can make a commit unreachable that was reachable before.Therefore it is not safe to assume that a
git repack -adlf
will keep unreachable commits alone (under the assumption that they had not been packed in the first place, which is an assumption at least some of Git's code seems to make).This is particularly important to keep in mind when looking at the
.git/shallow
file: if any commits listed in that file become unreachable, it is not a problem, but if they go missing, it is a problem.
One symptom of this problem is that a deepening fetch may now fail with:fatal: error in object: unshallow <commit-hash>
To avoid this problem, let's prune the shallow list in
git repack
when the-d
option is passed, unless-A
is passed, too (which would force the now-unreachable objects to be turned into loose objects instead of being deleted).
Additionally, we also need to take--keep-reachable
and--unpack-unreachable=<date>
into account.Note: an alternative solution discussed during the review of this patch was to teach
git fetch
to simply ignore entries in.git/shallow
if the corresponding commits do not exist locally.
A quick test, however, revealed that the.git/shallow
file is written during a shallow clone, in which case the commits do not exist, either, but the "shallow" line does need to be sent.
Therefore, this approach would be a lot more finicky than the approach presented by the this patch.
git gc
命令会发生什么? - VonC