@@ -878,7 +878,8 @@ static inline int push_mark(const char *string, int len)
}
static enum get_oid_result get_oid_1(struct repository *r, const char *name, int len, struct object_id *oid, unsigned lookup_flags);
-static int interpret_nth_prior_checkout(struct repository *r, const char *name, int namelen, struct strbuf *buf);
+static int interpret_nth_prior_checkout(struct repository *r, const char *name,
+ int namelen, struct strbuf *buf, struct object_id *ooid);
static int get_oid_basic(struct repository *r, const char *str, int len,
struct object_id *oid, unsigned int flags)
@@ -940,10 +941,12 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
if (nth_prior) {
struct strbuf buf = STRBUF_INIT;
+ struct object_id ooid;
int detached;
- if (interpret_nth_prior_checkout(r, str, len, &buf) > 0) {
- detached = (buf.len == r->hash_algo->hexsz && !get_oid_hex(buf.buf, oid));
+ if (interpret_nth_prior_checkout(r, str, len, &buf, &ooid) > 0) {
+ detached = (buf.len == r->hash_algo->hexsz &&
+ !get_oid_hex(buf.buf, oid)) && !oidcmp(oid, &ooid);
strbuf_release(&buf);
if (detached)
return 0;
@@ -1383,9 +1386,10 @@ static int get_oid_oneline(struct repository *r,
struct grab_nth_branch_switch_cbdata {
int remaining;
struct strbuf *sb;
+ struct object_id *ooid;
};
-static int grab_nth_branch_switch(struct object_id *ooid UNUSED,
+static int grab_nth_branch_switch(struct object_id *ooid,
struct object_id *noid UNUSED,
const char *email UNUSED,
timestamp_t timestamp UNUSED,
@@ -1405,6 +1409,8 @@ static int grab_nth_branch_switch(struct object_id *ooid UNUSED,
len = target - match;
strbuf_reset(cb->sb);
strbuf_add(cb->sb, match, len);
+ if (cb->ooid)
+ oidcpy(cb->ooid, ooid);
return 1; /* we are done */
}
return 0;
@@ -1416,7 +1422,8 @@ static int grab_nth_branch_switch(struct object_id *ooid UNUSED,
*/
static int interpret_nth_prior_checkout(struct repository *r,
const char *name, int namelen,
- struct strbuf *buf)
+ struct strbuf *buf,
+ struct object_id *ooid)
{
long nth;
int retval;
@@ -1438,6 +1445,7 @@ static int interpret_nth_prior_checkout(struct repository *r,
return -1;
cb.remaining = nth;
cb.sb = buf;
+ cb.ooid = ooid;
retval = refs_for_each_reflog_ent_reverse(get_main_ref_store(r),
"HEAD", grab_nth_branch_switch, &cb);
@@ -1621,7 +1629,7 @@ int repo_interpret_branch_name(struct repository *r,
namelen = strlen(name);
if (!options->allowed || (options->allowed & INTERPRET_BRANCH_LOCAL)) {
- len = interpret_nth_prior_checkout(r, name, namelen, buf);
+ len = interpret_nth_prior_checkout(r, name, namelen, buf, NULL);
if (!len) {
return len; /* syntax Ok, not enough switches */
} else if (len > 0) {
@@ -167,4 +167,14 @@ test_expect_success 'modify branch upstream via "@{-1}" and "@{-1}@{upstream}"'
test_must_fail git config branch.upstream-other.merge
'
+test_expect_success '@{-1} might look erroneously like a detached HEAD' '
+ oid=$(git rev-parse HEAD) &&
+ git checkout -b $oid &&
+ test_commit new-oid &&
+ git checkout - &&
+ git branch -D $oid &&
+ test_must_fail git checkout @{-1} &&
+ test_must_fail git rev-parse @{-1}
+'
+
test_done
We discourage the use of branch names that resemble commit ids; but for convenience not as a limitation: $ git commit --allow-empty -m first [... 000001] first $ oid=$(git rev-parse HEAD) $ git commit --allow-empty -m second [... 000002] second $ git checkout -b $oid Switched to a new branch '000001...' With this usage, removing that risky-named branch and trying to re-use the branch name again, the result expected is an error but: $ git checkout - $ git branch -d $oid Deleted branch 000001... (was 000002). $ git checkout $oid ... You are in 'detached HEAD' state... HEAD is now at 000001... With @{-1} shortcuts the result is the same, but here we can do better and give an error as a result: from the reflog we know @{-1} refers to a branch named '000001...' which pointed to commit '000002...'. Let's use this unused-yet information to avoid the ambiguity in the result. Signed-off-by: Rubén Justo <rjusto@gmail.com> --- object-name.c | 20 ++++++++++++++------ t/t3204-branch-name-interpretation.sh | 10 ++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-)