From 55c4a673070f40f2ef12d0be269e95f1df6825a9 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sat, 20 Aug 2011 14:49:48 -0700 Subject: Prevent force-updating of the current branch "git branch -M " allows updating the current branch which HEAD points, without the necessary house-keeping that git reset normally does to make this operation sensible. It also leaves the reflog in a confusing state (you would be warned when trying to read it). "git checkout -B " is also partly vulnerable to this bug; due to inconsistent pre-flight checks it would perform half of its task and then abort just before rewriting the branch. Again this manifested itself as the index file getting out-of-sync with HEAD. "git branch -f" already guarded against this problem, and aborts with a fatal error. Update "git branch -M", "git checkout -B" and "git branch -f" to share the same check before allowing a branch to be created. These prevent you from updating the current branch. We considered suggesting the use of "git reset" in the failure message but concluded that it was not possible to discern what the user was actually trying to do. Signed-off-by: Conrad Irwin Signed-off-by: Junio C Hamano --- branch.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'branch.c') diff --git a/branch.c b/branch.c index c0c865a4b1..ff84b5b9b7 100644 --- a/branch.c +++ b/branch.c @@ -135,6 +135,26 @@ static int setup_tracking(const char *new_ref, const char *orig_ref, return 0; } +int validate_new_branchname(const char *name, struct strbuf *ref, int force) +{ + const char *head; + unsigned char sha1[20]; + + if (strbuf_check_branch_ref(ref, name)) + die("'%s' is not a valid branch name.", name); + + if (!ref_exists(ref->buf)) + return 0; + else if (!force) + die("A branch named '%s' already exists.", name); + + head = resolve_ref("HEAD", sha1, 0, NULL); + if (!is_bare_repository() && head && !strcmp(head, ref->buf)) + die("Cannot force update the current branch."); + + return 1; +} + void create_branch(const char *head, const char *name, const char *start_name, int force, int reflog, enum branch_track track) @@ -151,17 +171,11 @@ void create_branch(const char *head, if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE) explicit_tracking = 1; - if (strbuf_check_branch_ref(&ref, name)) - die("'%s' is not a valid branch name.", name); - - if (resolve_ref(ref.buf, sha1, 1, NULL)) { - if (!force && track == BRANCH_TRACK_OVERRIDE) + if (validate_new_branchname(name, &ref, force || track == BRANCH_TRACK_OVERRIDE)) { + if (!force) dont_change_ref = 1; - else if (!force) - die("A branch named '%s' already exists.", name); - else if (!is_bare_repository() && head && !strcmp(head, name)) - die("Cannot force update the current branch."); - forcing = 1; + else + forcing = 1; } real_ref = NULL; -- cgit v1.2.3 From 587a9ee7da348f5e6696720d770d0e0da597827c Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sat, 20 Aug 2011 14:49:49 -0700 Subject: Show interpreted branch name in error messages Change the error message when doing: "git branch @{-1}", "git checkout -b @{-1}", or "git branch -m foo @{-1}" * was: A branch named '@{-1}' already exists. * now: A branch named 'bar' already exists. Signed-off-by: Conrad Irwin Signed-off-by: Junio C Hamano --- branch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'branch.c') diff --git a/branch.c b/branch.c index ff84b5b9b7..1fe3078a6c 100644 --- a/branch.c +++ b/branch.c @@ -146,7 +146,7 @@ int validate_new_branchname(const char *name, struct strbuf *ref, int force) if (!ref_exists(ref->buf)) return 0; else if (!force) - die("A branch named '%s' already exists.", name); + die("A branch named '%s' already exists.", ref->buf + strlen("refs/heads/")); head = resolve_ref("HEAD", sha1, 0, NULL); if (!is_bare_repository() && head && !strcmp(head, ref->buf)) -- cgit v1.2.3