git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] rerere: keep a background gc from killing a rebase

From
Patrick Steinhardt <ps@pks.im>
Date
Sep 3, 2026, 07:40 UTC
Message-ID
<apkkVAYOqjfAsp9-@pks.im>
In-Reply-To
<pull.2214.git.1788337897490.gitgitgadget@gmail.com>
On Wed, Sep 02, 2026 at 08:31:37AM +0000, Thomas Bachem via GitGitGadget wrote:
Show 7 quoted lines
> From: Thomas Bachem <mail@thomasbachem.com>
> 
> Since 2.54 unscheduled maintenance uses the "geometric" strategy, so
> the "git maintenance run --auto --detach" behind every "git commit"
> runs "git rerere gc" in the background whenever rr-cache has an entry.
> That includes the "git commit" the sequencer runs for a resolved pick
> on "git rebase --continue".

I think this hints that we should tweak the default value of "maintenance.rerere-gc.auto". The way it's currently written we indeed are quite aggressive with spawning `git rerere gc`, and I agree that we should tweak it. And in the best case we'd not only respect whether we have a specific number of entries, but we should also respect whether those would be garbage collected in the first place.

I'll send a patch series later today to do this.
[snip]
Show 11 quoted lines
> The gc needs the lock: it removes every rr-cache directory it finds
> empty, and a rerere that has just created its directory but not yet
> written the preimage looks exactly like that. So keep the lock and fix
> both orders. When the gc finds the lock busy, let it warn and do
> nothing this time, the way "maintenance run" treats its own lock, so a
> manual "git rerere gc" sees the warning and the maintenance task and
> "git gc" see a clean exit. When the gc holds the lock, let every other
> caller wait it out instead of dying at once, for rerere.lockTimeout
> milliseconds with the semantics of core.packedRefsTimeout: 1000 by
> default, 0 for the old behaviour, -1 for an unbounded wait. Walking a
> 20000-entry rr-cache takes about 0.4 s here.

Having a locking timeout is sensible anyway, I think. It does not only solve races with a concurrent maintenance run, but also with concurrent writers.

Show 39 quoted lines
> diff --git a/rerere.c b/rerere.c
> index 8232542585..22d114262b 100644
> --- a/rerere.c
> +++ b/rerere.c
> @@ -32,6 +32,7 @@ static int rerere_enabled = -1;
>  
>  /* automatically update cleanly resolved paths to the index */
>  static int rerere_autoupdate;
> +static int rerere_lock_timeout_ms = 1000;
>  
>  #define RR_HAS_POSTIMAGE 1
>  #define RR_HAS_PREIMAGE 2
> @@ -876,6 +877,8 @@ static void git_rerere_config(void)
>  {
>  	repo_config_get_bool(the_repository, "rerere.enabled", &rerere_enabled);
>  	repo_config_get_bool(the_repository, "rerere.autoupdate", &rerere_autoupdate);
> +	repo_config_get_int(the_repository, "rerere.locktimeout",
> +			    &rerere_lock_timeout_ms);
>  	repo_config(the_repository, git_default_config, NULL);
>  }
>  
> @@ -908,12 +911,26 @@ int setup_rerere(struct repository *r, struct string_list *merge_rr, int flags)
>  
>  	if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
>  		rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
> -	if (flags & RERERE_READONLY)
> +	if (flags & RERERE_READONLY) {
>  		fd = 0;
> -	else
> +	} else if (flags & RERERE_SKIP_LOCKED) {
>  		fd = hold_lock_file_for_update(&write_lock,
> -					       git_path_merge_rr(r),
> -					       LOCK_DIE_ON_ERROR);
> +					       git_path_merge_rr(r), 0);
> +		if (fd < 0) {
> +			warning_errno(_("unable to lock '%s', skipping"),
> +				      git_path_merge_rr(r));
> +			return -1;
> +		}

We should instead pass `LOCK_REPORT_ON_ERROR`, as the lockfile machinery knows better why exactly locking has failed.

Show 10 quoted lines
> +	} else {
> +		/*
> +		 * A background "rerere gc" holds the lock for as long as it
> +		 * takes to walk rr-cache, so wait it out rather than die.
> +		 */
> +		fd = hold_lock_file_for_update_timeout(&write_lock,
> +						       git_path_merge_rr(r),
> +						       LOCK_DIE_ON_ERROR,
> +						       rerere_lock_timeout_ms);
> +	}

I think we can easily combine those two branches and simply set the timeout value to 0 in case we see the flag.

Patrick
Previous: Phillip WoodNext: Thomas Bachem
Message 5 of 45 in “rerere: keep a background gc from killing a rebase”
  1. rerere: keep a background gc from killing a rebaseThomas Bachem via GitGitGadget, Sep 2, 2026
  2. Phillip WoodSep 2, 2026
  3. Thomas BachemSep 2, 2026
  4. Phillip WoodSep 3, 2026
  5. Patrick SteinhardtSep 3, 2026
  6. Thomas BachemSep 3, 2026
  7. Patrick SteinhardtSep 3, 2026
  8. Thomas BachemSep 3, 2026
  9. Phillip WoodSep 3, 2026
  10. rerere: keep a background gc from killing a rebaseThomas Bachem via GitGitGadget, Sep 4, 2026
  11. Phillip WoodSep 4, 2026
  12. Thomas BachemSep 4, 2026
  13. Phillip WoodSep 7, 2026
  14. Junio C HamanoSep 4, 2026
  15. Thomas BachemSep 4, 2026
  16. rerere: keep a background gc from killing a rebaseThomas Bachem via GitGitGadget, Sep 4, 2026
  17. Junio C HamanoSep 4, 2026
  18. Thomas BachemSep 5, 2026
  19. Junio C HamanoSep 5, 2026
  20. Thomas BachemSep 6, 2026
  21. Patrick SteinhardtSep 7, 2026
  22. 0/2 rerere: wait for MERGE_RR.lock, and go on at a conflictThomas Bachem via GitGitGadget, Sep 14, 2026
  23. 1/2 rerere: wait for MERGE_RR.lock, and let the gc skip itThomas Bachem via GitGitGadget, Sep 14, 2026
  24. Patrick SteinhardtSep 28, 2026
  25. 2/2 rerere: go on at a conflict when the lock stays busyThomas Bachem via GitGitGadget, Sep 14, 2026
  26. Patrick SteinhardtSep 28, 2026
  27. 0/3 rerere: wait for MERGE_RR.lock, and go on at a conflictThomas Bachem via GitGitGadget, Sep 28, 2026
  28. 1/3 rerere: wait for MERGE_RR.lock before giving upThomas Bachem via GitGitGadget, Sep 28, 2026
  29. 2/3 rerere: add "gc --auto" that skips a held lockThomas Bachem via GitGitGadget, Sep 28, 2026
  30. Patrick SteinhardtSep 30, 2026
  31. Thomas BachemOct 1, 2026
  32. Patrick SteinhardtOct 1, 2026
  33. 3/3 rerere: go on at a conflict when the lock stays busyThomas Bachem via GitGitGadget, Sep 28, 2026
  34. 0/3 rerere: wait for MERGE_RR.lock, and go on at a conflictThomas Bachem via GitGitGadget, Oct 2, 2026
  35. 1/3 rerere: wait for MERGE_RR.lock before giving upThomas Bachem via GitGitGadget, Oct 2, 2026
  36. 2/3 rerere: add "gc --skip-locked" for auto maintenanceThomas Bachem via GitGitGadget, Oct 2, 2026
  37. Patrick SteinhardtOct 9, 2026
  38. Thomas BachemOct 10, 2026
  39. 3/3 rerere: go on at a conflict when the lock stays busyThomas Bachem via GitGitGadget, Oct 2, 2026
  40. Patrick SteinhardtOct 9, 2026
  41. Thomas BachemOct 10, 2026
  42. 0/2 rerere: wait for MERGE_RR.lock, but not in auto maintenanceThomas Bachem via GitGitGadget, Oct 10, 2026
  43. 1/2 rerere: wait for MERGE_RR.lock before giving upThomas Bachem via GitGitGadget, Oct 10, 2026
  44. Junio C HamanoOct 11, 2026
  45. 2/2 rerere: add "gc --skip-locked" for auto maintenanceThomas Bachem via GitGitGadget, Oct 10, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.