Skip to content

Commit 8282f95

Browse files
committed
Merge branch 'ps/not-so-many-refs-are-special'
Define "special ref" as a very narrow set that consists of FETCH_HEAD and MERGE_HEAD, and clarify everything else that used to be classified as such are actually just pseudorefs. * ps/not-so-many-refs-are-special: Documentation: add "special refs" to the glossary refs: redefine special refs refs: convert MERGE_AUTOSTASH to become a normal pseudo-ref sequencer: introduce functions to handle autostashes via refs refs: convert AUTO_MERGE to become a normal pseudo-ref sequencer: delete REBASE_HEAD in correct repo when picking commits sequencer: clean up pseudo refs with REF_NO_DEREF
2 parents 9869e02 + 8df4c5d commit 8282f95

File tree

13 files changed

+132
-78
lines changed

13 files changed

+132
-78
lines changed

Documentation/glossary-content.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,20 @@ The most notable example is `HEAD`.
638638
An <<def_object,object>> used to temporarily store the contents of a
639639
<<def_dirty,dirty>> working directory and the index for future reuse.
640640

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

branch.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,9 @@ void remove_merge_branch_state(struct repository *r)
817817
unlink(git_path_merge_rr(r));
818818
unlink(git_path_merge_msg(r));
819819
unlink(git_path_merge_mode(r));
820-
unlink(git_path_auto_merge(r));
821-
save_autostash(git_path_merge_autostash(r));
820+
refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
821+
NULL, REF_NO_DEREF);
822+
save_autostash_ref(r, "MERGE_AUTOSTASH");
822823
}
823824

824825
void remove_branch_state(struct repository *r, int verbose)

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1877,7 +1877,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
18771877
&oid, flags);
18781878
}
18791879

1880-
apply_autostash(git_path_merge_autostash(the_repository));
1880+
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
18811881

18821882
cleanup:
18831883
strbuf_release(&author_ident);

builtin/merge.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ static void finish(struct commit *head_commit,
476476
run_hooks_l("post-merge", squash ? "1" : "0", NULL);
477477

478478
if (new_head)
479-
apply_autostash(git_path_merge_autostash(the_repository));
479+
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
480480
strbuf_release(&reflog_message);
481481
}
482482

@@ -1315,7 +1315,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13151315
if (abort_current_merge) {
13161316
int nargc = 2;
13171317
const char *nargv[] = {"reset", "--merge", NULL};
1318-
struct strbuf stash_oid = STRBUF_INIT;
1318+
char stash_oid_hex[GIT_MAX_HEXSZ + 1];
1319+
struct object_id stash_oid = {0};
13191320

13201321
if (orig_argc != 2)
13211322
usage_msg_opt(_("--abort expects no arguments"),
@@ -1324,17 +1325,17 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13241325
if (!file_exists(git_path_merge_head(the_repository)))
13251326
die(_("There is no merge to abort (MERGE_HEAD missing)."));
13261327

1327-
if (read_oneliner(&stash_oid, git_path_merge_autostash(the_repository),
1328-
READ_ONELINER_SKIP_IF_EMPTY))
1329-
unlink(git_path_merge_autostash(the_repository));
1328+
if (!read_ref("MERGE_AUTOSTASH", &stash_oid))
1329+
delete_ref("", "MERGE_AUTOSTASH", &stash_oid, REF_NO_DEREF);
13301330

13311331
/* Invoke 'git reset --merge' */
13321332
ret = cmd_reset(nargc, nargv, prefix);
13331333

1334-
if (stash_oid.len)
1335-
apply_autostash_oid(stash_oid.buf);
1334+
if (!is_null_oid(&stash_oid)) {
1335+
oid_to_hex_r(stash_oid_hex, &stash_oid);
1336+
apply_autostash_oid(stash_oid_hex);
1337+
}
13361338

1337-
strbuf_release(&stash_oid);
13381339
goto done;
13391340
}
13401341

@@ -1563,13 +1564,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
15631564
}
15641565

15651566
if (autostash)
1566-
create_autostash(the_repository,
1567-
git_path_merge_autostash(the_repository));
1567+
create_autostash_ref(the_repository, "MERGE_AUTOSTASH");
15681568
if (checkout_fast_forward(the_repository,
15691569
&head_commit->object.oid,
15701570
&commit->object.oid,
15711571
overwrite_ignore)) {
1572-
apply_autostash(git_path_merge_autostash(the_repository));
1572+
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
15731573
ret = 1;
15741574
goto done;
15751575
}
@@ -1655,8 +1655,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
16551655
die_ff_impossible();
16561656

16571657
if (autostash)
1658-
create_autostash(the_repository,
1659-
git_path_merge_autostash(the_repository));
1658+
create_autostash_ref(the_repository, "MERGE_AUTOSTASH");
16601659

16611660
/* We are going to make a new commit. */
16621661
git_committer_info(IDENT_STRICT);
@@ -1741,7 +1740,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
17411740
else
17421741
fprintf(stderr, _("Merge with strategy %s failed.\n"),
17431742
use_strategies[0]->name);
1744-
apply_autostash(git_path_merge_autostash(the_repository));
1743+
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
17451744
ret = 2;
17461745
goto done;
17471746
} else if (best_strategy == wt_strategy)

builtin/rebase.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ static int finish_rebase(struct rebase_options *opts)
515515
int ret = 0;
516516

517517
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
518-
unlink(git_path_auto_merge(the_repository));
518+
delete_ref(NULL, "AUTO_MERGE", NULL, REF_NO_DEREF);
519519
apply_autostash(state_dir_path("autostash", opts));
520520
/*
521521
* We ignore errors in 'git maintenance run --auto', since the

merge-ort.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "path.h"
3939
#include "promisor-remote.h"
4040
#include "read-cache-ll.h"
41+
#include "refs.h"
4142
#include "revision.h"
4243
#include "sparse-index.h"
4344
#include "strmap.h"
@@ -4659,9 +4660,6 @@ void merge_switch_to_result(struct merge_options *opt,
46594660
{
46604661
assert(opt->priv == NULL);
46614662
if (result->clean >= 0 && update_worktree_and_index) {
4662-
const char *filename;
4663-
FILE *fp;
4664-
46654663
trace2_region_enter("merge", "checkout", opt->repo);
46664664
if (checkout(opt, head, result->tree)) {
46674665
/* failure to function */
@@ -4687,10 +4685,17 @@ void merge_switch_to_result(struct merge_options *opt,
46874685
trace2_region_leave("merge", "record_conflicted", opt->repo);
46884686

46894687
trace2_region_enter("merge", "write_auto_merge", opt->repo);
4690-
filename = git_path_auto_merge(opt->repo);
4691-
fp = xfopen(filename, "w");
4692-
fprintf(fp, "%s\n", oid_to_hex(&result->tree->object.oid));
4693-
fclose(fp);
4688+
if (refs_update_ref(get_main_ref_store(opt->repo), "", "AUTO_MERGE",
4689+
&result->tree->object.oid, NULL, REF_NO_DEREF,
4690+
UPDATE_REFS_MSG_ON_ERR)) {
4691+
/* failure to function */
4692+
opt->priv = NULL;
4693+
result->clean = -1;
4694+
merge_finalize(opt, result);
4695+
trace2_region_leave("merge", "write_auto_merge",
4696+
opt->repo);
4697+
return;
4698+
}
46944699
trace2_region_leave("merge", "write_auto_merge", opt->repo);
46954700
}
46964701
if (display_update_msgs)

path.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,5 @@ REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
15881588
REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
15891589
REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
15901590
REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
1591-
REPO_GIT_PATH_FUNC(merge_autostash, "MERGE_AUTOSTASH")
1592-
REPO_GIT_PATH_FUNC(auto_merge, "AUTO_MERGE")
15931591
REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
15941592
REPO_GIT_PATH_FUNC(shallow, "shallow")

path.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,6 @@ const char *git_path_merge_msg(struct repository *r);
175175
const char *git_path_merge_rr(struct repository *r);
176176
const char *git_path_merge_mode(struct repository *r);
177177
const char *git_path_merge_head(struct repository *r);
178-
const char *git_path_merge_autostash(struct repository *r);
179-
const char *git_path_auto_merge(struct repository *r);
180178
const char *git_path_fetch_head(struct repository *r);
181179
const char *git_path_shallow(struct repository *r);
182180

refs.c

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,44 +1839,23 @@ static int refs_read_special_head(struct ref_store *ref_store,
18391839
static int is_special_ref(const char *refname)
18401840
{
18411841
/*
1842-
* Special references get written and read directly via the filesystem
1843-
* by the subsystems that create them. Thus, they must not go through
1844-
* the reference backend but must instead be read directly. It is
1845-
* arguable whether this behaviour is sensible, or whether it's simply
1846-
* a leaky abstraction enabled by us only having a single reference
1847-
* backend implementation. But at least for a subset of references it
1848-
* indeed does make sense to treat them specially:
1842+
* Special references are refs that have different semantics compared
1843+
* to "normal" refs. These refs can thus not be stored in the ref
1844+
* backend, but must always be accessed via the filesystem. The
1845+
* following refs are special:
18491846
*
18501847
* - FETCH_HEAD may contain multiple object IDs, and each one of them
18511848
* carries additional metadata like where it came from.
18521849
*
18531850
* - MERGE_HEAD may contain multiple object IDs when merging multiple
18541851
* heads.
18551852
*
1856-
* There are some exceptions that you might expect to see on this list
1857-
* but which are handled exclusively via the reference backend:
1858-
*
1859-
* - BISECT_EXPECTED_REV
1860-
*
1861-
* - CHERRY_PICK_HEAD
1862-
*
1863-
* - HEAD
1864-
*
1865-
* - ORIG_HEAD
1866-
*
1867-
* - "rebase-apply/" and "rebase-merge/" contain all of the state for
1868-
* rebases, including some reference-like files. These are
1869-
* exclusively read and written via the filesystem and never go
1870-
* through the refdb.
1871-
*
1872-
* Writing or deleting references must consistently go either through
1873-
* the filesystem (special refs) or through the reference backend
1874-
* (normal ones).
1853+
* Reading, writing or deleting references must consistently go either
1854+
* through the filesystem (special refs) or through the reference
1855+
* backend (normal ones).
18751856
*/
18761857
static const char * const special_refs[] = {
1877-
"AUTO_MERGE",
18781858
"FETCH_HEAD",
1879-
"MERGE_AUTOSTASH",
18801859
"MERGE_HEAD",
18811860
};
18821861
size_t i;

repository.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,6 @@ static void repo_clear_path_cache(struct repo_path_cache *cache)
262262
FREE_AND_NULL(cache->merge_rr);
263263
FREE_AND_NULL(cache->merge_mode);
264264
FREE_AND_NULL(cache->merge_head);
265-
FREE_AND_NULL(cache->merge_autostash);
266-
FREE_AND_NULL(cache->auto_merge);
267265
FREE_AND_NULL(cache->fetch_head);
268266
FREE_AND_NULL(cache->shallow);
269267
}

0 commit comments

Comments
 (0)