Skip to content

Commit 0ff6d23

Browse files
committed
Merge branch 'ps/pseudo-ref-terminology' into ps/ref-storage-migration
* 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 e55f364 + 8e4f5c2 commit 0ff6d23

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
@@ -782,7 +782,22 @@ int is_per_worktree_ref(const char *refname)
782782
starts_with(refname, "refs/rewritten/");
783783
}
784784

785-
static int is_pseudoref_syntax(const char *refname)
785+
int is_pseudo_ref(const char *refname)
786+
{
787+
static const char * const pseudo_refs[] = {
788+
"FETCH_HEAD",
789+
"MERGE_HEAD",
790+
};
791+
size_t i;
792+
793+
for (i = 0; i < ARRAY_SIZE(pseudo_refs); i++)
794+
if (!strcmp(refname, pseudo_refs[i]))
795+
return 1;
796+
797+
return 0;
798+
}
799+
800+
static int is_root_ref_syntax(const char *refname)
786801
{
787802
const char *c;
788803

@@ -791,56 +806,37 @@ static int is_pseudoref_syntax(const char *refname)
791806
return 0;
792807
}
793808

794-
/*
795-
* HEAD is not a pseudoref, but it certainly uses the
796-
* pseudoref syntax.
797-
*/
798809
return 1;
799810
}
800811

801-
int is_pseudoref(struct ref_store *refs, const char *refname)
812+
int is_root_ref(const char *refname)
802813
{
803-
static const char *const irregular_pseudorefs[] = {
814+
static const char *const irregular_root_refs[] = {
815+
"HEAD",
804816
"AUTO_MERGE",
805817
"BISECT_EXPECTED_REV",
806818
"NOTES_MERGE_PARTIAL",
807819
"NOTES_MERGE_REF",
808820
"MERGE_AUTOSTASH",
809821
};
810-
struct object_id oid;
811822
size_t i;
812823

813-
if (!is_pseudoref_syntax(refname))
824+
if (!is_root_ref_syntax(refname) ||
825+
is_pseudo_ref(refname))
814826
return 0;
815827

816-
if (ends_with(refname, "_HEAD")) {
817-
refs_resolve_ref_unsafe(refs, refname,
818-
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
819-
&oid, NULL);
820-
return !is_null_oid(&oid);
821-
}
822-
823-
for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
824-
if (!strcmp(refname, irregular_pseudorefs[i])) {
825-
refs_resolve_ref_unsafe(refs, refname,
826-
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
827-
&oid, NULL);
828-
return !is_null_oid(&oid);
829-
}
830-
831-
return 0;
832-
}
828+
if (ends_with(refname, "_HEAD"))
829+
return 1;
833830

834-
int is_headref(struct ref_store *refs, const char *refname)
835-
{
836-
if (!strcmp(refname, "HEAD"))
837-
return refs_ref_exists(refs, refname);
831+
for (i = 0; i < ARRAY_SIZE(irregular_root_refs); i++)
832+
if (!strcmp(refname, irregular_root_refs[i]))
833+
return 1;
838834

839835
return 0;
840836
}
841837

842838
static int is_current_worktree_ref(const char *ref) {
843-
return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
839+
return is_root_ref_syntax(ref) || is_per_worktree_ref(ref);
844840
}
845841

846842
enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
@@ -1206,6 +1202,13 @@ int ref_transaction_update(struct ref_transaction *transaction,
12061202
return -1;
12071203
}
12081204

1205+
if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
1206+
is_pseudo_ref(refname)) {
1207+
strbuf_addf(err, _("refusing to update pseudoref '%s'"),
1208+
refname);
1209+
return -1;
1210+
}
1211+
12091212
if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
12101213
BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
12111214

@@ -1737,43 +1740,12 @@ static int refs_read_special_head(struct ref_store *ref_store,
17371740
return result;
17381741
}
17391742

1740-
static int is_special_ref(const char *refname)
1741-
{
1742-
/*
1743-
* Special references are refs that have different semantics compared
1744-
* to "normal" refs. These refs can thus not be stored in the ref
1745-
* backend, but must always be accessed via the filesystem. The
1746-
* following refs are special:
1747-
*
1748-
* - FETCH_HEAD may contain multiple object IDs, and each one of them
1749-
* carries additional metadata like where it came from.
1750-
*
1751-
* - MERGE_HEAD may contain multiple object IDs when merging multiple
1752-
* heads.
1753-
*
1754-
* Reading, writing or deleting references must consistently go either
1755-
* through the filesystem (special refs) or through the reference
1756-
* backend (normal ones).
1757-
*/
1758-
static const char * const special_refs[] = {
1759-
"FETCH_HEAD",
1760-
"MERGE_HEAD",
1761-
};
1762-
size_t i;
1763-
1764-
for (i = 0; i < ARRAY_SIZE(special_refs); i++)
1765-
if (!strcmp(refname, special_refs[i]))
1766-
return 1;
1767-
1768-
return 0;
1769-
}
1770-
17711743
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
17721744
struct object_id *oid, struct strbuf *referent,
17731745
unsigned int *type, int *failure_errno)
17741746
{
17751747
assert(failure_errno);
1776-
if (is_special_ref(refname))
1748+
if (is_pseudo_ref(refname))
17771749
return refs_read_special_head(ref_store, refname, oid, referent,
17781750
type, failure_errno);
17791751

refs.h

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

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

10121056
/*
10131057
* 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
@@ -359,8 +359,7 @@ static void add_pseudoref_and_head_entries(struct ref_store *ref_store,
359359
strbuf_addstr(&refname, de->d_name);
360360

361361
dtype = get_dtype(de, &path, 1);
362-
if (dtype == DT_REG && (is_pseudoref(ref_store, de->d_name) ||
363-
is_headref(ref_store, de->d_name)))
362+
if (dtype == DT_REG && is_root_ref(de->d_name))
364363
loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
365364

366365
strbuf_setlen(&refname, dirnamelen);

refs/reftable-backend.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
375375
*/
376376
if (!starts_with(iter->ref.refname, "refs/") &&
377377
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
378-
(is_pseudoref(&iter->refs->base, iter->ref.refname) ||
379-
is_headref(&iter->refs->base, iter->ref.refname)))) {
378+
is_root_ref(iter->ref.refname))) {
380379
continue;
381380
}
382381

0 commit comments

Comments
 (0)