Interesting. This is because "git checkout -b <name>" tries to make sure that "refs/heads/<name>" does not exist, and the way it does it to pass it to get_sha1() and make sure it fails. It almost always works, except when that string is passed from get_sha1() to get_describe_name(), which takes "ANYTHING-g<hexstring>" and as long as hexstring names an existing object, it says "Yup, I found one." I think the right fix is to make sure that "refs/heads/<name>" does not exist by checking exactly that. Perhaps something like this. I am not sure if we want to use the "yield non zero to signal not an error but an early return" trick like I did in this patch, though. --- builtin/checkout.c | 2 +- refs.c | 14 ++++++++++++++ refs.h | 1 + 3 files changed, 16 insertions(+), 1 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index 28cdc51..af1e7b5 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1071,7 +1071,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) if (strbuf_check_branch_ref(&buf, opts.new_branch)) die(_("git checkout: we do not like '%s' as a branch name."), opts.new_branch); - if (!get_sha1(buf.buf, rev)) { + if (ref_exists(buf.buf)) { opts.branch_exists = 1; if (!opts.new_branch_force) die(_("git checkout: branch %s already exists"), diff --git a/refs.c b/refs.c index e3c0511..138b1a0 100644 --- a/refs.c +++ b/refs.c @@ -1826,6 +1826,20 @@ int update_ref(const char *action, const char *refname, return 0; } +static int compare_ref_name(const char *refname, + const unsigned char *sha1, int flag, + void *cb_data) +{ + if (!strcmp(cb_data, refname)) + return -1; /* early return */ + return 0; +} + +int ref_exists(char *refname) +{ + return for_each_ref(compare_ref_name, refname) != 0; +} + struct ref *find_ref_by_name(const struct ref *list, const char *name) { for ( ; list; list = list->next) diff --git a/refs.h b/refs.h index 5e7a9a5..5839487 100644 --- a/refs.h +++ b/refs.h @@ -35,6 +35,7 @@ extern int for_each_ref_in_submodule(const char *submodule, const char *prefix, extern int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data); extern int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data); extern int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data); +extern int ref_exists(char *); static inline const char *has_glob_specials(const char *pattern) { -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html