builtin/refs: add "rename" subcommand
Add a "rename" subcommand to git-refs(1) with the syntax: $ git refs rename <oldref> <newref> It renames <oldref> together with its reflog to <newref>; even when used on a local branch ref, the current value and the reflog of the ref are the only things that are renamed. Document it and redirect casual users to "git branch -m" if that is what they wanted to do. Co-authored-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>jch
parent
e1bc6983f3
commit
7140a75b05
|
|
@ -23,6 +23,7 @@ git refs optimize [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude
|
|||
git refs create [--message=<reason>] [--no-deref] [--create-reflog] <ref> <new-value>
|
||||
git refs delete [--message=<reason>] [--no-deref] <ref> [<old-value>]
|
||||
git refs update [--message=<reason>] [--no-deref] [--create-reflog] <ref> <new-value> [<old-value>]
|
||||
git refs rename [--message=<reason>] <old-ref> <new-ref>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
@ -71,6 +72,11 @@ update::
|
|||
`<new-value>` deletes the branch, whereas an all-zeroes `<old-value>`
|
||||
ensures that the branch does not yet exist.
|
||||
|
||||
rename::
|
||||
Rename the reference `<oldref>` to `<newref>`. The old reference must
|
||||
exist and the new reference must not yet exist, and both must have a
|
||||
well-formed name (see linkgit:git-check-ref-format[1]).
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
#define REFS_UPDATE_USAGE \
|
||||
N_("git refs update [--message=<reason>] [--no-deref] [--create-reflog] <ref> <new-value> [<old-value>]")
|
||||
|
||||
#define REFS_RENAME_USAGE \
|
||||
N_("git refs rename [--message=<reason>] <old-ref> <new-ref>")
|
||||
|
||||
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
|
||||
struct repository *repo)
|
||||
{
|
||||
|
|
@ -327,6 +330,50 @@ static int cmd_refs_update(int argc, const char **argv, const char *prefix,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_refs_rename(int argc, const char **argv, const char *prefix,
|
||||
struct repository *repo)
|
||||
{
|
||||
static char const * const refs_rename_usage[] = {
|
||||
REFS_RENAME_USAGE,
|
||||
NULL
|
||||
};
|
||||
const char *message = NULL;
|
||||
struct option opts[] = {
|
||||
OPT_STRING(0, "message", &message, N_("reason"),
|
||||
N_("reason of the update")),
|
||||
OPT_END(),
|
||||
};
|
||||
const char *oldref, *newref;
|
||||
int ret;
|
||||
|
||||
argc = parse_options(argc, argv, prefix, opts, refs_rename_usage, 0);
|
||||
if (argc != 2)
|
||||
usage(_("rename requires old and new reference name"));
|
||||
if (message && !*message)
|
||||
die(_("refusing to perform update with empty message"));
|
||||
|
||||
repo_config(repo, git_default_config, NULL);
|
||||
|
||||
oldref = argv[0];
|
||||
newref = argv[1];
|
||||
|
||||
if (check_refname_format(oldref, 0))
|
||||
die(_("invalid ref format: '%s'"), oldref);
|
||||
if (check_refname_format(newref, 0))
|
||||
die(_("invalid ref format: '%s'"), newref);
|
||||
|
||||
if (!refs_ref_exists(get_main_ref_store(repo), oldref))
|
||||
die(_("reference does not exist: '%s'"), oldref);
|
||||
if (refs_ref_exists(get_main_ref_store(repo), newref))
|
||||
die(_("reference already exists: '%s'"), newref);
|
||||
|
||||
ret = refs_rename_ref(get_main_ref_store(repo), oldref, newref, message);
|
||||
|
||||
if (ret < 0)
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cmd_refs(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
|
|
@ -341,6 +388,7 @@ int cmd_refs(int argc,
|
|||
REFS_CREATE_USAGE,
|
||||
REFS_DELETE_USAGE,
|
||||
REFS_UPDATE_USAGE,
|
||||
REFS_RENAME_USAGE,
|
||||
NULL,
|
||||
};
|
||||
parse_opt_subcommand_fn *fn = NULL;
|
||||
|
|
@ -353,6 +401,7 @@ int cmd_refs(int argc,
|
|||
OPT_SUBCOMMAND("create", &fn, cmd_refs_create),
|
||||
OPT_SUBCOMMAND("delete", &fn, cmd_refs_delete),
|
||||
OPT_SUBCOMMAND("update", &fn, cmd_refs_update),
|
||||
OPT_SUBCOMMAND("rename", &fn, cmd_refs_rename),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ integration_tests = [
|
|||
't1464-refs-delete.sh',
|
||||
't1465-refs-update.sh',
|
||||
't1466-refs-create.sh',
|
||||
't1467-refs-rename.sh',
|
||||
't1500-rev-parse.sh',
|
||||
't1501-work-tree.sh',
|
||||
't1502-rev-parse-parseopt.sh',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='git refs rename'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
setup_repo () {
|
||||
git init "$1" &&
|
||||
test_commit -C "$1" A &&
|
||||
test_commit -C "$1" B
|
||||
}
|
||||
|
||||
test_ref_matches () {
|
||||
git rev-parse "$1" >expect &&
|
||||
echo "$2" >actual &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
test_expect_success 'rename an existing reference' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
A=$(git rev-parse A) &&
|
||||
git refs update refs/heads/foo $A &&
|
||||
git refs rename refs/heads/foo refs/heads/bar &&
|
||||
test_must_fail git refs exists refs/heads/foo &&
|
||||
test_ref_matches refs/heads/bar $A
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename moves the reflog along with the reference' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
A=$(git rev-parse A) &&
|
||||
git refs update --message="rename me" refs/heads/foo $A &&
|
||||
git refs rename refs/heads/foo refs/heads/bar &&
|
||||
git reflog show refs/heads/bar >reflog &&
|
||||
test_grep "rename me" reflog &&
|
||||
test_must_fail git reflog exists refs/heads/foo
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename with message records reason in reflog' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
A=$(git rev-parse A) &&
|
||||
git refs update refs/heads/foo $A &&
|
||||
git refs rename --message="rename reason" refs/heads/foo refs/heads/bar &&
|
||||
git reflog show refs/heads/bar >actual &&
|
||||
test_grep "rename reason" actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename a nonexistent reference fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
test_must_fail git refs rename refs/heads/foo refs/heads/bar 2>err &&
|
||||
test_grep "reference does not exist" err
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename to an existing reference fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
A=$(git rev-parse A) &&
|
||||
B=$(git rev-parse B) &&
|
||||
git refs update refs/heads/foo $A &&
|
||||
git refs update refs/heads/bar $B &&
|
||||
test_must_fail git refs rename refs/heads/foo refs/heads/bar 2>err &&
|
||||
test_grep "reference already exists" err
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename with empty message fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
A=$(git rev-parse A) &&
|
||||
git refs update refs/heads/foo $A &&
|
||||
test_must_fail git refs rename --message= refs/heads/foo refs/heads/bar 2>err &&
|
||||
test_grep "empty message" err
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename with invalid old reference name fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
test_must_fail git refs rename "refs/heads/foo..bar" refs/heads/bar 2>err &&
|
||||
test_grep "invalid ref format" err
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename with invalid new reference name fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
(
|
||||
cd repo &&
|
||||
A=$(git rev-parse A) &&
|
||||
git refs update refs/heads/foo $A &&
|
||||
test_must_fail git refs rename refs/heads/foo "refs/heads/bar..baz" 2>err &&
|
||||
test_grep "invalid ref format" err
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'rename with too few arguments fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
test_must_fail git -C repo refs rename refs/heads/foo 2>err &&
|
||||
test_grep "requires old and new reference name" err
|
||||
'
|
||||
|
||||
test_expect_success 'rename with too many arguments fails' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
setup_repo repo &&
|
||||
test_must_fail git -C repo refs rename refs/heads/foo refs/heads/bar refs/heads/baz 2>err &&
|
||||
test_grep "requires old and new reference name" err
|
||||
'
|
||||
|
||||
test_done
|
||||
Loading…
Reference in New Issue