git gc:设备上没有剩余空间,尽管有3GB可用空间,而tmp_pack只有16MB

4xrmg8kj  于 2022-11-20  发布在  Git
关注(0)|答案(4)|浏览(336)
> git gc --aggressive --prune=now
Counting objects: 68752, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (66685/66685), done.
fatal: sha1 file '.git/objects/pack/tmp_pack_cO6T53' write error: No space left on device
  • 叹息,好吧 *
df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        19G   15G  3.0G  84% /
udev            485M  4.0K  485M   1% /dev
tmpfs            99M  296K   99M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            494M     0  494M   0% /run/shm
cgroup          494M     0  494M   0% /sys/fs/cgroup
  • 看起来没那么糟 *
ls -lh .git/objects/pack/
total 580M
-r--r--r-- 1 foouser root  12K Oct 30 05:47 pack-0301f67f3b080de7eb0139b982fa732338c49064.idx
-r--r--r-- 1 foouser root 5.1M Oct 30 05:47 pack-0301f67f3b080de7eb0139b982fa732338c49064.pack
-r--r--r-- 1 foouser root 5.1K Oct 14 10:51 pack-27da727e362bcf2493ac01326a8c93f96517a488.idx
-r--r--r-- 1 foouser root 100K Oct 14 10:51 pack-27da727e362bcf2493ac01326a8c93f96517a488.pack
-r--r--r-- 1 foouser root  11K Oct 25 10:35 pack-4dce80846752e6d813fc9eb0a0385cf6ce106d9b.idx
-r--r--r-- 1 foouser root 2.6M Oct 25 10:35 pack-4dce80846752e6d813fc9eb0a0385cf6ce106d9b.pack
-r--r--r-- 1 foouser root 1.6M Apr  3  2014 pack-4dcef34b411c8159e3f5a975d6fcac009a411850.idx
-r--r--r-- 1 foouser root 290M Apr  3  2014 pack-4dcef34b411c8159e3f5a975d6fcac009a411850.pack
-r--r--r-- 1 foouser root  40K Oct 26 11:53 pack-87529eb2c9e58e0f3ca0be00e644ec5ba5250973.idx
-r--r--r-- 1 foouser root 6.1M Oct 26 11:53 pack-87529eb2c9e58e0f3ca0be00e644ec5ba5250973.pack
-r--r--r-- 1 foouser root 1.6M Apr 19  2014 pack-9d5ab71d6787ba2671c807790890d96f03926b84.idx
-r--r--r-- 1 foouser root 102M Apr 19  2014 pack-9d5ab71d6787ba2671c807790890d96f03926b84.pack
-r--r--r-- 1 foouser root 1.6M Oct  3 10:12 pack-af6562bdbbf444103930830a13c11908dbb599a8.idx
-r--r--r-- 1 foouser root 151M Oct  3 10:12 pack-af6562bdbbf444103930830a13c11908dbb599a8.pack
-r--r--r-- 1 foouser root 4.7K Oct 20 11:02 pack-c0830d7a0343dd484286b65d380b6ae5053ec685.idx
-r--r--r-- 1 foouser root 125K Oct 20 11:02 pack-c0830d7a0343dd484286b65d380b6ae5053ec685.pack
-r--r--r-- 1 foouser root 6.2K Oct  2 15:38 pack-c20278ebc16273d24880354af3e395929728481a.idx
-r--r--r-- 1 foouser root 4.2M Oct  2 15:38 pack-c20278ebc16273d24880354af3e395929728481a.pack
-r--r--r-- 1 root          root  16M Feb 27 08:19 tmp_pack_cO6T53

所以,git gc在一个只有16 MB大的临时包上失败了,而我的磁盘似乎有3GB的空闲空间。我错过了什么?我怎样才能让git gc更可靠地工作?我试过没有积极的选项,也用--prune代替--prune=now,同样的情况。

更新

在repack操作期间执行df -h,它显示它现在正在使用我的所有磁盘(100%的使用率)。过了一会儿,repack操作失败了,它在.git/objects/pack/文件夹中留下了另一个14 MB的文件。我的包总共用了580 MB。git repack不知怎么的用掉了3GB来重新打包。顺便说一句,完成后我还有~ 800 MB的空闲内存。-也许是吧'What“使用了太多的工作内存,以至于阻塞了交换?我想我的问题可以归结为:有没有选项可以让git重新打包的资源消耗更少?
版本:Ubuntu 12.04上的git版本1.7.9.5

更新2我已经把git更新到2.3版了。不幸的是没有任何改变。

> git --version
git version 2.3.0
> git repack -Ad && git prune
Counting objects: 68752, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (36893/36893), done.
fatal: sha1 file '.git/objects/pack/tmp_pack_N9jyVJ' write error: No space left on device

更新3

好了,我刚才注意到一件很奇怪的事:.git目录实际使用的磁盘空间比以前报告的508 MB要多得多。

> du -h -d 1 ./.git
8.0K    ./.git/info
40K ./.git/hooks
24M ./.git/modules
28K ./.git/refs
4.0K    ./.git/branches
140K    ./.git/logs
5.0G    ./.git/objects
5.0G    ./.git

经过进一步检查,.git/objects/pack实际上使用了4.5GB。差异在于隐藏的临时文件,我以前没有注意到:

ls -lha ./.git/objects/pack/
total 4.5G
drwxr-xr-x   2 foouser root  56K Feb 27 15:40 .
drwxr-xr-x 260 foouser root 4.0K Oct 26 14:24 ..
-r--r--r--   1 foouser root  12K Oct 30 05:47 pack-0301f67f3b080de7eb0139b982fa732338c49064.idx
-r--r--r--   1 foouser root 5.1M Oct 30 05:47 pack-0301f67f3b080de7eb0139b982fa732338c49064.pack
-r--r--r--   1 foouser root 5.1K Oct 14 10:51 pack-27da727e362bcf2493ac01326a8c93f96517a488.idx
-r--r--r--   1 foouser root 100K Oct 14 10:51 pack-27da727e362bcf2493ac01326a8c93f96517a488.pack
-r--r--r--   1 foouser root  11K Oct 25 10:35 pack-4dce80846752e6d813fc9eb0a0385cf6ce106d9b.idx
-r--r--r--   1 foouser root 2.6M Oct 25 10:35 pack-4dce80846752e6d813fc9eb0a0385cf6ce106d9b.pack
-r--r--r--   1 foouser root 1.6M Apr  3  2014 pack-4dcef34b411c8159e3f5a975d6fcac009a411850.idx
-r--r--r--   1 foouser root 290M Apr  3  2014 pack-4dcef34b411c8159e3f5a975d6fcac009a411850.pack
-r--r--r--   1 foouser root  40K Oct 26 11:53 pack-87529eb2c9e58e0f3ca0be00e644ec5ba5250973.idx
-r--r--r--   1 foouser root 6.1M Oct 26 11:53 pack-87529eb2c9e58e0f3ca0be00e644ec5ba5250973.pack
-r--r--r--   1 foouser root 1.6M Apr 19  2014 pack-9d5ab71d6787ba2671c807790890d96f03926b84.idx
-r--r--r--   1 foouser root 102M Apr 19  2014 pack-9d5ab71d6787ba2671c807790890d96f03926b84.pack
-r--r--r--   1 foouser root 1.6M Oct  3 10:12 pack-af6562bdbbf444103930830a13c11908dbb599a8.idx
-r--r--r--   1 foouser root 151M Oct  3 10:12 pack-af6562bdbbf444103930830a13c11908dbb599a8.pack
-r--r--r--   1 foouser root 4.7K Oct 20 11:02 pack-c0830d7a0343dd484286b65d380b6ae5053ec685.idx
-r--r--r--   1 foouser root 125K Oct 20 11:02 pack-c0830d7a0343dd484286b65d380b6ae5053ec685.pack
-r--r--r--   1 foouser root 6.2K Oct  2 15:38 pack-c20278ebc16273d24880354af3e395929728481a.idx
-r--r--r--   1 foouser root 4.2M Oct  2 15:38 pack-c20278ebc16273d24880354af3e395929728481a.pack
-r--r--r--   1 root          root 1.1K Feb 27 15:37 .tmp-7729-pack-00447364da9dfe647c89bb7797c48c79589a4e44.idx
-r--r--r--   1 root          root  14M Feb 27 15:29 .tmp-7729-pack-00447364da9dfe647c89bb7797c48c79589a4e44.pack
-r--r--r--   1 root          root 1.1K Feb 27 15:32 .tmp-7729-pack-020efaa9c7caf8b792081f89b27361093f00c2db.idx
-r--r--r--   1 root          root  41M Feb 27 15:30 .tmp-7729-pack-020efaa9c7caf8b792081f89b27361093f00c2db.pack
-r--r--r--   1 root          root 1.1K Feb 27 15:37 .tmp-7729-pack-051980133b8f0052b66dce418b4d3899de0d1342.idx
(continuing for a *long* while).

现在我很想知道:删除这些文件安全吗?

tkclm6bt

tkclm6bt1#

这是我目前的发现:我在.git/objects/pack文件夹中找不到任何关于这些隐藏的.“tmp-XXXX-pack”的文档。我能找到的所有其他线程都是关于同一文件夹中带有tmp_前缀的 * 非隐藏 * 文件。隐藏的文件显然也是在重新打包操作中创建的,这些文件也有可能被卡住。我不能确定这在git 2.3.0中是否仍然可能(我已经更新了),但至少磁盘空间的要求在这个新版本中似乎没有改变-它仍然不能完成gc/repack。通过删除这些. tmp文件,我能够恢复我最后的4GB,git似乎仍然表现良好-你的结果可能会有所不同,所以请确保你在这样做之前有一个备份.最后,即使是4GB也不足以重新打包gc --agressive。我的.git文件夹在清理后是1.1GB,我的整个存储库是1.7GB。所以2倍的存储库大小对于git gc来说可能是不够的,即使使用了激进的选项(应该可以保存空间)。所以我必须首先从其他地方恢复更多的空间。
下面是我用来清理的命令(同样,要有备份!):

git gc --aggressive --prune=now || rm -f .git/objects/*/tmp_* && rm -f .git/objects/*/.tmp-*
mpbci0fu

mpbci0fu2#

类似场景(大约2.3G可用),不同之处在于git gc本身也会因fatal: Unable to create '/home/ubuntu/my-app-here/.git/gc.pid.lock': No space left on device而失败
有效的方法是先运行git prune,然后运行gc。

j2qf4p5b

j2qf4p5b3#

我曾经遇到过这样的问题,我释放了大量的磁盘空间,但当然,这并没有解决如何处理.tmp-* 文件的问题。我运行了git fsck,Git仓库并没有因此受损。
我做了常规的打包和垃圾收集操作

git repack -Ad
git prune

但这并没有删除.tmp-* 文件,尽管它可以确保所有必要的对象都在标准的pack-* 文件中,如果它们需要从过去崩溃的Git进程留下的过渡文件中复制的话。
最后我意识到我可以安全地将.tmp-* 文件移到一个临时目录,然后运行git fsck来查看.git目录中剩下的文件是否完整。结果证明是完整的,所以我删除了临时目录及其包含的文件。如果git fsck报告了问题,我可以将.tmp-* 文件移回.git目录,然后研究另一种解决方案。

dtcbnfnu

dtcbnfnu4#

在重新打包操作期间,也会明显创建隐藏的文件夹,这些文件夹也可能会卡住
git repack“(man)在接收到信号时创建临时文件的方式很容易出现死锁,Git 2.39(Q4 2022)已对此进行了修正。
参见commit 9b3fadf(2022年10月23日)和Jeff King ( peff )commit 1934307commit 9cf10d8commit a4880b2commit b639606commit d3d9c51(2022年10月21日)。
(2022年10月30日,由Taylor Blau -- ttaylorr --commit c88895e中合并)
第1000章:使用临时文件进行信号清除
报告人:扬·波科尔尼
签署人:杰夫·金
git-repackman)由于信号而退出时,它尝试通过调用其remove_temporary_files()函数来进行清理,该函数遍历packs dir,查找要删除的“.tmp-$$-pack-*“文件(其中“$$“是当前进程的pid)。
这里最大的问题是在信号处理程序中调用remove_temporary_files()是不安全的。
它使用的是opendir(),它不在POSIX async-signal-safe列表中。
细节将是特定于平台的,但可能的问题是它需要分配内存;如果我们在malloc()等内部接收到一个信号,我们将在分配器锁上发生冲突,并与自己死锁。
我们可以通过直接清理文件来解决这个问题,而不需要遍历目录。
我们已经知道生成的.tmp-*文件的完整列表,因为我们通过populate_pack_exts()记录了它们。
当我们在那里找到文件时,我们可以使用register_tempfile()来记录文件名。
如果我们收到一个信号,那么tempfile API会为我们清理它们,它是异步安全的,并且经过了相当多的实战测试。
还有:
第1441章:删除remove_temporary_files()
签署人:杰夫·金
成功完成重新打包后,我们调用remove_temporary_files(),它查找并删除所有匹配“.tmp-$$-pack-*“的文件,其中$$是当前进程的pid。
但这毫无意义。
如果我们在这个过程中做到了这一步,我们已经将这些临时文件重命名到位,没有什么要删除的了。
当我们 * 不 * 成功时,试图调用它来清理也没有意义。
在信号处理程序中使用它是不安全的,并且上一次提交已经将该任务移交给了tempfile API。
清理其他git-repack调用留下的.tmp文件似乎很有用。
但它不会清理那些文件;它只将一个与其PID匹配,而留下其余的。
幸运的是,这些都可以通过对git-repack的连续调用自然地清除;我们将把.tmp-*.pack视为与普通的packfiles相同,因此“repack -ad“等将卷起它们的内容并最终删除它们。

相关问题