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

[PATCH v4 13/16] revision.c: --reflog add HEAD reflog from all worktrees

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Aug 23, 2017, 12:37 UTC
Message-ID
<20170823123704.16518-14-pclouds@gmail.com>
In-Reply-To
<20170823123704.16518-1-pclouds@gmail.com>

Note that add_other_reflogs_to_pending() is a bit inefficient, since it scans reflog for all refs of each worktree, including shared refs, so the shared ref's reflog is scanned over and over again.

We could update refs API to pass "per-worktree only" flag to avoid that. But long term we should be able to obtain a "per-worktree only" ref store and would need to revert the changes in reflog iteration API. So let's just wait until then.

add_reflogs_to_pending() is called by reachable.c so by default "git prune" will examine reflog from all worktrees.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 revision.c       | 28 +++++++++++++++++++++++++++-
 t/t5304-prune.sh | 16 ++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/revision.c b/revision.c
index 0e98444857..d100b3a3be 100644
--- a/revision.c
+++ b/revision.c
@@ -1132,6 +1132,7 @@ struct all_refs_cb {
 	int warned_bad_reflog;
 	struct rev_info *all_revs;
 	const char *name_for_errormsg;
+	struct ref_store *refs;
 };
 
 int ref_excluded(struct string_list *ref_excludes, const char *path)
@@ -1168,6 +1169,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
 	cb->all_revs = revs;
 	cb->all_flags = flags;
 	revs->rev_input_given = 1;
+	cb->refs = NULL;
 }
 
 void clear_ref_exclusion(struct string_list **ref_excludes_p)
@@ -1236,17 +1238,41 @@ static int handle_one_reflog(const char *path, const struct object_id *oid,
 	struct all_refs_cb *cb = cb_data;
 	cb->warned_bad_reflog = 0;
 	cb->name_for_errormsg = path;
-	for_each_reflog_ent(path, handle_one_reflog_ent, cb_data);
+	refs_for_each_reflog_ent(cb->refs, path,
+				 handle_one_reflog_ent, cb_data);
 	return 0;
 }
 
+static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
+{
+	struct worktree **worktrees, **p;
+
+	worktrees = get_worktrees(0);
+	for (p = worktrees; *p; p++) {
+		struct worktree *wt = *p;
+
+		if (wt->is_current)
+			continue;
+
+		cb->refs = get_worktree_ref_store(wt);
+		refs_for_each_reflog(cb->refs,
+				     handle_one_reflog,
+				     cb);
+	}
+	free_worktrees(worktrees);
+}
+
 void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
 {
 	struct all_refs_cb cb;
 
 	cb.all_revs = revs;
 	cb.all_flags = flags;
+	cb.refs = get_main_ref_store();
 	for_each_reflog(handle_one_reflog, &cb);
+
+	if (!revs->single_worktree)
+		add_other_reflogs_to_pending(&cb);
 }
 
 static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 683bdb031c..6694c19a1e 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -304,4 +304,20 @@ test_expect_success 'prune: handle HEAD in multiple worktrees' '
 	test_cmp third-worktree/blob actual
 '
 
+test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
+	git config core.logAllRefUpdates true &&
+	echo "lost blob for third-worktree" >expected &&
+	(
+		cd third-worktree &&
+		cat ../expected >blob &&
+		git add blob &&
+		git commit -m "second commit in third" &&
+		git reset --hard HEAD^
+	) &&
+	git prune --expire=now &&
+	SHA1=`git hash-object expected` &&
+	git -C third-worktree show "$SHA1" >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.11.0.157.gd943d85
Previous: Michael HaggertyNext: Nguyễn Thái Ngọc Duy
Message 31 of 40 in “Fix git-gc losing objects in multi worktree”
  1. 00/16 Fix git-gc losing objects in multi worktreeNguyễn Thái Ngọc Duy, Aug 23, 2017
  2. 01/16 revision.h: new flag in struct rev_info wrt. worktree-related refsNguyễn Thái Ngọc Duy, Aug 23, 2017
  3. 02/16 refs.c: use is_dir_sep() in resolve_gitlink_ref()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  4. Stefan BellerAug 23, 2017
  5. Duy NguyenSep 6, 2017
  6. Stefan BellerSep 6, 2017
  7. 03/16 revision.c: refactor add_index_objects_to_pending()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  8. 04/16 revision.c: --indexed-objects add objects from all worktreesNguyễn Thái Ngọc Duy, Aug 23, 2017
  9. Stefan BellerAug 23, 2017
  10. 05/16 refs.c: refactor get_submodule_ref_store(), share common free blockNguyễn Thái Ngọc Duy, Aug 23, 2017
  11. Stefan BellerAug 23, 2017
  12. 06/16 refs: move submodule slash stripping code to get_submodule_ref_storeNguyễn Thái Ngọc Duy, Aug 23, 2017
  13. Michael HaggertySep 9, 2017
  14. 07/16 refs: add refs_head_ref()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  15. Junio C HamanoAug 24, 2017
  16. Duy NguyenSep 6, 2017
  17. 08/16 revision.c: use refs_for_each*() instead of for_each_*_submodule()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  18. Junio C HamanoAug 24, 2017
  19. 09/16 refs.c: move for_each_remote_ref_submodule() to submodule.cNguyễn Thái Ngọc Duy, Aug 23, 2017
  20. 10/16 refs: remove dead for_each_*_submodule()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  21. Stefan BellerAug 23, 2017
  22. Michael HaggertySep 9, 2017
  23. 11/16 revision.c: --all adds HEAD from all worktreesNguyễn Thái Ngọc Duy, Aug 23, 2017
  24. Stefan BellerAug 23, 2017
  25. Duy NguyenSep 6, 2017
  26. Stefan BellerSep 6, 2017
  27. Michael HaggertySep 9, 2017
  28. 12/16 files-backend: make reflog iterator go through per-worktree reflogNguyễn Thái Ngọc Duy, Aug 23, 2017
  29. Richard MawAug 24, 2017
  30. Michael HaggertySep 9, 2017
  31. 13/16 revision.c: --reflog add HEAD reflog from all worktreesNguyễn Thái Ngọc Duy, Aug 23, 2017
  32. 14/16 rev-list: expose and document --single-worktreeNguyễn Thái Ngọc Duy, Aug 23, 2017
  33. Stefan BellerAug 23, 2017
  34. 15/16 refs.c: remove fallback-to-main-store code get_submodule_ref_store()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  35. Michael HaggertySep 9, 2017
  36. 16/16 refs.c: reindent get_submodule_ref_store()Nguyễn Thái Ngọc Duy, Aug 23, 2017
  37. Michael HaggertySep 9, 2017
  38. Michael J GruberAug 25, 2017
  39. Duy NguyenSep 6, 2017
  40. Michael HaggertySep 9, 2017

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.