Skip to content

Commit 16a592f

Browse files
committed
Merge branch 'ps/pseudo-ref-terminology'
Terminology to call various ref-like things are getting straightened out. * ps/pseudo-ref-terminology: refs: refuse to write pseudorefs ref-filter: properly distinuish pseudo and root refs refs: pseudorefs are no refs refs: classify HEAD as a root ref refs: do not check ref existence in `is_root_ref()` refs: rename `is_special_ref()` to `is_pseudo_ref()` refs: rename `is_pseudoref()` to `is_root_ref()` Documentation/glossary: define root refs as refs Documentation/glossary: clarify limitations of pseudorefs Documentation/glossary: redefine pseudorefs as special refs
2 parents 3b1e3f0 + 8e4f5c2 commit 16a592f

File tree

10 files changed

+169
-117
lines changed

10 files changed

+169
-117
lines changed

Documentation/glossary-content.txt

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -497,20 +497,18 @@ exclude;;
497497
unusual refs.
498498

499499
[[def_pseudoref]]pseudoref::
500-
Pseudorefs are a class of files under `$GIT_DIR` which behave
501-
like refs for the purposes of rev-parse, but which are treated
502-
specially by git. Pseudorefs both have names that are all-caps,
503-
and always start with a line consisting of a
504-
<<def_SHA1,SHA-1>> followed by whitespace. So, HEAD is not a
505-
pseudoref, because it is sometimes a symbolic ref. They might
506-
optionally contain some additional data. `MERGE_HEAD` and
507-
`CHERRY_PICK_HEAD` are examples. Unlike
508-
<<def_per_worktree_ref,per-worktree refs>>, these files cannot
509-
be symbolic refs, and never have reflogs. They also cannot be
510-
updated through the normal ref update machinery. Instead,
511-
they are updated by directly writing to the files. However,
512-
they can be read as if they were refs, so `git rev-parse
513-
MERGE_HEAD` will work.
500+
A ref that has different semantics than normal refs. These refs can be
501+
read via normal Git commands, but cannot be written to by commands like
502+
linkgit:git-update-ref[1].
503+
+
504+
The following pseudorefs are known to Git:
505+
506+
- `FETCH_HEAD` is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
507+
may refer to multiple object IDs. Each object ID is annotated with metadata
508+
indicating where it was fetched from and its fetch status.
509+
510+
- `MERGE_HEAD` is written by linkgit:git-merge[1] when resolving merge
511+
conflicts. It contains all commit IDs which are being merged.
514512

515513
[[def_pull]]pull::
516514
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
@@ -552,20 +550,38 @@ exclude;;
552550
to the result.
553551

554552
[[def_ref]]ref::
555-
A name that begins with `refs/` (e.g. `refs/heads/master`)
556-
that points to an <<def_object_name,object name>> or another
557-
ref (the latter is called a <<def_symref,symbolic ref>>).
553+
A name that that points to an <<def_object_name,object name>> or
554+
another ref (the latter is called a <<def_symref,symbolic ref>>).
558555
For convenience, a ref can sometimes be abbreviated when used
559556
as an argument to a Git command; see linkgit:gitrevisions[7]
560557
for details.
561558
Refs are stored in the <<def_repository,repository>>.
562559
+
563560
The ref namespace is hierarchical.
564-
Different subhierarchies are used for different purposes (e.g. the
565-
`refs/heads/` hierarchy is used to represent local branches).
561+
Ref names must either start with `refs/` or be located in the root of
562+
the hierarchy. For the latter, their name must follow these rules:
563+
+
564+
- The name consists of only upper-case characters or underscores.
565+
566+
- The name ends with "`_HEAD`" or is equal to "`HEAD`".
566567
+
567-
There are a few special-purpose refs that do not begin with `refs/`.
568-
The most notable example is `HEAD`.
568+
There are some irregular refs in the root of the hierarchy that do not
569+
match these rules. The following list is exhaustive and shall not be
570+
extended in the future:
571+
+
572+
- `AUTO_MERGE`
573+
574+
- `BISECT_EXPECTED_REV`
575+
576+
- `NOTES_MERGE_PARTIAL`
577+
578+
- `NOTES_MERGE_REF`
579+
580+
- `MERGE_AUTOSTASH`
581+
+
582+
Different subhierarchies are used for different purposes. For example,
583+
the `refs/heads/` hierarchy is used to represent local branches whereas
584+
the `refs/tags/` hierarchy is used to represent local tags..
569585

570586
[[def_reflog]]reflog::
571587
A reflog shows the local "history" of a ref. In other words,
@@ -639,20 +655,6 @@ The most notable example is `HEAD`.
639655
An <<def_object,object>> used to temporarily store the contents of a
640656
<<def_dirty,dirty>> working directory and the index for future reuse.
641657

642-
[[def_special_ref]]special ref::
643-
A ref that has different semantics than normal refs. These refs can be
644-
accessed via normal Git commands but may not behave the same as a
645-
normal ref in some cases.
646-
+
647-
The following special refs are known to Git:
648-
649-
- "`FETCH_HEAD`" is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
650-
may refer to multiple object IDs. Each object ID is annotated with metadata
651-
indicating where it was fetched from and its fetch status.
652-
653-
- "`MERGE_HEAD`" is written by linkgit:git-merge[1] when resolving merge
654-
conflicts. It contains all commit IDs which are being merged.
655-
656658
[[def_submodule]]submodule::
657659
A <<def_repository,repository>> that holds the history of a
658660
separate project inside another repository (the latter of

builtin/for-each-ref.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
9898
}
9999

100100
if (include_root_refs)
101-
flags |= FILTER_REFS_ROOT_REFS;
101+
flags |= FILTER_REFS_ROOT_REFS | FILTER_REFS_DETACHED_HEAD;
102102

103103
filter.match_as_path = 1;
104104
filter_and_format_refs(&filter, flags, sorting, &format);

ref-filter.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,7 +2634,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
26342634
each_ref_fn cb,
26352635
void *cb_data)
26362636
{
2637-
if (filter->kind == FILTER_REFS_KIND_MASK) {
2637+
if (filter->kind & FILTER_REFS_ROOT_REFS) {
26382638
/* In this case, we want to print all refs including root refs. */
26392639
return refs_for_each_include_root_refs(get_main_ref_store(the_repository),
26402640
cb, cb_data);
@@ -2764,8 +2764,10 @@ static int ref_kind_from_refname(const char *refname)
27642764
return ref_kind[i].kind;
27652765
}
27662766

2767-
if (is_pseudoref(get_main_ref_store(the_repository), refname))
2767+
if (is_pseudo_ref(refname))
27682768
return FILTER_REFS_PSEUDOREFS;
2769+
if (is_root_ref(refname))
2770+
return FILTER_REFS_ROOT_REFS;
27692771

27702772
return FILTER_REFS_OTHERS;
27712773
}
@@ -2802,11 +2804,11 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
28022804
/*
28032805
* Generally HEAD refs are printed with special description denoting a rebase,
28042806
* detached state and so forth. This is useful when only printing the HEAD ref
2805-
* But when it is being printed along with other pseudorefs, it makes sense to
2806-
* keep the formatting consistent. So we mask the type to act like a pseudoref.
2807+
* But when it is being printed along with other root refs, it makes sense to
2808+
* keep the formatting consistent. So we mask the type to act like a root ref.
28072809
*/
2808-
if (filter->kind == FILTER_REFS_KIND_MASK && kind == FILTER_REFS_DETACHED_HEAD)
2809-
kind = FILTER_REFS_PSEUDOREFS;
2810+
if (filter->kind & FILTER_REFS_ROOT_REFS && kind == FILTER_REFS_DETACHED_HEAD)
2811+
kind = FILTER_REFS_ROOT_REFS;
28102812
else if (!(kind & filter->kind))
28112813
return NULL;
28122814

@@ -3086,7 +3088,7 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
30863088
* When printing all ref types, HEAD is already included,
30873089
* so we don't want to print HEAD again.
30883090
*/
3089-
if (!ret && (filter->kind != FILTER_REFS_KIND_MASK) &&
3091+
if (!ret && !(filter->kind & FILTER_REFS_ROOT_REFS) &&
30903092
(filter->kind & FILTER_REFS_DETACHED_HEAD))
30913093
refs_head_ref(get_main_ref_store(the_repository), fn,
30923094
cb_data);

ref-filter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
FILTER_REFS_REMOTES | FILTER_REFS_OTHERS)
2424
#define FILTER_REFS_DETACHED_HEAD 0x0020
2525
#define FILTER_REFS_PSEUDOREFS 0x0040
26-
#define FILTER_REFS_ROOT_REFS (FILTER_REFS_DETACHED_HEAD | FILTER_REFS_PSEUDOREFS)
26+
#define FILTER_REFS_ROOT_REFS 0x0080
2727
#define FILTER_REFS_KIND_MASK (FILTER_REFS_REGULAR | FILTER_REFS_DETACHED_HEAD | \
28-
FILTER_REFS_PSEUDOREFS)
28+
FILTER_REFS_PSEUDOREFS | FILTER_REFS_ROOT_REFS)
2929

3030
struct atom_value;
3131
struct ref_sorting;

refs.c

Lines changed: 35 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,22 @@ int is_per_worktree_ref(const char *refname)
819819
starts_with(refname, "refs/rewritten/");
820820
}
821821

822-
static int is_pseudoref_syntax(const char *refname)
822+
int is_pseudo_ref(const char *refname)
823+
{
824+
static const char * const pseudo_refs[] = {
825+
"FETCH_HEAD",
826+
"MERGE_HEAD",
827+
};
828+
size_t i;
829+
830+
for (i = 0; i < ARRAY_SIZE(pseudo_refs); i++)
831+
if (!strcmp(refname, pseudo_refs[i]))
832+
return 1;
833+
834+
return 0;
835+
}
836+
837+
static int is_root_ref_syntax(const char *refname)
823838
{
824839
const char *c;
825840

@@ -828,56 +843,37 @@ static int is_pseudoref_syntax(const char *refname)
828843
return 0;
829844
}
830845

831-
/*
832-
* HEAD is not a pseudoref, but it certainly uses the
833-
* pseudoref syntax.
834-
*/
835846
return 1;
836847
}
837848

838-
int is_pseudoref(struct ref_store *refs, const char *refname)
849+
int is_root_ref(const char *refname)
839850
{
840-
static const char *const irregular_pseudorefs[] = {
851+
static const char *const irregular_root_refs[] = {
852+
"HEAD",
841853
"AUTO_MERGE",
842854
"BISECT_EXPECTED_REV",
843855
"NOTES_MERGE_PARTIAL",
844856
"NOTES_MERGE_REF",
845857
"MERGE_AUTOSTASH",
846858
};
847-
struct object_id oid;
848859
size_t i;
849860

850-
if (!is_pseudoref_syntax(refname))
861+
if (!is_root_ref_syntax(refname) ||
862+
is_pseudo_ref(refname))
851863
return 0;
852864

853-
if (ends_with(refname, "_HEAD")) {
854-
refs_resolve_ref_unsafe(refs, refname,
855-
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
856-
&oid, NULL);
857-
return !is_null_oid(&oid);
858-
}
859-
860-
for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
861-
if (!strcmp(refname, irregular_pseudorefs[i])) {
862-
refs_resolve_ref_unsafe(refs, refname,
863-
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
864-
&oid, NULL);
865-
return !is_null_oid(&oid);
866-
}
867-
868-
return 0;
869-
}
865+
if (ends_with(refname, "_HEAD"))
866+
return 1;
870867

871-
int is_headref(struct ref_store *refs, const char *refname)
872-
{
873-
if (!strcmp(refname, "HEAD"))
874-
return refs_ref_exists(refs, refname);
868+
for (i = 0; i < ARRAY_SIZE(irregular_root_refs); i++)
869+
if (!strcmp(refname, irregular_root_refs[i]))
870+
return 1;
875871

876872
return 0;
877873
}
878874

879875
static int is_current_worktree_ref(const char *ref) {
880-
return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
876+
return is_root_ref_syntax(ref) || is_per_worktree_ref(ref);
881877
}
882878

883879
enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
@@ -1243,6 +1239,13 @@ int ref_transaction_update(struct ref_transaction *transaction,
12431239
return -1;
12441240
}
12451241

1242+
if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
1243+
is_pseudo_ref(refname)) {
1244+
strbuf_addf(err, _("refusing to update pseudoref '%s'"),
1245+
refname);
1246+
return -1;
1247+
}
1248+
12461249
if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
12471250
BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
12481251

@@ -1816,43 +1819,12 @@ static int refs_read_special_head(struct ref_store *ref_store,
18161819
return result;
18171820
}
18181821

1819-
static int is_special_ref(const char *refname)
1820-
{
1821-
/*
1822-
* Special references are refs that have different semantics compared
1823-
* to "normal" refs. These refs can thus not be stored in the ref
1824-
* backend, but must always be accessed via the filesystem. The
1825-
* following refs are special:
1826-
*
1827-
* - FETCH_HEAD may contain multiple object IDs, and each one of them
1828-
* carries additional metadata like where it came from.
1829-
*
1830-
* - MERGE_HEAD may contain multiple object IDs when merging multiple
1831-
* heads.
1832-
*
1833-
* Reading, writing or deleting references must consistently go either
1834-
* through the filesystem (special refs) or through the reference
1835-
* backend (normal ones).
1836-
*/
1837-
static const char * const special_refs[] = {
1838-
"FETCH_HEAD",
1839-
"MERGE_HEAD",
1840-
};
1841-
size_t i;
1842-
1843-
for (i = 0; i < ARRAY_SIZE(special_refs); i++)
1844-
if (!strcmp(refname, special_refs[i]))
1845-
return 1;
1846-
1847-
return 0;
1848-
}
1849-
18501822
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
18511823
struct object_id *oid, struct strbuf *referent,
18521824
unsigned int *type, int *failure_errno)
18531825
{
18541826
assert(failure_errno);
1855-
if (is_special_ref(refname))
1827+
if (is_pseudo_ref(refname))
18561828
return refs_read_special_head(ref_store, refname, oid, referent,
18571829
type, failure_errno);
18581830

refs.h

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,8 +1013,52 @@ extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];
10131013
*/
10141014
void update_ref_namespace(enum ref_namespace namespace, char *ref);
10151015

1016-
int is_pseudoref(struct ref_store *refs, const char *refname);
1017-
int is_headref(struct ref_store *refs, const char *refname);
1016+
/*
1017+
* Check whether the provided name names a root reference. This function only
1018+
* performs a syntactic check.
1019+
*
1020+
* A root ref is a reference that lives in the root of the reference hierarchy.
1021+
* These references must conform to special syntax:
1022+
*
1023+
* - Their name must be all-uppercase or underscores ("_").
1024+
*
1025+
* - Their name must end with "_HEAD". As a special rule, "HEAD" is a root
1026+
* ref, as well.
1027+
*
1028+
* - Their name may not contain a slash.
1029+
*
1030+
* There is a special set of irregular root refs that exist due to historic
1031+
* reasons, only. This list shall not be expanded in the future:
1032+
*
1033+
* - AUTO_MERGE
1034+
*
1035+
* - BISECT_EXPECTED_REV
1036+
*
1037+
* - NOTES_MERGE_PARTIAL
1038+
*
1039+
* - NOTES_MERGE_REF
1040+
*
1041+
* - MERGE_AUTOSTASH
1042+
*/
1043+
int is_root_ref(const char *refname);
1044+
1045+
/*
1046+
* Pseudorefs are refs that have different semantics compared to
1047+
* "normal" refs. These refs can thus not be stored in the ref backend,
1048+
* but must always be accessed via the filesystem. The following refs
1049+
* are pseudorefs:
1050+
*
1051+
* - FETCH_HEAD may contain multiple object IDs, and each one of them
1052+
* carries additional metadata like where it came from.
1053+
*
1054+
* - MERGE_HEAD may contain multiple object IDs when merging multiple
1055+
* heads.
1056+
*
1057+
* Reading, writing or deleting references must consistently go either
1058+
* through the filesystem (pseudorefs) or through the reference
1059+
* backend (normal ones).
1060+
*/
1061+
int is_pseudo_ref(const char *refname);
10181062

10191063
/*
10201064
* The following functions have been removed in Git v2.45 in favor of functions

refs/files-backend.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,7 @@ static void add_pseudoref_and_head_entries(struct ref_store *ref_store,
351351
strbuf_addstr(&refname, de->d_name);
352352

353353
dtype = get_dtype(de, &path, 1);
354-
if (dtype == DT_REG && (is_pseudoref(ref_store, de->d_name) ||
355-
is_headref(ref_store, de->d_name)))
354+
if (dtype == DT_REG && is_root_ref(de->d_name))
356355
loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
357356

358357
strbuf_setlen(&refname, dirnamelen);

refs/reftable-backend.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
354354
*/
355355
if (!starts_with(iter->ref.refname, "refs/") &&
356356
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
357-
(is_pseudoref(&iter->refs->base, iter->ref.refname) ||
358-
is_headref(&iter->refs->base, iter->ref.refname)))) {
357+
is_root_ref(iter->ref.refname))) {
359358
continue;
360359
}
361360

0 commit comments

Comments
 (0)