status: show more info than "currently not on any branch"
When a remote ref or a tag is checked out, HEAD is automatically detached. There is no user-friendly way to find out what ref is checked out in this case. This patch digs in reflog for this information and shows "HEAD detached from origin/master" or "HEAD detached at v1.8.0" instead of "currently not on any branch". When it cannot figure out the original ref, it shows an abbreviated SHA-1. "Currently not on any branch" would never display (unless reflog is pruned to near empty that the last checkout entry is lost). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
3b691cccb0
commit
b397ea4863
@ -664,8 +664,10 @@ test_expect_success 'submodule add properly re-creates deeper level submodules'
|
||||
|
||||
test_expect_success 'submodule update properly revives a moved submodule' '
|
||||
(cd super &&
|
||||
H=$(git rev-parse --short HEAD) &&
|
||||
git commit -am "pre move" &&
|
||||
git status >expect&&
|
||||
H2=$(git rev-parse --short HEAD) &&
|
||||
git status | sed "s/$H/XXX/" >expect &&
|
||||
H=$(cd submodule2; git rev-parse HEAD) &&
|
||||
git rm --cached submodule2 &&
|
||||
rm -rf submodule2 &&
|
||||
@ -674,7 +676,7 @@ test_expect_success 'submodule update properly revives a moved submodule' '
|
||||
git config -f .gitmodules submodule.submodule2.path "moved/sub module"
|
||||
git commit -am "post move" &&
|
||||
git submodule update &&
|
||||
git status >actual &&
|
||||
git status | sed "s/$H2/XXX/" >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
@ -76,7 +76,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
|
||||
ONTO=$(git rev-parse --short HEAD^^) &&
|
||||
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached at $ONTO
|
||||
# You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
|
||||
# (fix conflicts and then run "git rebase --continue")
|
||||
# (use "git rebase --skip" to skip this patch)
|
||||
@ -103,7 +103,7 @@ test_expect_success 'status when rebase in progress before rebase --continue' '
|
||||
echo three >main.txt &&
|
||||
git add main.txt &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached at $ONTO
|
||||
# You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
|
||||
# (all conflicts fixed: run "git rebase --continue")
|
||||
#
|
||||
@ -135,7 +135,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
|
||||
ONTO=$(git rev-parse --short rebase_i_conflicts) &&
|
||||
test_must_fail git rebase -i rebase_i_conflicts &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached at $ONTO
|
||||
# You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
|
||||
# (fix conflicts and then run "git rebase --continue")
|
||||
# (use "git rebase --skip" to skip this patch)
|
||||
@ -161,7 +161,7 @@ test_expect_success 'status during rebase -i after resolving conflicts' '
|
||||
test_must_fail git rebase -i rebase_i_conflicts &&
|
||||
git add main.txt &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached at $ONTO
|
||||
# You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
|
||||
# (all conflicts fixed: run "git rebase --continue")
|
||||
#
|
||||
@ -187,9 +187,10 @@ test_expect_success 'status when rebasing -i in edit mode' '
|
||||
export FAKE_LINES &&
|
||||
test_when_finished "git rebase --abort" &&
|
||||
ONTO=$(git rev-parse --short HEAD~2) &&
|
||||
TGT=$(git rev-parse --short two_rebase_i) &&
|
||||
git rebase -i HEAD~2 &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $TGT
|
||||
# You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -214,8 +215,9 @@ test_expect_success 'status when splitting a commit' '
|
||||
ONTO=$(git rev-parse --short HEAD~3) &&
|
||||
git rebase -i HEAD~3 &&
|
||||
git reset HEAD^ &&
|
||||
TGT=$(git rev-parse --short HEAD) &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached at $TGT
|
||||
# You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''.
|
||||
# (Once your working directory is clean, run "git rebase --continue")
|
||||
#
|
||||
@ -243,10 +245,11 @@ test_expect_success 'status after editing the last commit with --amend during a
|
||||
export FAKE_LINES &&
|
||||
test_when_finished "git rebase --abort" &&
|
||||
ONTO=$(git rev-parse --short HEAD~3) &&
|
||||
TGT=$(git rev-parse --short three_amend) &&
|
||||
git rebase -i HEAD~3 &&
|
||||
git commit --amend -m "foo" &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $TGT
|
||||
# You are currently editing a commit while rebasing branch '\''amend_last'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -276,7 +279,7 @@ test_expect_success 'status: (continue first edit) second edit' '
|
||||
git rebase -i HEAD~3 &&
|
||||
git rebase --continue &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -298,7 +301,7 @@ test_expect_success 'status: (continue first edit) second edit and split' '
|
||||
git rebase --continue &&
|
||||
git reset HEAD^ &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (Once your working directory is clean, run "git rebase --continue")
|
||||
#
|
||||
@ -325,7 +328,7 @@ test_expect_success 'status: (continue first edit) second edit and amend' '
|
||||
git rebase --continue &&
|
||||
git commit --amend -m "foo" &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -347,7 +350,7 @@ test_expect_success 'status: (amend first edit) second edit' '
|
||||
git commit --amend -m "a" &&
|
||||
git rebase --continue &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -370,7 +373,7 @@ test_expect_success 'status: (amend first edit) second edit and split' '
|
||||
git rebase --continue &&
|
||||
git reset HEAD^ &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (Once your working directory is clean, run "git rebase --continue")
|
||||
#
|
||||
@ -398,7 +401,7 @@ test_expect_success 'status: (amend first edit) second edit and amend' '
|
||||
git rebase --continue &&
|
||||
git commit --amend -m "d" &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -422,7 +425,7 @@ test_expect_success 'status: (split first edit) second edit' '
|
||||
git commit -m "e" &&
|
||||
git rebase --continue &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -447,7 +450,7 @@ test_expect_success 'status: (split first edit) second edit and split' '
|
||||
git rebase --continue &&
|
||||
git reset HEAD^ &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (Once your working directory is clean, run "git rebase --continue")
|
||||
#
|
||||
@ -477,7 +480,7 @@ test_expect_success 'status: (split first edit) second edit and amend' '
|
||||
git rebase --continue &&
|
||||
git commit --amend -m "h" &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached from $ONTO
|
||||
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
|
||||
# (use "git commit --amend" to amend the current commit)
|
||||
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||
@ -572,8 +575,9 @@ test_expect_success 'status when bisecting' '
|
||||
git bisect start &&
|
||||
git bisect bad &&
|
||||
git bisect good one_bisect &&
|
||||
cat >expected <<-\EOF &&
|
||||
# Not currently on any branch.
|
||||
TGT=$(git rev-parse --short two_bisect) &&
|
||||
cat >expected <<-EOF &&
|
||||
# HEAD detached at $TGT
|
||||
# You are currently bisecting branch '\''bisect'\''.
|
||||
# (use "git bisect reset" to get back to the original branch)
|
||||
#
|
||||
@ -596,7 +600,7 @@ test_expect_success 'status when rebase conflicts with statushints disabled' '
|
||||
ONTO=$(git rev-parse --short HEAD^^) &&
|
||||
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
|
||||
cat >expected <<-EOF &&
|
||||
# Not currently on any branch.
|
||||
# HEAD detached at $ONTO
|
||||
# You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
|
||||
#
|
||||
# Unmerged paths:
|
||||
@ -662,5 +666,15 @@ test_expect_success 'status when cherry-picking after resolving conflicts' '
|
||||
test_i18ncmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'status showing detached from a tag' '
|
||||
test_commit atag tagging &&
|
||||
git checkout atag &&
|
||||
cat >expected <<-\EOF
|
||||
# HEAD detached at atag
|
||||
nothing to commit (use -u to show untracked files)
|
||||
EOF
|
||||
git status --untracked-files=no >actual &&
|
||||
test_i18ncmp expected actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
89
wt-status.c
89
wt-status.c
@ -999,7 +999,73 @@ got_nothing:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wt_status_get_state(struct wt_status_state *state)
|
||||
struct grab_1st_switch_cbdata {
|
||||
int found;
|
||||
struct strbuf buf;
|
||||
unsigned char nsha1[20];
|
||||
};
|
||||
|
||||
static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1,
|
||||
const char *email, unsigned long timestamp, int tz,
|
||||
const char *message, void *cb_data)
|
||||
{
|
||||
struct grab_1st_switch_cbdata *cb = cb_data;
|
||||
const char *target = NULL, *end;
|
||||
|
||||
if (prefixcmp(message, "checkout: moving from "))
|
||||
return 0;
|
||||
message += strlen("checkout: moving from ");
|
||||
target = strstr(message, " to ");
|
||||
if (!target)
|
||||
return 0;
|
||||
target += strlen(" to ");
|
||||
strbuf_reset(&cb->buf);
|
||||
hashcpy(cb->nsha1, nsha1);
|
||||
for (end = target; *end && *end != '\n'; end++)
|
||||
;
|
||||
strbuf_add(&cb->buf, target, end - target);
|
||||
cb->found = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void wt_status_get_detached_from(struct wt_status_state *state)
|
||||
{
|
||||
struct grab_1st_switch_cbdata cb;
|
||||
struct commit *commit;
|
||||
unsigned char sha1[20];
|
||||
char *ref = NULL;
|
||||
|
||||
strbuf_init(&cb.buf, 0);
|
||||
if (for_each_reflog_ent_reverse("HEAD", grab_1st_switch, &cb) <= 0) {
|
||||
strbuf_release(&cb.buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 &&
|
||||
/* sha1 is a commit? match without further lookup */
|
||||
(!hashcmp(cb.nsha1, sha1) ||
|
||||
/* perhaps sha1 is a tag, try to dereference to a commit */
|
||||
((commit = lookup_commit_reference_gently(sha1, 1)) != NULL &&
|
||||
!hashcmp(cb.nsha1, commit->object.sha1)))) {
|
||||
int ofs;
|
||||
if (!prefixcmp(ref, "refs/tags/"))
|
||||
ofs = strlen("refs/tags/");
|
||||
else if (!prefixcmp(ref, "refs/remotes/"))
|
||||
ofs = strlen("refs/remotes/");
|
||||
else
|
||||
ofs = 0;
|
||||
state->detached_from = xstrdup(ref + ofs);
|
||||
} else
|
||||
state->detached_from =
|
||||
xstrdup(find_unique_abbrev(cb.nsha1, DEFAULT_ABBREV));
|
||||
hashcpy(state->detached_sha1, cb.nsha1);
|
||||
|
||||
free(ref);
|
||||
strbuf_release(&cb.buf);
|
||||
}
|
||||
|
||||
void wt_status_get_state(struct wt_status_state *state,
|
||||
int get_detached_from)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
@ -1029,6 +1095,9 @@ void wt_status_get_state(struct wt_status_state *state)
|
||||
state->bisect_in_progress = 1;
|
||||
state->branch = read_and_strip_branch("BISECT_START");
|
||||
}
|
||||
|
||||
if (get_detached_from)
|
||||
wt_status_get_detached_from(state);
|
||||
}
|
||||
|
||||
static void wt_status_print_state(struct wt_status *s,
|
||||
@ -1054,7 +1123,8 @@ void wt_status_print(struct wt_status *s)
|
||||
struct wt_status_state state;
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
wt_status_get_state(&state);
|
||||
wt_status_get_state(&state,
|
||||
s->branch && !strcmp(s->branch, "HEAD"));
|
||||
|
||||
if (s->branch) {
|
||||
const char *on_what = _("On branch ");
|
||||
@ -1062,9 +1132,19 @@ void wt_status_print(struct wt_status *s)
|
||||
if (!prefixcmp(branch_name, "refs/heads/"))
|
||||
branch_name += 11;
|
||||
else if (!strcmp(branch_name, "HEAD")) {
|
||||
branch_name = "";
|
||||
branch_status_color = color(WT_STATUS_NOBRANCH, s);
|
||||
on_what = _("Not currently on any branch.");
|
||||
if (state.detached_from) {
|
||||
unsigned char sha1[20];
|
||||
branch_name = state.detached_from;
|
||||
if (!get_sha1("HEAD", sha1) &&
|
||||
!hashcmp(sha1, state.detached_sha1))
|
||||
on_what = _("HEAD detached at ");
|
||||
else
|
||||
on_what = _("HEAD detached from ");
|
||||
} else {
|
||||
branch_name = "";
|
||||
on_what = _("Not currently on any branch.");
|
||||
}
|
||||
}
|
||||
status_printf(s, color(WT_STATUS_HEADER, s), "");
|
||||
status_printf_more(s, branch_status_color, "%s", on_what);
|
||||
@ -1076,6 +1156,7 @@ void wt_status_print(struct wt_status *s)
|
||||
wt_status_print_state(s, &state);
|
||||
free(state.branch);
|
||||
free(state.onto);
|
||||
free(state.detached_from);
|
||||
|
||||
if (s->is_initial) {
|
||||
status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
|
||||
|
@ -81,12 +81,14 @@ struct wt_status_state {
|
||||
int bisect_in_progress;
|
||||
char *branch;
|
||||
char *onto;
|
||||
char *detached_from;
|
||||
unsigned char detached_sha1[20];
|
||||
};
|
||||
|
||||
void wt_status_prepare(struct wt_status *s);
|
||||
void wt_status_print(struct wt_status *s);
|
||||
void wt_status_collect(struct wt_status *s);
|
||||
void wt_status_get_state(struct wt_status_state *state);
|
||||
void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
|
||||
|
||||
void wt_shortstatus_print(struct wt_status *s);
|
||||
void wt_porcelain_print(struct wt_status *s);
|
||||
|
Loading…
Reference in New Issue
Block a user