зеркало из https://github.com/microsoft/git.git
Merge branch 'km/delete-ref-reflog-message'
"git update-ref -d" and other operations to delete references did not leave any entry in HEAD's reflog when the reference being deleted was the current branch. This is not a problem in practice because you do not want to delete the branch you are currently on, but caused renaming of the current branch to something else not to be logged in a useful way. * km/delete-ref-reflog-message: branch: record creation of renamed branch in HEAD's log rename_ref: replace empty message in HEAD's log update-ref: pass reflog message to delete_ref() delete_ref: accept a reflog message argument
This commit is contained in:
Коммит
c13c783c9d
5
branch.c
5
branch.c
|
@ -345,7 +345,8 @@ void die_if_checked_out(const char *branch, int ignore_current_worktree)
|
|||
branch, wt->path);
|
||||
}
|
||||
|
||||
int replace_each_worktree_head_symref(const char *oldref, const char *newref)
|
||||
int replace_each_worktree_head_symref(const char *oldref, const char *newref,
|
||||
const char *logmsg)
|
||||
{
|
||||
int ret = 0;
|
||||
struct worktree **worktrees = get_worktrees(0);
|
||||
|
@ -358,7 +359,7 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref)
|
|||
continue;
|
||||
|
||||
if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
|
||||
newref)) {
|
||||
newref, logmsg)) {
|
||||
ret = -1;
|
||||
error(_("HEAD of working tree %s is not updated"),
|
||||
worktrees[i]->path);
|
||||
|
|
3
branch.h
3
branch.h
|
@ -71,6 +71,7 @@ extern void die_if_checked_out(const char *branch, int ignore_current_worktree);
|
|||
* This will be used when renaming a branch. Returns 0 if successful, non-zero
|
||||
* otherwise.
|
||||
*/
|
||||
extern int replace_each_worktree_head_symref(const char *oldref, const char *newref);
|
||||
extern int replace_each_worktree_head_symref(const char *oldref, const char *newref,
|
||||
const char *logmsg);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1049,7 +1049,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
|
|||
} else {
|
||||
write_state_text(state, "abort-safety", "");
|
||||
if (!state->rebasing)
|
||||
delete_ref("ORIG_HEAD", NULL, 0);
|
||||
delete_ref(NULL, "ORIG_HEAD", NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2172,7 +2172,7 @@ static void am_abort(struct am_state *state)
|
|||
has_curr_head ? &curr_head : NULL, 0,
|
||||
UPDATE_REFS_DIE_ON_ERR);
|
||||
else if (curr_branch)
|
||||
delete_ref(curr_branch, NULL, REF_NODEREF);
|
||||
delete_ref(NULL, curr_branch, NULL, REF_NODEREF);
|
||||
|
||||
free(curr_branch);
|
||||
am_destroy(state);
|
||||
|
|
|
@ -252,7 +252,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||
goto next;
|
||||
}
|
||||
|
||||
if (delete_ref(name, is_null_sha1(sha1) ? NULL : sha1,
|
||||
if (delete_ref(NULL, name, is_null_sha1(sha1) ? NULL : sha1,
|
||||
REF_NODEREF)) {
|
||||
error(remote_branch
|
||||
? _("Error deleting remote-tracking branch '%s'")
|
||||
|
@ -471,14 +471,15 @@ static void rename_branch(const char *oldname, const char *newname, int force)
|
|||
|
||||
if (rename_ref(oldref.buf, newref.buf, logmsg.buf))
|
||||
die(_("Branch rename failed"));
|
||||
strbuf_release(&logmsg);
|
||||
|
||||
if (recovery)
|
||||
warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11);
|
||||
|
||||
if (replace_each_worktree_head_symref(oldref.buf, newref.buf))
|
||||
if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
|
||||
die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
|
||||
|
||||
strbuf_release(&logmsg);
|
||||
|
||||
strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11);
|
||||
strbuf_release(&oldref);
|
||||
strbuf_addf(&newsection, "branch.%s", newref.buf + 11);
|
||||
|
|
|
@ -681,9 +681,9 @@ static int merge_abort(struct notes_merge_options *o)
|
|||
* notes_merge_abort() to remove .git/NOTES_MERGE_WORKTREE.
|
||||
*/
|
||||
|
||||
if (delete_ref("NOTES_MERGE_PARTIAL", NULL, 0))
|
||||
if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
|
||||
ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL"));
|
||||
if (delete_ref("NOTES_MERGE_REF", NULL, REF_NODEREF))
|
||||
if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NODEREF))
|
||||
ret += error(_("failed to delete ref NOTES_MERGE_REF"));
|
||||
if (notes_merge_abort(o))
|
||||
ret += error(_("failed to remove 'git notes merge' worktree"));
|
||||
|
|
|
@ -691,7 +691,7 @@ static int mv(int argc, const char **argv)
|
|||
read_ref_full(item->string, RESOLVE_REF_READING, oid.hash, &flag);
|
||||
if (!(flag & REF_ISSYMREF))
|
||||
continue;
|
||||
if (delete_ref(item->string, NULL, REF_NODEREF))
|
||||
if (delete_ref(NULL, item->string, NULL, REF_NODEREF))
|
||||
die(_("deleting '%s' failed"), item->string);
|
||||
}
|
||||
for (i = 0; i < remote_branches.nr; i++) {
|
||||
|
@ -1248,7 +1248,7 @@ static int set_head(int argc, const char **argv)
|
|||
head_name = xstrdup(states.heads.items[0].string);
|
||||
free_remote_ref_states(&states);
|
||||
} else if (opt_d && !opt_a && argc == 1) {
|
||||
if (delete_ref(buf.buf, NULL, REF_NODEREF))
|
||||
if (delete_ref(NULL, buf.buf, NULL, REF_NODEREF))
|
||||
result |= error(_("Could not delete %s"), buf.buf);
|
||||
} else
|
||||
usage_with_options(builtin_remote_sethead_usage, options);
|
||||
|
|
|
@ -121,7 +121,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
|
|||
static int delete_replace_ref(const char *name, const char *ref,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
if (delete_ref(ref, sha1, 0))
|
||||
if (delete_ref(NULL, ref, sha1, 0))
|
||||
return 1;
|
||||
printf("Deleted replace ref '%s'\n", name);
|
||||
return 0;
|
||||
|
|
|
@ -256,7 +256,7 @@ static int reset_refs(const char *rev, const struct object_id *oid)
|
|||
update_ref_oid(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
|
||||
UPDATE_REFS_MSG_ON_ERR);
|
||||
} else if (old_orig)
|
||||
delete_ref("ORIG_HEAD", old_orig->hash, 0);
|
||||
delete_ref(NULL, "ORIG_HEAD", old_orig->hash, 0);
|
||||
set_reflog_message(&msg, "updating HEAD", rev);
|
||||
update_ref_status = update_ref_oid(msg.buf, "HEAD", oid, orig, 0,
|
||||
UPDATE_REFS_MSG_ON_ERR);
|
||||
|
|
|
@ -58,7 +58,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
|
|||
die("Cannot delete %s, not a symbolic ref", argv[0]);
|
||||
if (!strcmp(argv[0], "HEAD"))
|
||||
die("deleting '%s' is not allowed", argv[0]);
|
||||
return delete_ref(argv[0], NULL, REF_NODEREF);
|
||||
return delete_ref(NULL, argv[0], NULL, REF_NODEREF);
|
||||
}
|
||||
|
||||
switch (argc) {
|
||||
|
|
|
@ -97,7 +97,7 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
|
|||
static int delete_tag(const char *name, const char *ref,
|
||||
const unsigned char *sha1, const void *cb_data)
|
||||
{
|
||||
if (delete_ref(ref, sha1, 0))
|
||||
if (delete_ref(NULL, ref, sha1, 0))
|
||||
return 1;
|
||||
printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||
return 0;
|
||||
|
|
|
@ -433,7 +433,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
|
|||
* For purposes of backwards compatibility, we treat
|
||||
* NULL_SHA1 as "don't care" here:
|
||||
*/
|
||||
return delete_ref(refname,
|
||||
return delete_ref(msg, refname,
|
||||
(oldval && !is_null_sha1(oldsha1)) ? oldsha1 : NULL,
|
||||
flags);
|
||||
else
|
||||
|
|
|
@ -1752,7 +1752,7 @@ static int update_branch(struct branch *b)
|
|||
|
||||
if (is_null_sha1(b->sha1)) {
|
||||
if (b->delete)
|
||||
delete_ref(b->name, NULL, 0);
|
||||
delete_ref(NULL, b->name, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
if (read_ref(b->name, old_sha1))
|
||||
|
|
6
refs.c
6
refs.c
|
@ -592,8 +592,8 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
|
|||
return 0;
|
||||
}
|
||||
|
||||
int delete_ref(const char *refname, const unsigned char *old_sha1,
|
||||
unsigned int flags)
|
||||
int delete_ref(const char *msg, const char *refname,
|
||||
const unsigned char *old_sha1, unsigned int flags)
|
||||
{
|
||||
struct ref_transaction *transaction;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
|
@ -604,7 +604,7 @@ int delete_ref(const char *refname, const unsigned char *old_sha1,
|
|||
transaction = ref_transaction_begin(&err);
|
||||
if (!transaction ||
|
||||
ref_transaction_delete(transaction, refname, old_sha1,
|
||||
flags, NULL, &err) ||
|
||||
flags, msg, &err) ||
|
||||
ref_transaction_commit(transaction, &err)) {
|
||||
error("%s", err.buf);
|
||||
ref_transaction_free(transaction);
|
||||
|
|
7
refs.h
7
refs.h
|
@ -276,8 +276,8 @@ int reflog_exists(const char *refname);
|
|||
* exists, regardless of its old value. It is an error for old_sha1 to
|
||||
* be NULL_SHA1. flags is passed through to ref_transaction_delete().
|
||||
*/
|
||||
int delete_ref(const char *refname, const unsigned char *old_sha1,
|
||||
unsigned int flags);
|
||||
int delete_ref(const char *msg, const char *refname,
|
||||
const unsigned char *old_sha1, unsigned int flags);
|
||||
|
||||
/*
|
||||
* Delete the specified references. If there are any problems, emit
|
||||
|
@ -334,7 +334,8 @@ int create_symref(const char *refname, const char *target, const char *logmsg);
|
|||
* $GIT_DIR points to.
|
||||
* Return 0 if successful, non-zero otherwise.
|
||||
* */
|
||||
int set_worktree_head_symref(const char *gitdir, const char *target);
|
||||
int set_worktree_head_symref(const char *gitdir, const char *target,
|
||||
const char *logmsg);
|
||||
|
||||
enum action_on_err {
|
||||
UPDATE_REFS_MSG_ON_ERR,
|
||||
|
|
|
@ -2481,7 +2481,7 @@ static int files_delete_refs(struct ref_store *ref_store,
|
|||
for (i = 0; i < refnames->nr; i++) {
|
||||
const char *refname = refnames->items[i].string;
|
||||
|
||||
if (delete_ref(refname, NULL, flags))
|
||||
if (delete_ref(NULL, refname, NULL, flags))
|
||||
result |= error(_("could not remove reference %s"), refname);
|
||||
}
|
||||
|
||||
|
@ -2596,7 +2596,7 @@ static int files_rename_ref(struct ref_store *ref_store,
|
|||
return error("unable to move logfile logs/%s to "TMP_RENAMED_LOG": %s",
|
||||
oldrefname, strerror(errno));
|
||||
|
||||
if (delete_ref(oldrefname, orig_sha1, REF_NODEREF)) {
|
||||
if (delete_ref(logmsg, oldrefname, orig_sha1, REF_NODEREF)) {
|
||||
error("unable to delete old %s", oldrefname);
|
||||
goto rollback;
|
||||
}
|
||||
|
@ -2610,7 +2610,7 @@ static int files_rename_ref(struct ref_store *ref_store,
|
|||
*/
|
||||
if (!read_ref_full(newrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
|
||||
sha1, NULL) &&
|
||||
delete_ref(newrefname, NULL, REF_NODEREF)) {
|
||||
delete_ref(NULL, newrefname, NULL, REF_NODEREF)) {
|
||||
if (errno == EISDIR) {
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
int result;
|
||||
|
@ -3044,7 +3044,7 @@ static int files_create_symref(struct ref_store *ref_store,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int set_worktree_head_symref(const char *gitdir, const char *target)
|
||||
int set_worktree_head_symref(const char *gitdir, const char *target, const char *logmsg)
|
||||
{
|
||||
static struct lock_file head_lock;
|
||||
struct ref_lock *lock;
|
||||
|
@ -3072,7 +3072,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target)
|
|||
lock->lk = &head_lock;
|
||||
lock->ref_name = xstrdup(head_rel);
|
||||
|
||||
ret = create_symref_locked(lock, head_rel, target, NULL);
|
||||
ret = create_symref_locked(lock, head_rel, target, logmsg);
|
||||
|
||||
unlock_ref(lock); /* will free lock */
|
||||
strbuf_release(&head_path);
|
||||
|
|
|
@ -85,6 +85,24 @@ test_expect_success "delete $m (by HEAD)" '
|
|||
'
|
||||
rm -f .git/$m
|
||||
|
||||
test_expect_success "deleting current branch adds message to HEAD's log" '
|
||||
git update-ref $m $A &&
|
||||
git symbolic-ref HEAD $m &&
|
||||
git update-ref -m delete-$m -d $m &&
|
||||
! test -f .git/$m &&
|
||||
grep "delete-$m$" .git/logs/HEAD
|
||||
'
|
||||
rm -f .git/$m
|
||||
|
||||
test_expect_success "deleting by HEAD adds message to HEAD's log" '
|
||||
git update-ref $m $A &&
|
||||
git symbolic-ref HEAD $m &&
|
||||
git update-ref -m delete-by-head -d HEAD &&
|
||||
! test -f .git/$m &&
|
||||
grep "delete-by-head$" .git/logs/HEAD
|
||||
'
|
||||
rm -f .git/$m
|
||||
|
||||
test_expect_success 'update-ref does not create reflogs by default' '
|
||||
test_when_finished "git update-ref -d $outside" &&
|
||||
git update-ref $outside $A &&
|
||||
|
|
|
@ -139,6 +139,12 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
|
|||
test $(git rev-parse --abbrev-ref HEAD) = bam
|
||||
'
|
||||
|
||||
test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD' '
|
||||
msg="Branch: renamed refs/heads/baz to refs/heads/bam" &&
|
||||
grep " 0\{40\}.*$msg$" .git/logs/HEAD &&
|
||||
grep "^0\{40\}.*$msg$" .git/logs/HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'git branch -M baz bam should succeed when baz is checked out as linked working tree' '
|
||||
git checkout master &&
|
||||
git worktree add -b baz bazdir &&
|
||||
|
|
|
@ -299,7 +299,7 @@ void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int v
|
|||
if (verbose)
|
||||
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
|
||||
if (ref->deletion) {
|
||||
delete_ref(rs.dst, NULL, 0);
|
||||
delete_ref(NULL, rs.dst, NULL, 0);
|
||||
} else
|
||||
update_ref("update by push", rs.dst,
|
||||
ref->new_oid.hash, NULL, 0, 0);
|
||||
|
|
Загрузка…
Ссылка в новой задаче