如何防止 GIT 中的垃圾回收?

How to Prevent Garbage Collection in GIT?

Git 神秘地运行垃圾收集 "from time to time" 并删除和孤立您的提交。

https://www.kernel.org/pub/software/scm/git/docs/git-gc.html

从科学上讲,这将在您意识到您确实需要刚刚删除的那个提交之前大约 6-8 小时发生。

我不想让 Git 删除我的文件。我怎样才能完全禁用自动垃圾收集?

来自very same page you just linked to

Some git commands may automatically run git gc; see the --auto flag below for details. If you know what you’re doing and all you want is to disable this behavior permanently without further considerations, just do:

$ git config --global gc.auto 0

另一种方法,最近记录在:
Documentation/config:为 'expire' 设置提及“now”和“never

In addition to approxidate-style values ("2.months.ago", "yesterday"), consumers of 'gc.*expire*' configuration variables also accept and respect 'now' ("do it immediately") and 'never' ("suppress entirely").

参见 commit 8cc8816 (28 Jul 2015) by Eric Sunshine (sunshineco)
推荐人:Michael Haggerty (mhagger).
(由 Junio C Hamano -- gitster -- in commit 8cc8816 合并,2015 年 7 月 28 日)

这意味着这也将阻止任何 gc:

git config --global gc.pruneExpire never
git config --global gc.reflogExpire never

但是,你可能会遇到(如果你使用配置值never):

warning: There are too many unreachable loose objects; run 'git prune' to remove them. 

在那种情况下,如果您真的不想让任何东西过期,您可能希望将 gc.auto 设置为某个高值(例如 100000)。这将使警告消失,但可能导致垃圾收集整体效率降低,因此应将其视为一种解决方法,而不是真正的解决方法。有关详细信息,请参阅 Is it possible to get `git gc` to pack reflog objects?


为避免git gc仅在背景中设置,如nornagon's :

git config --global gc.autodetach false

来自Git v2.14.0-rc1 commit c45af94 (11 Jul 2017) by Jeff King (peff).
(由 Junio C Hamano -- gitster -- in commit 764046f 合并,2017 年 7 月 18 日)

We run an early part of "git gc" that deals with refs before daemonising (and not under lock) even when running a background auto-gc, which caused multiple gc processes attempting to run the early part at the same time.
This is now prevented by running the early part also under the GC lock.

gc: run pre-detach operations under lock

We normally try to avoid having two auto-gc operations run at the same time, because it wastes resources.
This was done long ago in 64a99eb (gc: reject if another gc is running, unless --force is given, 2013-08-08, v1.8.5-rc0).

When we do a detached auto-gc, we run the ref-related commands before detaching, to avoid confusing lock contention.
This was done by 62aad18 (gc --auto: do not lock refs in the background, 2014-05-25, Git v2.0.1).

These two features do not interact well.
The pre-detach operations are run before we check the gc.pid lock, meaning that on a busy repository we may run many of them concurrently.
Ideally we'd take the lock before spawning any operations, and hold it for the duration of the program.

This is tricky, though, with the way the pid-file interacts with the daemonize() process.
Other processes will check that the pid recorded in the pid-file still exists. But detaching causes us to fork and continue running under a new pid.
So if we take the lock before detaching, the pid-file will have a bogus pid in it. We'd have to go back and update it with the new pid after detaching.
We'd also have to play some tricks with the tempfile subsystem to tweak the "owner" field, so that the parent process does not clean it up on exit, but the child process does.

Instead, we can do something a bit simpler: take the lock only for the duration of the pre-detach work, then detach, then take it again for the post-detach work.

Technically, this means that the post-detach lock could lose to another process doing pre-detach work.
But in the long run this works out.

That second process would then follow-up by doing post-detach work. Unless it was in turn blocked by a third process doing pre-detach work, and so on.

This could in theory go on indefinitely, as the pre-detach work does not repack, and so need_to_gc() will continue to trigger.
But in each round we are racing between the pre- and post-detach locks.
Eventually, one of the post-detach locks will win the race and complete the full gc.

So in the worst case, we may racily repeat the pre-detach work, but we would never do so simultaneously (it would happen via a sequence of serialized race-wins).

我找到这个答案是因为我试图阻止 git 在后台 运行 git gc ,因为它正在搞乱我试图在回购协议上执行的其他操作。事实证明,您可以使用

专门禁用背景行为
$ git config gc.autodetach false

如果您希望在所有回购协议中出现此行为:

$ git config --global gc.autodetach false