path: root/refs.c
diff options
authorNguyễn Thái Ngọc Duy <>2018-10-21 08:08:54 (GMT)
committerJunio C Hamano <>2018-10-22 04:32:29 (GMT)
commit3a3b9d8cde4ed647b1c56a8097f6db8e269bbc71 (patch)
treecbac4a25a4f33120cec68f92ee93a59708a00d6e /refs.c
parent8aff1a9ca5a266020fe5b1bd8c54228581e34530 (diff)
refs: new ref types to make per-worktree refs visible to all worktrees
One of the problems with multiple worktree is accessing per-worktree refs of one worktree from another worktree. This was sort of solved by multiple ref store, where the code can open the ref store of another worktree and has access to the ref space of that worktree. The problem with this is reporting. "HEAD" in another ref space is also called "HEAD" like in the current ref space. In order to differentiate them, all the code must somehow carry the ref store around and print something like "HEAD from this ref store". But that is not feasible (or possible with a _lot_ of work). With the current design, we pass a reference around as a string (so called "refname"). Extending this design to pass a string _and_ a ref store is a nightmare, especially when handling extended SHA-1 syntax. So we do it another way. Instead of entering a separate ref space, we make refs from other worktrees available in the current ref space. So "HEAD" is always HEAD of the current worktree, but then we can have "worktrees/blah/HEAD" to denote HEAD from a worktree named "blah". This syntax coincidentally matches the underlying directory structure which makes implementation a bit easier. The main worktree has to be treated specially because well... it's special from the beginning. So HEAD from the main worktree is acccessible via the name "main-worktree/HEAD" instead of "worktrees/main/HEAD" because "main" could be just another secondary worktree. This patch also makes it possible to specify refs from one worktree in another one, e.g. git log worktrees/foo/HEAD Signed-off-by: Nguyễn Thái Ngọc Duy <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'refs.c')
1 files changed, 21 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index 1bc4ed3..2378b2e 100644
--- a/refs.c
+++ b/refs.c
@@ -641,12 +641,33 @@ static int is_pseudoref_syntax(const char *refname)
return 1;
+static int is_main_pseudoref_syntax(const char *refname)
+ return skip_prefix(refname, "main-worktree/", &refname) &&
+ *refname &&
+ is_pseudoref_syntax(refname);
+static int is_other_pseudoref_syntax(const char *refname)
+ if (!skip_prefix(refname, "worktrees/", &refname))
+ return 0;
+ refname = strchr(refname, '/');
+ if (!refname || !refname[1])
+ return 0;
+ return is_pseudoref_syntax(refname + 1);
enum ref_type ref_type(const char *refname)
if (is_per_worktree_ref(refname))
if (is_pseudoref_syntax(refname))
+ if (is_main_pseudoref_syntax(refname))
+ if (is_other_pseudoref_syntax(refname))