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_DEREFmaint
commit
8282f95928
|
@ -638,6 +638,20 @@ The most notable example is `HEAD`.
|
|||
An <<def_object,object>> used to temporarily store the contents of a
|
||||
<<def_dirty,dirty>> working directory and the index for future reuse.
|
||||
|
||||
[[def_special_ref]]special ref::
|
||||
A ref that has different semantics than normal refs. These refs can be
|
||||
accessed via normal Git commands but may not behave the same as a
|
||||
normal ref in some cases.
|
||||
+
|
||||
The following special refs are known to Git:
|
||||
|
||||
- "`FETCH_HEAD`" is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
|
||||
may refer to multiple object IDs. Each object ID is annotated with metadata
|
||||
indicating where it was fetched from and its fetch status.
|
||||
|
||||
- "`MERGE_HEAD`" is written by linkgit:git-merge[1] when resolving merge
|
||||
conflicts. It contains all commit IDs which are being merged.
|
||||
|
||||
[[def_submodule]]submodule::
|
||||
A <<def_repository,repository>> that holds the history of a
|
||||
separate project inside another repository (the latter of
|
||||
|
|
5
branch.c
5
branch.c
|
@ -817,8 +817,9 @@ void remove_merge_branch_state(struct repository *r)
|
|||
unlink(git_path_merge_rr(r));
|
||||
unlink(git_path_merge_msg(r));
|
||||
unlink(git_path_merge_mode(r));
|
||||
unlink(git_path_auto_merge(r));
|
||||
save_autostash(git_path_merge_autostash(r));
|
||||
refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
|
||||
NULL, REF_NO_DEREF);
|
||||
save_autostash_ref(r, "MERGE_AUTOSTASH");
|
||||
}
|
||||
|
||||
void remove_branch_state(struct repository *r, int verbose)
|
||||
|
|
|
@ -1877,7 +1877,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
&oid, flags);
|
||||
}
|
||||
|
||||
apply_autostash(git_path_merge_autostash(the_repository));
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
|
||||
cleanup:
|
||||
strbuf_release(&author_ident);
|
||||
|
|
|
@ -476,7 +476,7 @@ static void finish(struct commit *head_commit,
|
|||
run_hooks_l("post-merge", squash ? "1" : "0", NULL);
|
||||
|
||||
if (new_head)
|
||||
apply_autostash(git_path_merge_autostash(the_repository));
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
strbuf_release(&reflog_message);
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1315,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||
if (abort_current_merge) {
|
||||
int nargc = 2;
|
||||
const char *nargv[] = {"reset", "--merge", NULL};
|
||||
struct strbuf stash_oid = STRBUF_INIT;
|
||||
char stash_oid_hex[GIT_MAX_HEXSZ + 1];
|
||||
struct object_id stash_oid = {0};
|
||||
|
||||
if (orig_argc != 2)
|
||||
usage_msg_opt(_("--abort expects no arguments"),
|
||||
|
@ -1324,17 +1325,17 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||
if (!file_exists(git_path_merge_head(the_repository)))
|
||||
die(_("There is no merge to abort (MERGE_HEAD missing)."));
|
||||
|
||||
if (read_oneliner(&stash_oid, git_path_merge_autostash(the_repository),
|
||||
READ_ONELINER_SKIP_IF_EMPTY))
|
||||
unlink(git_path_merge_autostash(the_repository));
|
||||
if (!read_ref("MERGE_AUTOSTASH", &stash_oid))
|
||||
delete_ref("", "MERGE_AUTOSTASH", &stash_oid, REF_NO_DEREF);
|
||||
|
||||
/* Invoke 'git reset --merge' */
|
||||
ret = cmd_reset(nargc, nargv, prefix);
|
||||
|
||||
if (stash_oid.len)
|
||||
apply_autostash_oid(stash_oid.buf);
|
||||
if (!is_null_oid(&stash_oid)) {
|
||||
oid_to_hex_r(stash_oid_hex, &stash_oid);
|
||||
apply_autostash_oid(stash_oid_hex);
|
||||
}
|
||||
|
||||
strbuf_release(&stash_oid);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -1563,13 +1564,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
|
||||
if (autostash)
|
||||
create_autostash(the_repository,
|
||||
git_path_merge_autostash(the_repository));
|
||||
create_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
if (checkout_fast_forward(the_repository,
|
||||
&head_commit->object.oid,
|
||||
&commit->object.oid,
|
||||
overwrite_ignore)) {
|
||||
apply_autostash(git_path_merge_autostash(the_repository));
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1655,8 +1655,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||
die_ff_impossible();
|
||||
|
||||
if (autostash)
|
||||
create_autostash(the_repository,
|
||||
git_path_merge_autostash(the_repository));
|
||||
create_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
|
||||
/* We are going to make a new commit. */
|
||||
git_committer_info(IDENT_STRICT);
|
||||
|
@ -1741,7 +1740,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||
else
|
||||
fprintf(stderr, _("Merge with strategy %s failed.\n"),
|
||||
use_strategies[0]->name);
|
||||
apply_autostash(git_path_merge_autostash(the_repository));
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
ret = 2;
|
||||
goto done;
|
||||
} else if (best_strategy == wt_strategy)
|
||||
|
|
|
@ -515,7 +515,7 @@ static int finish_rebase(struct rebase_options *opts)
|
|||
int ret = 0;
|
||||
|
||||
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
|
||||
unlink(git_path_auto_merge(the_repository));
|
||||
delete_ref(NULL, "AUTO_MERGE", NULL, REF_NO_DEREF);
|
||||
apply_autostash(state_dir_path("autostash", opts));
|
||||
/*
|
||||
* We ignore errors in 'git maintenance run --auto', since the
|
||||
|
|
19
merge-ort.c
19
merge-ort.c
|
@ -38,6 +38,7 @@
|
|||
#include "path.h"
|
||||
#include "promisor-remote.h"
|
||||
#include "read-cache-ll.h"
|
||||
#include "refs.h"
|
||||
#include "revision.h"
|
||||
#include "sparse-index.h"
|
||||
#include "strmap.h"
|
||||
|
@ -4659,9 +4660,6 @@ void merge_switch_to_result(struct merge_options *opt,
|
|||
{
|
||||
assert(opt->priv == NULL);
|
||||
if (result->clean >= 0 && update_worktree_and_index) {
|
||||
const char *filename;
|
||||
FILE *fp;
|
||||
|
||||
trace2_region_enter("merge", "checkout", opt->repo);
|
||||
if (checkout(opt, head, result->tree)) {
|
||||
/* failure to function */
|
||||
|
@ -4687,10 +4685,17 @@ void merge_switch_to_result(struct merge_options *opt,
|
|||
trace2_region_leave("merge", "record_conflicted", opt->repo);
|
||||
|
||||
trace2_region_enter("merge", "write_auto_merge", opt->repo);
|
||||
filename = git_path_auto_merge(opt->repo);
|
||||
fp = xfopen(filename, "w");
|
||||
fprintf(fp, "%s\n", oid_to_hex(&result->tree->object.oid));
|
||||
fclose(fp);
|
||||
if (refs_update_ref(get_main_ref_store(opt->repo), "", "AUTO_MERGE",
|
||||
&result->tree->object.oid, NULL, REF_NO_DEREF,
|
||||
UPDATE_REFS_MSG_ON_ERR)) {
|
||||
/* failure to function */
|
||||
opt->priv = NULL;
|
||||
result->clean = -1;
|
||||
merge_finalize(opt, result);
|
||||
trace2_region_leave("merge", "write_auto_merge",
|
||||
opt->repo);
|
||||
return;
|
||||
}
|
||||
trace2_region_leave("merge", "write_auto_merge", opt->repo);
|
||||
}
|
||||
if (display_update_msgs)
|
||||
|
|
2
path.c
2
path.c
|
@ -1588,7 +1588,5 @@ REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
|
|||
REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
|
||||
REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
|
||||
REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
|
||||
REPO_GIT_PATH_FUNC(merge_autostash, "MERGE_AUTOSTASH")
|
||||
REPO_GIT_PATH_FUNC(auto_merge, "AUTO_MERGE")
|
||||
REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
|
||||
REPO_GIT_PATH_FUNC(shallow, "shallow")
|
||||
|
|
2
path.h
2
path.h
|
@ -175,8 +175,6 @@ const char *git_path_merge_msg(struct repository *r);
|
|||
const char *git_path_merge_rr(struct repository *r);
|
||||
const char *git_path_merge_mode(struct repository *r);
|
||||
const char *git_path_merge_head(struct repository *r);
|
||||
const char *git_path_merge_autostash(struct repository *r);
|
||||
const char *git_path_auto_merge(struct repository *r);
|
||||
const char *git_path_fetch_head(struct repository *r);
|
||||
const char *git_path_shallow(struct repository *r);
|
||||
|
||||
|
|
35
refs.c
35
refs.c
|
@ -1839,13 +1839,10 @@ done:
|
|||
static int is_special_ref(const char *refname)
|
||||
{
|
||||
/*
|
||||
* Special references get written and read directly via the filesystem
|
||||
* by the subsystems that create them. Thus, they must not go through
|
||||
* the reference backend but must instead be read directly. It is
|
||||
* arguable whether this behaviour is sensible, or whether it's simply
|
||||
* a leaky abstraction enabled by us only having a single reference
|
||||
* backend implementation. But at least for a subset of references it
|
||||
* indeed does make sense to treat them specially:
|
||||
* Special references are refs that have different semantics compared
|
||||
* to "normal" refs. These refs can thus not be stored in the ref
|
||||
* backend, but must always be accessed via the filesystem. The
|
||||
* following refs are special:
|
||||
*
|
||||
* - FETCH_HEAD may contain multiple object IDs, and each one of them
|
||||
* carries additional metadata like where it came from.
|
||||
|
@ -1853,30 +1850,12 @@ static int is_special_ref(const char *refname)
|
|||
* - MERGE_HEAD may contain multiple object IDs when merging multiple
|
||||
* heads.
|
||||
*
|
||||
* There are some exceptions that you might expect to see on this list
|
||||
* but which are handled exclusively via the reference backend:
|
||||
*
|
||||
* - BISECT_EXPECTED_REV
|
||||
*
|
||||
* - CHERRY_PICK_HEAD
|
||||
*
|
||||
* - HEAD
|
||||
*
|
||||
* - ORIG_HEAD
|
||||
*
|
||||
* - "rebase-apply/" and "rebase-merge/" contain all of the state for
|
||||
* rebases, including some reference-like files. These are
|
||||
* exclusively read and written via the filesystem and never go
|
||||
* through the refdb.
|
||||
*
|
||||
* Writing or deleting references must consistently go either through
|
||||
* the filesystem (special refs) or through the reference backend
|
||||
* (normal ones).
|
||||
* Reading, writing or deleting references must consistently go either
|
||||
* through the filesystem (special refs) or through the reference
|
||||
* backend (normal ones).
|
||||
*/
|
||||
static const char * const special_refs[] = {
|
||||
"AUTO_MERGE",
|
||||
"FETCH_HEAD",
|
||||
"MERGE_AUTOSTASH",
|
||||
"MERGE_HEAD",
|
||||
};
|
||||
size_t i;
|
||||
|
|
|
@ -262,8 +262,6 @@ static void repo_clear_path_cache(struct repo_path_cache *cache)
|
|||
FREE_AND_NULL(cache->merge_rr);
|
||||
FREE_AND_NULL(cache->merge_mode);
|
||||
FREE_AND_NULL(cache->merge_head);
|
||||
FREE_AND_NULL(cache->merge_autostash);
|
||||
FREE_AND_NULL(cache->auto_merge);
|
||||
FREE_AND_NULL(cache->fetch_head);
|
||||
FREE_AND_NULL(cache->shallow);
|
||||
}
|
||||
|
|
|
@ -67,8 +67,6 @@ struct repo_path_cache {
|
|||
char *merge_rr;
|
||||
char *merge_mode;
|
||||
char *merge_head;
|
||||
char *merge_autostash;
|
||||
char *auto_merge;
|
||||
char *fetch_head;
|
||||
char *shallow;
|
||||
};
|
||||
|
|
87
sequencer.c
87
sequencer.c
|
@ -474,7 +474,7 @@ static void print_advice(struct repository *r, int show_hint,
|
|||
* of the commit itself so remove CHERRY_PICK_HEAD
|
||||
*/
|
||||
refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
|
||||
NULL, 0);
|
||||
NULL, REF_NO_DEREF);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1667,7 +1667,7 @@ static int do_commit(struct repository *r,
|
|||
strbuf_release(&sb);
|
||||
if (!res) {
|
||||
refs_delete_ref(get_main_ref_store(r), "",
|
||||
"CHERRY_PICK_HEAD", NULL, 0);
|
||||
"CHERRY_PICK_HEAD", NULL, REF_NO_DEREF);
|
||||
unlink(git_path_merge_msg(r));
|
||||
if (!is_rebase_i(opts))
|
||||
print_commit_summary(r, NULL, &oid,
|
||||
|
@ -2406,9 +2406,10 @@ static int do_pick_commit(struct repository *r,
|
|||
} else if (allow == 2) {
|
||||
drop_commit = 1;
|
||||
refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
|
||||
NULL, 0);
|
||||
NULL, REF_NO_DEREF);
|
||||
unlink(git_path_merge_msg(r));
|
||||
unlink(git_path_auto_merge(r));
|
||||
refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
|
||||
NULL, REF_NO_DEREF);
|
||||
fprintf(stderr,
|
||||
_("dropping %s %s -- patch contents already upstream\n"),
|
||||
oid_to_hex(&commit->object.oid), msg.subject);
|
||||
|
@ -2802,7 +2803,7 @@ void sequencer_post_commit_cleanup(struct repository *r, int verbose)
|
|||
|
||||
if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD")) {
|
||||
if (!refs_delete_ref(get_main_ref_store(r), "",
|
||||
"CHERRY_PICK_HEAD", NULL, 0) &&
|
||||
"CHERRY_PICK_HEAD", NULL, REF_NO_DEREF) &&
|
||||
verbose)
|
||||
warning(_("cancelling a cherry picking in progress"));
|
||||
opts.action = REPLAY_PICK;
|
||||
|
@ -2811,14 +2812,15 @@ void sequencer_post_commit_cleanup(struct repository *r, int verbose)
|
|||
|
||||
if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
|
||||
if (!refs_delete_ref(get_main_ref_store(r), "", "REVERT_HEAD",
|
||||
NULL, 0) &&
|
||||
NULL, REF_NO_DEREF) &&
|
||||
verbose)
|
||||
warning(_("cancelling a revert in progress"));
|
||||
opts.action = REPLAY_REVERT;
|
||||
need_cleanup = 1;
|
||||
}
|
||||
|
||||
unlink(git_path_auto_merge(r));
|
||||
refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
|
||||
NULL, REF_NO_DEREF);
|
||||
|
||||
if (!need_cleanup)
|
||||
return;
|
||||
|
@ -4116,7 +4118,7 @@ static int do_merge(struct repository *r,
|
|||
|
||||
strbuf_release(&ref_name);
|
||||
refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
|
||||
NULL, 0);
|
||||
NULL, REF_NO_DEREF);
|
||||
rollback_lock_file(&lock);
|
||||
|
||||
ret = run_command(&cmd);
|
||||
|
@ -4461,12 +4463,17 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void create_autostash(struct repository *r, const char *path)
|
||||
static void create_autostash_internal(struct repository *r,
|
||||
const char *path,
|
||||
const char *refname)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct lock_file lock_file = LOCK_INIT;
|
||||
int fd;
|
||||
|
||||
if (path && refname)
|
||||
BUG("can only pass path or refname");
|
||||
|
||||
fd = repo_hold_locked_index(r, &lock_file, 0);
|
||||
refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL);
|
||||
if (0 <= fd)
|
||||
|
@ -4493,10 +4500,16 @@ void create_autostash(struct repository *r, const char *path)
|
|||
strbuf_reset(&buf);
|
||||
strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV);
|
||||
|
||||
if (path) {
|
||||
if (safe_create_leading_directories_const(path))
|
||||
die(_("Could not create directory for '%s'"),
|
||||
path);
|
||||
write_file(path, "%s", oid_to_hex(&oid));
|
||||
} else {
|
||||
refs_update_ref(get_main_ref_store(r), "", refname,
|
||||
&oid, null_oid(), 0, UPDATE_REFS_DIE_ON_ERR);
|
||||
}
|
||||
|
||||
printf(_("Created autostash: %s\n"), buf.buf);
|
||||
if (reset_head(r, &ropts) < 0)
|
||||
die(_("could not reset --hard"));
|
||||
|
@ -4507,6 +4520,16 @@ void create_autostash(struct repository *r, const char *path)
|
|||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
void create_autostash(struct repository *r, const char *path)
|
||||
{
|
||||
create_autostash_internal(r, path, NULL);
|
||||
}
|
||||
|
||||
void create_autostash_ref(struct repository *r, const char *refname)
|
||||
{
|
||||
create_autostash_internal(r, NULL, refname);
|
||||
}
|
||||
|
||||
static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply)
|
||||
{
|
||||
struct child_process child = CHILD_PROCESS_INIT;
|
||||
|
@ -4584,6 +4607,41 @@ int apply_autostash_oid(const char *stash_oid)
|
|||
return apply_save_autostash_oid(stash_oid, 1);
|
||||
}
|
||||
|
||||
static int apply_save_autostash_ref(struct repository *r, const char *refname,
|
||||
int attempt_apply)
|
||||
{
|
||||
struct object_id stash_oid;
|
||||
char stash_oid_hex[GIT_MAX_HEXSZ + 1];
|
||||
int flag, ret;
|
||||
|
||||
if (!refs_ref_exists(get_main_ref_store(r), refname))
|
||||
return 0;
|
||||
|
||||
if (!refs_resolve_ref_unsafe(get_main_ref_store(r), refname,
|
||||
RESOLVE_REF_READING, &stash_oid, &flag))
|
||||
return -1;
|
||||
if (flag & REF_ISSYMREF)
|
||||
return error(_("autostash reference is a symref"));
|
||||
|
||||
oid_to_hex_r(stash_oid_hex, &stash_oid);
|
||||
ret = apply_save_autostash_oid(stash_oid_hex, attempt_apply);
|
||||
|
||||
refs_delete_ref(get_main_ref_store(r), "", refname,
|
||||
&stash_oid, REF_NO_DEREF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int save_autostash_ref(struct repository *r, const char *refname)
|
||||
{
|
||||
return apply_save_autostash_ref(r, refname, 0);
|
||||
}
|
||||
|
||||
int apply_autostash_ref(struct repository *r, const char *refname)
|
||||
{
|
||||
return apply_save_autostash_ref(r, refname, 1);
|
||||
}
|
||||
|
||||
static int checkout_onto(struct repository *r, struct replay_opts *opts,
|
||||
const char *onto_name, const struct object_id *onto,
|
||||
const struct object_id *orig_head)
|
||||
|
@ -4766,8 +4824,10 @@ static int pick_commits(struct repository *r,
|
|||
}
|
||||
unlink(rebase_path_author_script());
|
||||
unlink(git_path_merge_head(r));
|
||||
unlink(git_path_auto_merge(r));
|
||||
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
|
||||
refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
|
||||
NULL, REF_NO_DEREF);
|
||||
refs_delete_ref(get_main_ref_store(r), "", "REBASE_HEAD",
|
||||
NULL, REF_NO_DEREF);
|
||||
|
||||
if (item->command == TODO_BREAK) {
|
||||
if (!opts->verbose)
|
||||
|
@ -5108,7 +5168,7 @@ static int commit_staged_changes(struct repository *r,
|
|||
if (refs_ref_exists(get_main_ref_store(r),
|
||||
"CHERRY_PICK_HEAD") &&
|
||||
refs_delete_ref(get_main_ref_store(r), "",
|
||||
"CHERRY_PICK_HEAD", NULL, 0))
|
||||
"CHERRY_PICK_HEAD", NULL, REF_NO_DEREF))
|
||||
return error(_("could not remove CHERRY_PICK_HEAD"));
|
||||
if (unlink(git_path_merge_msg(r)) && errno != ENOENT)
|
||||
return error_errno(_("could not remove '%s'"),
|
||||
|
@ -5122,7 +5182,8 @@ static int commit_staged_changes(struct repository *r,
|
|||
return error(_("could not commit staged changes."));
|
||||
unlink(rebase_path_amend());
|
||||
unlink(git_path_merge_head(r));
|
||||
unlink(git_path_auto_merge(r));
|
||||
refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
|
||||
NULL, REF_NO_DEREF);
|
||||
if (final_fixup) {
|
||||
unlink(rebase_path_fixup_msg());
|
||||
unlink(rebase_path_squash_msg());
|
||||
|
|
|
@ -225,9 +225,12 @@ void commit_post_rewrite(struct repository *r,
|
|||
const struct object_id *new_head);
|
||||
|
||||
void create_autostash(struct repository *r, const char *path);
|
||||
void create_autostash_ref(struct repository *r, const char *refname);
|
||||
int save_autostash(const char *path);
|
||||
int save_autostash_ref(struct repository *r, const char *refname);
|
||||
int apply_autostash(const char *path);
|
||||
int apply_autostash_oid(const char *stash_oid);
|
||||
int apply_autostash_ref(struct repository *r, const char *refname);
|
||||
|
||||
#define SUMMARY_INITIAL_COMMIT (1 << 0)
|
||||
#define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)
|
||||
|
|
Loading…
Reference in New Issue