Allow the creation of a ref (e.g. stash) with a reflog already in
place. For most refs (e.g. those under refs/heads), this happens
automatically, but for others, we need this option.
Currently, git does this by pre-creating the reflog, but alternate ref
backends might store reflogs somewhere other than .git/logs. Code
that now directly manipulates .git/logs should instead use git
plumbing commands.
I also added --create-reflog to git tag, just for completeness.
In a moment, we will use this argument to make git stash work with
alternate ref backends.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
<tagname> [<commit> | <object>]
'git tag' -d <tagname>...
'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
- [--column[=<options>] | --no-column] [<pattern>...]
+ [--column[=<options>] | --no-column] [--create-reflog] [<pattern>...]
[<pattern>...]
'git tag' -v <tagname>...
all, 'whitespace' removes just leading/trailing whitespace lines and
'strip' removes both whitespace and commentary.
+--create-reflog::
+ Create a reflog for the tag.
+
<tagname>::
The name of the tag to create, delete, or describe.
The new tag name must pass all checks defined by
SYNOPSIS
--------
[verse]
-'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
+'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] [--create-reflog] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
DESCRIPTION
-----------
verify SP <ref> [SP <oldvalue>] LF
option SP <opt> LF
+With `--create-reflog`, update-ref will create a reflog for each ref
+even if one would not ordinarily be created.
+
Quote fields containing whitespace as if they were strings in C source
code; i.e., surrounded by double-quotes and with backslash escapes.
Use 40 "0" characters or the empty string to specify a zero value. To
struct create_tag_options opt;
char *cleanup_arg = NULL;
int annotate = 0, force = 0, lines = -1;
+ int create_reflog = 0;
int cmdmode = 0;
const char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT };
OPT_STRING('u', "local-user", &keyid, N_("key-id"),
N_("use another key to sign the tag")),
OPT__FORCE(&force, N_("replace the tag if exists")),
+ OPT_BOOL(0, "create-reflog", &create_reflog, N_("create_reflog")),
OPT_GROUP(N_("Tag listing options")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, ref.buf, object, prev,
- 0, NULL, &err) ||
+ create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
+ NULL, &err) ||
ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
static char line_termination = '\n';
static int update_flags;
+static unsigned create_reflog_flag;
static const char *msg;
/*
if (ref_transaction_update(transaction, refname,
new_sha1, have_old ? old_sha1 : NULL,
- update_flags, msg, &err))
+ update_flags | create_reflog_flag,
+ msg, &err))
die("%s", err.buf);
update_flags = 0;
die("create %s: extra input: %s", refname, next);
if (ref_transaction_create(transaction, refname, new_sha1,
- update_flags, msg, &err))
+ update_flags | create_reflog_flag,
+ msg, &err))
die("%s", err.buf);
update_flags = 0;
unsigned char sha1[20], oldsha1[20];
int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;
unsigned int flags = 0;
+ int create_reflog = 0;
struct option options[] = {
OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
N_("update <refname> not the one it points to")),
OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")),
OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")),
+ OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create_reflog")),
OPT_END(),
};
if (msg && !*msg)
die("Refusing to perform update with empty message.");
+ create_reflog_flag = create_reflog ? REF_FORCE_CREATE_REFLOG : 0;
+
if (read_stdin) {
struct strbuf err = STRBUF_INIT;
struct ref_transaction *transaction;
return delete_ref(refname, oldval ? oldsha1 : NULL, flags);
else
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
- flags, UPDATE_REFS_DIE_ON_ERR);
+ flags | create_reflog_flag,
+ UPDATE_REFS_DIE_ON_ERR);
}
m=refs/heads/master
n_dir=refs/heads/gu
n=$n_dir/fixes
+outside=foo
test_expect_success \
"create $m" \
'
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 &&
+ git rev-parse $A >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ test_must_fail git reflog exists $outside
+'
+
+test_expect_success 'update-ref creates reflogs with --create-reflog' '
+ test_when_finished "git update-ref -d $outside" &&
+ git update-ref --create-reflog $outside $A &&
+ git rev-parse $A >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ git reflog exists $outside
+'
+
test_expect_success \
"create $m (by HEAD)" \
"git update-ref HEAD $A &&
test_cmp expect actual
'
+test_expect_success 'stdin does not create reflogs by default' '
+ test_when_finished "git update-ref -d $outside" &&
+ echo "create $outside $m" >stdin &&
+ git update-ref --stdin <stdin &&
+ git rev-parse $m >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ test_must_fail git reflog exists $outside
+'
+
+test_expect_success 'stdin creates reflogs with --create-reflog' '
+ echo "create $outside $m" >stdin &&
+ git update-ref --create-reflog --stdin <stdin &&
+ git rev-parse $m >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ git reflog exists $outside
+'
+
test_expect_success 'stdin succeeds with quoted argument' '
git update-ref -d $a &&
echo "create $a \"$m\"" >stdin &&
echo foo >foo &&
git add foo &&
git commit -m Foo &&
- git tag mytag
+ git tag mytag &&
+ test_must_fail git reflog exists refs/tags/mytag
+'
+
+test_expect_success 'creating a tag with --create-reflog should create reflog' '
+ test_when_finished "git tag -d tag_with_reflog" &&
+ git tag --create-reflog tag_with_reflog &&
+ git reflog exists refs/tags/tag_with_reflog
+'
+
+test_expect_success '--create-reflog does not create reflog on failure' '
+ test_must_fail git tag --create-reflog mytag &&
+ test_must_fail git reflog exists refs/tags/mytag
'
test_expect_success 'listing all tags if one exists should succeed' '