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

[RFC PATCH 7/7] repack-promisor: record dropped objects in a drop log

From
Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Date
Jul 16, 2026, 13:28 UTC
Message-ID
<20260716132848.95982-8-r.siddharth.shrimali@gmail.com>
In-Reply-To
<20260716132848.95982-1-r.siddharth.shrimali@gmail.com>

After --drop-filtered removes promisor blobs, append a record of each dropped object to $GIT_DIR/objects/info/promisor-dropped. Each line records the object ID, a reflog-style timestamp (Unix seconds and timezone), the filter spec, and the promisor remote it was attested recoverable from like the following:

  <oid> <time> <tz> filter=<spec> remote=<name>

If a dropped object later becomes unrecoverable (for example, the branch holding it is deleted on the promisor remote), a lazy fetch fails with a generic error. This persistent record lets a later change explain that the object was dropped deliberately, when, under which filter, and from which remote it was expected to be recoverable.

The remote field lists all configured promisor remotes rather than the specific one each dropped object is recoverable from. Determining the exact remote would require asking the remote whether it has the object. A "remote-object-info" command is being added to the "git cat-file --batch" protocol for this kind of query, but it is not available yet. A NEEDSWORK marks this for a follow-up.

The log is written only on a real run, i.e. --dry-run changes nothing.
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Siddharth Asthana <siddharthasthana31@gmail.com>
Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
---
 builtin/repack.c  |  4 +++
 repack-promisor.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
 repack.h          |  4 +++
 3 files changed, 99 insertions(+)
diff --git a/builtin/repack.c b/builtin/repack.c
index aa3257a98a..49dcbbc567 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -702,6 +702,10 @@ int cmd_repack(int argc,
 		write_midx_file(files->packed, NULL, NULL, flags);
 	}
 
+	if (drop_filtered && !dry_run)
+		append_drop_log(repo, &drop_oids,
+			expand_list_objects_filter_spec(&po_args.filter_options));
+
 cleanup:
 	string_list_clear(&keep_pack_list, 0);
 	string_list_clear(&names, 1);
diff --git a/repack-promisor.c b/repack-promisor.c
index fabfdc168a..60913a5150 100644
--- a/repack-promisor.c
+++ b/repack-promisor.c
@@ -7,6 +7,97 @@
 #include "repository.h"
 #include "run-command.h"
 #include "oidset.h"
+#include "date.h"
+#include "promisor-remote.h"
+#include "strbuf.h"
+
+/*
+ * Append the drop-log entries to the already-computed path.
+ * Returns -1 on any I/O failure so the caller can warn once.
+ * Keeping this in a separate helper avoids goto-based cleanup
+ * in append_drop_log();
+ */
+static int write_to_drop_log(struct repository *repo,
+			     const char *path,
+			     const struct oidset *dropped,
+			     const char *stamp,
+			     const char *filter_spec,
+			     const char *remotes)
+{
+	struct oidset_iter iter;
+	const struct object_id *oid;
+	FILE *fp;
+
+	if (safe_create_leading_directories(repo, (char *)path)) {
+		warning(_("could not create leading directories for '%s'"), path);
+		return -1;
+	}
+
+	fp = fopen(path, "a");
+	if (!fp) {
+		warning_errno(_("could not open '%s'"), path);
+		return -1;
+	}
+
+	oidset_iter_init(dropped, &iter);
+	while ((oid = oidset_iter_next(&iter))) {
+		if (fprintf(fp, "%s %s filter=%s remote=%s\n",
+				oid_to_hex(oid), stamp,
+				filter_spec ? filter_spec : "",
+				remotes) < 0) {
+			warning(_("could not write to '%s'"), path);
+			fclose(fp);
+			return -1;
+		}
+	}
+
+	if (fclose(fp)) {
+		warning_errno(_("could not close '%s'"), path);
+		return -1;
+	}
+
+	return 0;
+}
+
+void append_drop_log(struct repository *repo,
+		     const struct oidset *dropped,
+		     const char *filter_spec)
+{
+	char *path;
+	struct strbuf stamp = STRBUF_INIT;
+	struct strbuf remotes = STRBUF_INIT;
+	struct promisor_remote *pr;
+
+	if (!oidset_size(dropped))
+		return;
+
+	datestamp(&stamp);
+
+	/*
+	 * NEEDSWORK: we temporarily record all configured promisor remotes rather
+	 * than the specific one a given object is recoverable from because there
+	 * is currently no way to determine that locally. it would require
+	 * asking the remote whether it has the object. A "remote-object-info"
+	 * command is being added to the "git cat-file --batch" protocol for
+	 * this kind of query. Once it is merged in the codebase, this should
+	 * record the exact promisor remote that has each dropped object.
+	 */
+	for (pr = repo_promisor_remote_find(repo, NULL); pr; pr = pr->next) {
+		if (remotes.len)
+			strbuf_addch(&remotes, ',');
+		strbuf_addstr(&remotes, pr->name);
+	}
+
+	path = repo_git_path(repo, "objects/info/promisor-dropped");
+
+	if (write_to_drop_log(repo, path, dropped, stamp.buf,
+			filter_spec, remotes.buf))
+		warning(_("could not record all dropped objects in the drop log"));
+
+	strbuf_release(&stamp);
+	strbuf_release(&remotes);
+	free(path);
+}
 
 struct write_oid_context {
 	struct child_process *cmd;
diff --git a/repack.h b/repack.h
index 61e554e4ed..33309548ce 100644
--- a/repack.h
+++ b/repack.h
@@ -171,6 +171,10 @@ int enumerate_promisor_blobs(struct repository *repo,
 			     const struct list_objects_filter_options *filter,
 			     struct oidset *to_drop);
 
+void append_drop_log(struct repository *repo,
+		     const struct oidset *dropped,
+		     const char *filter_spec);
+
 int write_cruft_pack(const struct write_pack_opts *opts,
 		     const char *cruft_expiration,
 		     unsigned long combine_cruft_below_size,
-- 
2.54.0
Previous: Siddharth ShrimaliNext: Siddharth Asthana
Message 15 of 76 in “repack: add --drop-filtered to reclaim space in partial clones”
  1. 0/7 repack: add --drop-filtered to reclaim space in partial clonesSiddharth Shrimali, Jul 16, 2026
  2. 1/7 builtin/repack.c: add --drop-filtered and --dry-run optionsSiddharth Shrimali, Jul 16, 2026
  3. Junio C HamanoJul 16, 2026
  4. Siddharth ShrimaliJul 17, 2026
  5. Siddharth AsthanaJul 23, 2026
  6. Christian CouderJul 18, 2026
  7. Siddharth ShrimaliJul 20, 2026
  8. 2/7 list-objects-filter: add list_objects_filter__filter_oidset()Siddharth Shrimali, Jul 16, 2026
  9. 3/7 repack-promisor: allow excluding objects from the rebuilt promisor packSiddharth Shrimali, Jul 16, 2026
  10. 4/7 builtin/repack: enumerate promisor blobs for --drop-filteredSiddharth Shrimali, Jul 16, 2026
  11. 5/7 t7706: test --drop-filtered enumeration and validationSiddharth Shrimali, Jul 16, 2026
  12. 6/7 builtin/repack: actually drop filtered promisor blobsSiddharth Shrimali, Jul 16, 2026
  13. Siddharth AsthanaJul 23, 2026
  14. Siddharth ShrimaliJul 25, 2026
  15. 7/7 repack-promisor: record dropped objects in a drop logSiddharth Shrimali, Jul 16, 2026
  16. Siddharth AsthanaJul 23, 2026
  17. Siddharth ShrimaliJul 25, 2026
  18. Siddharth AsthanaJul 23, 2026
  19. Siddharth ShrimaliJul 25, 2026
  20. 0/7 repack: add --drop-filtered to reclaim space in partial clonesSiddharth Shrimali, Jul 30, 2026
  21. 1/7 builtin/repack.c: add --drop-filtered and --dry-run optionsSiddharth Shrimali, Jul 30, 2026
  22. Siddharth AsthanaAug 4, 2026
  23. 2/7 list-objects-filter: add list_objects_filter__filter_oidset()Siddharth Shrimali, Jul 30, 2026
  24. 3/7 repack-promisor: allow excluding objects from the rebuilt promisor packSiddharth Shrimali, Jul 30, 2026
  25. 4/7 builtin/repack: enumerate promisor blobs for --drop-filteredSiddharth Shrimali, Jul 30, 2026
  26. 5/7 builtin/repack: actually drop filtered promisor blobsSiddharth Shrimali, Jul 30, 2026
  27. 6/7 builtin/repack: add safety guards for --drop-filteredSiddharth Shrimali, Jul 30, 2026
  28. Siddharth AsthanaAug 4, 2026
  29. 7/7 Documentation/git-repack: document --drop-filtered and --dry-runSiddharth Shrimali, Jul 30, 2026
  30. Junio C HamanoJul 31, 2026
  31. Siddharth ShrimaliAug 1, 2026
  32. Junio C HamanoAug 2, 2026
  33. Siddharth ShrimaliAug 2, 2026
  34. Siddharth AsthanaAug 4, 2026
  35. 0/7 repack: add --drop-filtered to reclaim space in partial clonesSiddharth Shrimali, Aug 6, 2026
  36. 1/7 builtin/repack.c: add --drop-filtered and --dry-run optionsSiddharth Shrimali, Aug 6, 2026
  37. 2/7 list-objects-filter: add list_objects_filter__filter_oidset()Siddharth Shrimali, Aug 6, 2026
  38. 3/7 repack-promisor: allow excluding objects from the rebuilt promisor packSiddharth Shrimali, Aug 6, 2026
  39. 4/7 builtin/repack: enumerate promisor blobs for --drop-filteredSiddharth Shrimali, Aug 6, 2026
  40. 5/7 builtin/repack: actually drop filtered promisor blobsSiddharth Shrimali, Aug 6, 2026
  41. 6/7 builtin/repack: add guards for --drop-filteredSiddharth Shrimali, Aug 6, 2026
  42. 7/7 Documentation/git-repack: document --drop-filtered and --dry-runSiddharth Shrimali, Aug 6, 2026
  43. Junio C HamanoAug 6, 2026
  44. Junio C HamanoAug 6, 2026
  45. Siddharth ShrimaliAug 7, 2026
  46. Junio C HamanoAug 7, 2026
  47. Siddharth ShrimaliAug 8, 2026
  48. 0/7 repack: add --drop-filtered to reclaim space in partial clonesSiddharth Shrimali, Aug 10, 2026
  49. 1/7 builtin/repack.c: add --drop-filtered and --dry-run optionsSiddharth Shrimali, Aug 10, 2026
  50. 2/7 list-objects-filter: add list_objects_filter__filter_oidset()Siddharth Shrimali, Aug 10, 2026
  51. Christian CouderAug 12, 2026
  52. Junio C HamanoAug 12, 2026
  53. Siddharth ShrimaliAug 12, 2026
  54. 3/7 repack-promisor: allow excluding objects from the rebuilt promisor packSiddharth Shrimali, Aug 10, 2026
  55. 4/7 builtin/repack: enumerate promisor blobs for --drop-filteredSiddharth Shrimali, Aug 10, 2026
  56. Christian CouderAug 12, 2026
  57. 5/7 builtin/repack: actually drop filtered promisor blobsSiddharth Shrimali, Aug 10, 2026
  58. 6/7 builtin/repack: add guards for --drop-filteredSiddharth Shrimali, Aug 10, 2026
  59. Christian CouderAug 12, 2026
  60. Siddharth ShrimaliAug 12, 2026
  61. 7/7 Documentation/git-repack: document --drop-filtered and --dry-runSiddharth Shrimali, Aug 10, 2026
  62. Christian CouderAug 12, 2026
  63. Junio C HamanoAug 11, 2026
  64. Siddharth ShrimaliAug 12, 2026
  65. 0/6 repack: add --drop-filtered to reclaim space in partial clonesSiddharth Shrimali, Aug 13, 2026
  66. 1/6 builtin/repack: add --drop-filtered and --dry-run optionsSiddharth Shrimali, Aug 13, 2026
  67. 2/6 list-objects-filter: add list_objects_filter__filter_oidset()Siddharth Shrimali, Aug 13, 2026
  68. 3/6 repack-promisor: allow excluding objects from the rebuilt promisor packSiddharth Shrimali, Aug 13, 2026
  69. 4/6 builtin/repack: enumerate promisor blobs for --drop-filteredSiddharth Shrimali, Aug 13, 2026
  70. 5/6 builtin/repack: actually drop filtered promisor blobsSiddharth Shrimali, Aug 13, 2026
  71. 6/6 builtin/repack: add guards for --drop-filteredSiddharth Shrimali, Aug 13, 2026
  72. Samuel BronsonSep 3, 2026
  73. Siddharth ShrimaliSep 4, 2026
  74. Christian CouderAug 14, 2026
  75. Junio C HamanoAug 14, 2026
  76. Siddharth ShrimaliAug 14, 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.