* [PATCH 0/5] nd/branch-show-rebase-bisect-state updates @ 2013-03-03 9:41 Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 1/5] checkout: record full target ref in reflog Nguyễn Thái Ngọc Duy ` (5 more replies) 0 siblings, 6 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy This round addresses the code sharing issue in the previous round and shows a bit more info in both git-status and git-branch. Now when you do "git checkout v1.8.0" or "git checkout origin/master", you should see that ref in status/branch output, in addition to detached HEAD status. Nguyễn Thái Ngọc Duy (5): checkout: record full target ref in reflog wt-status: split wt_status_state parsing function out wt-status: move wt_status_get_state() out to wt_status_print() status: show the ref that is checked out, even if it's detached branch: show more information when HEAD is detached builtin/branch.c | 25 +++++++- builtin/checkout.c | 19 +++++- t/t6030-bisect-porcelain.sh | 2 +- wt-status.c | 139 ++++++++++++++++++++++++++++++++++---------- wt-status.h | 6 +- 5 files changed, 152 insertions(+), 39 deletions(-) -- 1.8.1.2.536.gf441e6d ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/5] checkout: record full target ref in reflog 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 ` Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 2/5] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy ` (4 subsequent siblings) 5 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy This simplifies parsing later on because the parser does not need to do dwim on the target (and later dwim may be ambiguous if new refs are added). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- builtin/checkout.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index a9c1b5a..b11bd31 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -398,6 +398,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, struct branch_info { const char *name; /* The short name used */ + const char *full_ref; /* The full name of a real ref */ const char *path; /* The full name of a real branch */ struct commit *commit; /* The named commit */ }; @@ -589,7 +590,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts, if (!old_desc && old->commit) old_desc = sha1_to_hex(old->commit->object.sha1); strbuf_addf(&msg, "checkout: moving from %s to %s", - old_desc ? old_desc : "(invalid)", new->name); + old_desc ? old_desc : "(invalid)", + new->full_ref ? new->full_ref : new->name); if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) { /* Nothing to do. */ @@ -907,10 +909,21 @@ static int parse_branchname_arg(int argc, const char **argv, setup_branch_path(new); if (!check_refname_format(new->path, 0) && - !read_ref(new->path, branch_rev)) + !read_ref(new->path, branch_rev)) { hashcpy(rev, branch_rev); - else + new->full_ref = xstrdup(new->path); + } else { + char *real_ref = NULL; + unsigned char sha1[20]; new->path = NULL; /* not an existing branch */ + if (dwim_ref(new->name, strlen(new->name), sha1, + &real_ref) == 1 && + !hashcmp(sha1, rev)) { + new->full_ref = real_ref; + real_ref = NULL; + } + free(real_ref); + } new->commit = lookup_commit_reference_gently(rev, 1); if (!new->commit) { -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 2/5] wt-status: split wt_status_state parsing function out 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 1/5] checkout: record full target ref in reflog Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 ` Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 3/5] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy ` (3 subsequent siblings) 5 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 52 +++++++++++++++++++++++++++++++--------------------- wt-status.h | 5 +++-- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/wt-status.c b/wt-status.c index ef405d0..183aafe 100644 --- a/wt-status.c +++ b/wt-status.c @@ -970,7 +970,7 @@ static void show_bisect_in_progress(struct wt_status *s, * Extract branch information from rebase/bisect */ static void read_and_strip_branch(struct strbuf *sb, - const char **branch, + char **branch, const char *path) { unsigned char sha1[20]; @@ -994,52 +994,62 @@ static void read_and_strip_branch(struct strbuf *sb, strbuf_addstr(sb, abbrev); *branch = sb->buf; } else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ - ; + *branch = NULL; else /* bisect */ *branch = sb->buf; + if (*branch) + *branch = xstrdup(*branch); } -static void wt_status_print_state(struct wt_status *s) +void wt_status_get_state(struct wt_status_state *state) { - const char *state_color = color(WT_STATUS_HEADER, s); struct strbuf branch = STRBUF_INIT; struct strbuf onto = STRBUF_INIT; - struct wt_status_state state; struct stat st; - memset(&state, 0, sizeof(state)); + memset(state, 0, sizeof(*state)); if (!stat(git_path("MERGE_HEAD"), &st)) { - state.merge_in_progress = 1; + state->merge_in_progress = 1; } else if (!stat(git_path("rebase-apply"), &st)) { if (!stat(git_path("rebase-apply/applying"), &st)) { - state.am_in_progress = 1; + state->am_in_progress = 1; if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size) - state.am_empty_patch = 1; + state->am_empty_patch = 1; } else { - state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, + state->rebase_in_progress = 1; + read_and_strip_branch(&branch, &state->branch, "rebase-apply/head-name"); - read_and_strip_branch(&onto, &state.onto, + read_and_strip_branch(&onto, &state->onto, "rebase-apply/onto"); } } else if (!stat(git_path("rebase-merge"), &st)) { if (!stat(git_path("rebase-merge/interactive"), &st)) - state.rebase_interactive_in_progress = 1; + state->rebase_interactive_in_progress = 1; else - state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, + state->rebase_in_progress = 1; + read_and_strip_branch(&branch, &state->branch, "rebase-merge/head-name"); - read_and_strip_branch(&onto, &state.onto, + read_and_strip_branch(&onto, &state->onto, "rebase-merge/onto"); } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { - state.cherry_pick_in_progress = 1; + state->cherry_pick_in_progress = 1; } if (!stat(git_path("BISECT_LOG"), &st)) { - state.bisect_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, + state->bisect_in_progress = 1; + read_and_strip_branch(&branch, &state->branch, "BISECT_START"); } + strbuf_release(&branch); + strbuf_release(&onto); +} + +static void wt_status_print_state(struct wt_status *s) +{ + const char *state_color = color(WT_STATUS_HEADER, s); + struct wt_status_state state; + + wt_status_get_state(&state); if (state.merge_in_progress) show_merge_in_progress(s, &state, state_color); @@ -1051,8 +1061,8 @@ static void wt_status_print_state(struct wt_status *s) show_cherry_pick_in_progress(s, &state, state_color); if (state.bisect_in_progress) show_bisect_in_progress(s, &state, state_color); - strbuf_release(&branch); - strbuf_release(&onto); + free(state.branch); + free(state.onto); } void wt_status_print(struct wt_status *s) diff --git a/wt-status.h b/wt-status.h index 81e1dcf..5ddcbf6 100644 --- a/wt-status.h +++ b/wt-status.h @@ -79,13 +79,14 @@ struct wt_status_state { int rebase_interactive_in_progress; int cherry_pick_in_progress; int bisect_in_progress; - const char *branch; - const char *onto; + char *branch; + char *onto; }; 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_shortstatus_print(struct wt_status *s); void wt_porcelain_print(struct wt_status *s); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 3/5] wt-status: move wt_status_get_state() out to wt_status_print() 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 1/5] checkout: record full target ref in reflog Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 2/5] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 ` Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 4/5] status: show the ref that is checked out, even if it's detached Nguyễn Thái Ngọc Duy ` (2 subsequent siblings) 5 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/wt-status.c b/wt-status.c index 183aafe..6a3566b 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1044,31 +1044,29 @@ void wt_status_get_state(struct wt_status_state *state) strbuf_release(&onto); } -static void wt_status_print_state(struct wt_status *s) +static void wt_status_print_state(struct wt_status *s, + struct wt_status_state *state) { const char *state_color = color(WT_STATUS_HEADER, s); - struct wt_status_state state; - - wt_status_get_state(&state); - - if (state.merge_in_progress) - show_merge_in_progress(s, &state, state_color); - else if (state.am_in_progress) - show_am_in_progress(s, &state, state_color); - else if (state.rebase_in_progress || state.rebase_interactive_in_progress) - show_rebase_in_progress(s, &state, state_color); - else if (state.cherry_pick_in_progress) - show_cherry_pick_in_progress(s, &state, state_color); - if (state.bisect_in_progress) - show_bisect_in_progress(s, &state, state_color); - free(state.branch); - free(state.onto); + if (state->merge_in_progress) + show_merge_in_progress(s, state, state_color); + else if (state->am_in_progress) + show_am_in_progress(s, state, state_color); + else if (state->rebase_in_progress || state->rebase_interactive_in_progress) + show_rebase_in_progress(s, state, state_color); + else if (state->cherry_pick_in_progress) + show_cherry_pick_in_progress(s, state, state_color); + if (state->bisect_in_progress) + show_bisect_in_progress(s, state, state_color); } void wt_status_print(struct wt_status *s) { const char *branch_color = color(WT_STATUS_ONBRANCH, s); const char *branch_status_color = color(WT_STATUS_HEADER, s); + struct wt_status_state state; + + wt_status_get_state(&state); if (s->branch) { const char *on_what = _("On branch "); @@ -1087,7 +1085,10 @@ void wt_status_print(struct wt_status *s) wt_status_print_tracking(s); } - wt_status_print_state(s); + wt_status_print_state(s, &state); + free(state.branch); + free(state.onto); + if (s->is_initial) { status_printf_ln(s, color(WT_STATUS_HEADER, s), ""); status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit")); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 4/5] status: show the ref that is checked out, even if it's detached 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (2 preceding siblings ...) 2013-03-03 9:41 ` [PATCH 3/5] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 ` Nguyễn Thái Ngọc Duy 2013-03-03 22:25 ` Junio C Hamano 2013-03-03 9:41 ` [PATCH 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 5 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy 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 "Detached from origin/master" or "Detached from v1.8.0" instead of "Currently not on any branch". Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- wt-status.h | 3 ++- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/wt-status.c b/wt-status.c index 6a3566b..4b6421a 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1001,7 +1001,60 @@ static void read_and_strip_branch(struct strbuf *sb, *branch = xstrdup(*branch); } -void wt_status_get_state(struct wt_status_state *state) +struct grab_1st_switch_cbdata { + struct strbuf buf; + unsigned char sha1[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; + + 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->sha1, nsha1); + if (!prefixcmp(target, "refs/")) { + const char *end = target; + while (*end && *end != '\n') + end++; + strbuf_add(&cb->buf, target, end - target); + } + return 0; +} + +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]; + + strbuf_init(&cb.buf, 0); + for_each_recent_reflog_ent("HEAD", grab_1st_switch, 40960, &cb); + if (cb.buf.len && + !read_ref(cb.buf.buf, sha1) && + (commit = lookup_commit_reference_gently(sha1, 1)) != NULL && + !hashcmp(cb.sha1, commit->object.sha1)) { + int ofs = 0; + if (!prefixcmp(cb.buf.buf, "refs/tags/")) + ofs = strlen("refs/tags/"); + else if (!prefixcmp(cb.buf.buf, "refs/remotes/")) + ofs = strlen("refs/remotes/"); + state->detached_from = xstrdup(cb.buf.buf + ofs); + } + strbuf_release(&cb.buf); +} + +void wt_status_get_state(struct wt_status_state *state, + int get_detached_from) { struct strbuf branch = STRBUF_INIT; struct strbuf onto = STRBUF_INIT; @@ -1040,6 +1093,10 @@ void wt_status_get_state(struct wt_status_state *state) read_and_strip_branch(&branch, &state->branch, "BISECT_START"); } + + if (get_detached_from) + wt_status_get_detached_from(state); + strbuf_release(&branch); strbuf_release(&onto); } @@ -1066,7 +1123,8 @@ void wt_status_print(struct wt_status *s) const char *branch_status_color = color(WT_STATUS_HEADER, s); struct wt_status_state 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 "); @@ -1074,9 +1132,14 @@ 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) { + branch_name = state.detached_from; + on_what = _("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); @@ -1088,6 +1151,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), ""); diff --git a/wt-status.h b/wt-status.h index 5ddcbf6..74c9055 100644 --- a/wt-status.h +++ b/wt-status.h @@ -81,12 +81,13 @@ struct wt_status_state { int bisect_in_progress; char *branch; char *onto; + char *detached_from; }; 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); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 4/5] status: show the ref that is checked out, even if it's detached 2013-03-03 9:41 ` [PATCH 4/5] status: show the ref that is checked out, even if it's detached Nguyễn Thái Ngọc Duy @ 2013-03-03 22:25 ` Junio C Hamano 2013-03-04 12:17 ` Duy Nguyen 2013-03-05 11:39 ` Duy Nguyen 0 siblings, 2 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-03 22:25 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier > 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 "Detached from origin/master" or "Detached from > v1.8.0" instead of "Currently not on any branch". "Detached from" is a nice attempt to compromise in the phrasing. We usually say you detach HEAD at v1.8.0, but what is shown is what started from such a state but then the user may have built more history on top of it and may no longer be at v1.8.0, so obviously we do not want to say "Detached at". We are in a "detached at v1.8.0 and then possibly built one or more commits on top" state (would it be helpful to differentiate the "nothing built on top" and "some commits have been built on top" cases, I wonder). Also I wonder if you could do a bit more to help the users who do: $ git checkout $(git merge-base HEAD nd/branch-show-rebase-bisect-state) aka $ git checkout ...nd/branch-show-rebase-bisect-state and then do one or more commits on top. Instead of punting to "Currently not on any branch", would it help to show the place you first detached at, so that the user can then grab that commit object name and run $ git log --oneline $that_commit.. or something? > +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; > + > + 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->sha1, nsha1); > + if (!prefixcmp(target, "refs/")) { > + const char *end = target; > + while (*end && *end != '\n') > + end++; > + strbuf_add(&cb->buf, target, end - target); > + } > + return 0; > +} Can't this be done by generalizing grab_nth_branch_switch() and then exposing it as part of the general API? I also feel uneasy about two issues this and the previous change introduces: 1) It is somewhat unnerving that this step reads what comes after "to", while nth_branch_switch() reads what comes between "from" and "to", but it probably cannot be avoided because this series wants to know what we switched "to" earlier, while "checkout -" wants to know what we switched "from" 2) The previous one records this sequence in a funny way: : start from branch A git checkout B git checkout C The resulting reflog entries result in checkout: moving from A to refs/heads/B checkout: moving from B to refs/heads/C even though existing code and tools are expecting to read checkout: moving from A to B checkout: moving from B to C By the way, even though the title of this patch is "status: show the ref that is checked out, even if it's detached", a quick check with $ cd ../linux-3.0 $ git describe v3.8-rc7 $ ../git.git/git-checkout v3.8-rc7 $ tail -n 1 .git/logs/HEAD | sed -e 's/.*checkout/checkout/' checkout: moving from master to refs/tags/v3.8-rc7 $ ../git.git/git-status | head -n 1 # Not currently on any branch. $ ../git.git/git-branch -v * (no branch) 836dc9e Linux 3.8-rc7 master 836dc9e Linux 3.8-rc7 does not seem to give me anything more helpful. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 4/5] status: show the ref that is checked out, even if it's detached 2013-03-03 22:25 ` Junio C Hamano @ 2013-03-04 12:17 ` Duy Nguyen 2013-03-04 15:49 ` Junio C Hamano 2013-03-05 11:39 ` Duy Nguyen 1 sibling, 1 reply; 38+ messages in thread From: Duy Nguyen @ 2013-03-04 12:17 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Matthieu Moy, Jonathan Niedier On Mon, Mar 4, 2013 at 5:25 AM, Junio C Hamano <gitster@pobox.com> wrote: >> 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 "Detached from origin/master" or "Detached from >> v1.8.0" instead of "Currently not on any branch". > > "Detached from" is a nice attempt to compromise in the phrasing. > > We usually say you detach HEAD at v1.8.0, but what is shown is what > started from such a state but then the user may have built more > history on top of it and may no longer be at v1.8.0, so obviously we > do not want to say "Detached at". We are in a "detached at v1.8.0 > and then possibly built one or more commits on top" state (would it > be helpful to differentiate the "nothing built on top" and "some > commits have been built on top" cases, I wonder). Hmm.. never thought of that subtlety. Differentiating should be possible. I'm just not sure if it would be helpful. Comments people, do or not do? > Also I wonder if you could do a bit more to help the users who do: > > $ git checkout $(git merge-base HEAD nd/branch-show-rebase-bisect-state) > > aka > > $ git checkout ...nd/branch-show-rebase-bisect-state > > and then do one or more commits on top. > > Instead of punting to "Currently not on any branch", would it help > to show the place you first detached at, so that the user can then > grab that commit object name and run > > $ git log --oneline $that_commit.. > > or something? $that_commit would be HEAD@{-1} right? Should that be used instead of grabbing random SHA-1 shown in git-status? >> +static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1, > > Can't this be done by generalizing grab_nth_branch_switch() and then > exposing it as part of the general API? We could share the code, yes. Initially I wanted something that resolves "@{-1}" and gives me the reflog entry. Maybe we could add a function to do that. > I also feel uneasy about two issues this and the previous change I assume "previous change" is 1/5, reflog format change. > 2) The previous one records this sequence in a funny way: > > : start from branch A > git checkout B > git checkout C > > The resulting reflog entries result in > > checkout: moving from A to refs/heads/B > checkout: moving from B to refs/heads/C > > even though existing code and tools are expecting to read > > checkout: moving from A to B > checkout: moving from B to C It does not record exactly user input, but the "to" part is basically extended sha-1 and I don't think current tools parse them manually. Instead just they should just pass them to git-rev-parse to do the job. So this change is not really bad. But again the recent '!' incident in attr.c shows that I know nothing about real world usage. We could do dwim when parsing the reflog, which introduces no changes in reflog format. > By the way, even though the title of this patch is "status: show the > ref that is checked out, even if it's detached", a quick check with > > $ cd ../linux-3.0 > $ git describe > v3.8-rc7 > $ ../git.git/git-checkout v3.8-rc7 > $ tail -n 1 .git/logs/HEAD | sed -e 's/.*checkout/checkout/' > checkout: moving from master to refs/tags/v3.8-rc7 > $ ../git.git/git-status | head -n 1 > # Not currently on any branch. > $ ../git.git/git-branch -v > * (no branch) 836dc9e Linux 3.8-rc7 > master 836dc9e Linux 3.8-rc7 > > does not seem to give me anything more helpful. Yeah. I blame myself for copying from interpret_nth_prior_checkout() without full understanding, and git's poor documentation (there's no description about for_each_recent_reflog_ent, and that the caller is supposed to call for_each_reflog_ent in some case; but I think this convention is unintuitive, for_each_recent_reflog_ent should do that itself) -- Duy ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 4/5] status: show the ref that is checked out, even if it's detached 2013-03-04 12:17 ` Duy Nguyen @ 2013-03-04 15:49 ` Junio C Hamano 0 siblings, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-04 15:49 UTC (permalink / raw) To: Duy Nguyen; +Cc: git, Matthieu Moy, Jonathan Niedier Duy Nguyen <pclouds@gmail.com> writes: >> Instead of punting to "Currently not on any branch", would it help >> to show the place you first detached at, so that the user can then >> grab that commit object name and run >> >> $ git log --oneline $that_commit.. >> >> or something? > > $that_commit would be HEAD@{-1} right? Should that be used instead of > grabbing random SHA-1 shown in git-status? You can say "git checkout @{-1}" to go back. That is the commit you came _from_. But I think what you were computing for $that_commit was different. It's "the ref that is checked out, even if it's detached". After doing: : start from anywhere git checkout master ;# on master git checkout branch~4 ;# detach at that commit ... hack hack hack ... git commit; git commit your @{-1} is 'master'; "the ref that is checked out, even if its' detached" is 'branch~4', and that is what you want as $that_commit in the example. That shows your _progress_, which has no relation with 'master' that is @{-1}. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 4/5] status: show the ref that is checked out, even if it's detached 2013-03-03 22:25 ` Junio C Hamano 2013-03-04 12:17 ` Duy Nguyen @ 2013-03-05 11:39 ` Duy Nguyen 2013-03-05 12:18 ` Matthieu Moy 1 sibling, 1 reply; 38+ messages in thread From: Duy Nguyen @ 2013-03-05 11:39 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Matthieu Moy, Jonathan Niedier OK new try. This - no longer requires 1/5 (i'll resend full series later when the wanted behavior is found) - shows either "detached from" or "detached at". We could even do "4 commits from detached point XXX", like we do "5 commits ahead of upstream". But I'm not sure if we should do that. - otherwise shows "detached from <sha1>". IOW "currently not on any branch" is no longer shown. - fixes the case when reflog is too short and for_each_recent_reflog_ent returns false. I did not merge grab_1st_switch and grab_nth_branch_switch because they use different part of the reflog and merging seems to make it more complicated than necessary. -- 8< -- Subject: [PATCH] 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 "Detached from/at origin/master" or "Detached from/at v1.8.0". When it cannot figure out the original ref, it shows an abbreviated SHA-1 instead. "Currently not on any branch" would never display. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- t/t7406-submodule-update.sh | 6 ++-- t/t7512-status-help.sh | 52 +++++++++++++++++---------- wt-status.c | 87 ++++++++++++++++++++++++++++++++++++++++++--- wt-status.h | 4 ++- 4 files changed, 123 insertions(+), 26 deletions(-) diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 4975ec0..50ac020 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -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 ) ' diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index d2da89a..c4f030f 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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. + # 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 && + # 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. + # 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 + # 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 diff --git a/wt-status.c b/wt-status.c index 6a3566b..7ad3c2b 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1001,7 +1001,70 @@ static void read_and_strip_branch(struct strbuf *sb, *branch = xstrdup(*branch); } -void wt_status_get_state(struct wt_status_state *state) +struct grab_1st_switch_cbdata { + 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); + return 0; +} + +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_recent_reflog_ent("HEAD", grab_1st_switch, 4096, &cb)) + for_each_reflog_ent("HEAD", grab_1st_switch, &cb); + if (!cb.buf.len) + return; + + if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 && + (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); + hashcpy(state->detached_sha1, sha1); + } else if (!get_sha1(cb.buf.buf, sha1)) { + state->detached_from = + xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); + hashcpy(state->detached_sha1, sha1); + } + + free(ref); + strbuf_release(&cb.buf); +} + +void wt_status_get_state(struct wt_status_state *state, + int get_detached_from) { struct strbuf branch = STRBUF_INIT; struct strbuf onto = STRBUF_INIT; @@ -1040,6 +1103,10 @@ void wt_status_get_state(struct wt_status_state *state) read_and_strip_branch(&branch, &state->branch, "BISECT_START"); } + + if (get_detached_from) + wt_status_get_detached_from(state); + strbuf_release(&branch); strbuf_release(&onto); } @@ -1066,7 +1133,8 @@ void wt_status_print(struct wt_status *s) const char *branch_status_color = color(WT_STATUS_HEADER, s); struct wt_status_state 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 "); @@ -1074,9 +1142,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 = _("Detached at "); + else + on_what = _("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); @@ -1088,6 +1166,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), ""); diff --git a/wt-status.h b/wt-status.h index 5ddcbf6..5cb7df9 100644 --- a/wt-status.h +++ b/wt-status.h @@ -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); -- 8< -- ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 4/5] status: show the ref that is checked out, even if it's detached 2013-03-05 11:39 ` Duy Nguyen @ 2013-03-05 12:18 ` Matthieu Moy 0 siblings, 0 replies; 38+ messages in thread From: Matthieu Moy @ 2013-03-05 12:18 UTC (permalink / raw) To: Duy Nguyen; +Cc: Junio C Hamano, git, Jonathan Niedier Duy Nguyen <pclouds@gmail.com> writes: > - # Not currently on any branch. > + # Detached at $ONTO Without the context, I don't think "Detached" alone says something to the user. "Detached HEAD at ..." would IMHO be clearer and at least give the user enough keywords to search the web/doc for an explanation. Actually, in the case of "Detached HEAD at $branch", you may even add an advice saying something like: (run "git checkout $branch" to switch to branch $branch) or so. But that's not the common case, so maybe it's not that useful. -- Matthieu Moy http://www-verimag.imag.fr/~moy/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 5/5] branch: show more information when HEAD is detached 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (3 preceding siblings ...) 2013-03-03 9:41 ` [PATCH 4/5] status: show the ref that is checked out, even if it's detached Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 ` Nguyễn Thái Ngọc Duy 2013-03-03 22:28 ` Junio C Hamano 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 5 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-03 9:41 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy This prints more helpful info when HEAD is detached: is it detached because of bisect or rebase? What is the original branch name in those cases? Is it detached because the user checks out a remote ref or a tag (and which one)? Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- builtin/branch.c | 25 ++++++++++++++++++++++++- t/t6030-bisect-porcelain.sh | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 6371bf9..02dee0d 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -18,6 +18,7 @@ #include "string-list.h" #include "column.h" #include "utf8.h" +#include "wt-status.h" static const char * const builtin_branch_usage[] = { N_("git branch [options] [-r | -a] [--merged | --no-merged]"), @@ -550,6 +551,28 @@ static int calc_maxwidth(struct ref_list *refs) return w; } +static char *get_head_description() +{ + struct strbuf desc = STRBUF_INIT; + struct wt_status_state state; + wt_status_get_state(&state, 1); + if (state.rebase_in_progress || + state.rebase_interactive_in_progress) + strbuf_addf(&desc, _("(no branch, rebasing %s)"), + state.branch); + else if (state.bisect_in_progress) + strbuf_addf(&desc, _("(no branch, bisecting %s)"), + state.branch); + else if (state.detached_from) + strbuf_addf(&desc, _("(detached from %s)"), + state.detached_from); + else + strbuf_addstr(&desc, _("(no branch)")); + free(state.branch); + free(state.onto); + free(state.detached_from); + return strbuf_detach(&desc, NULL); +} static void show_detached(struct ref_list *ref_list) { @@ -557,7 +580,7 @@ static void show_detached(struct ref_list *ref_list) if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; - item.name = xstrdup(_("(no branch)")); + item.name = get_head_description(); item.width = utf8_strwidth(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 3e0e15f..9b6f0d0 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - test_i18ngrep "* (no branch)" branch.output > /dev/null && + test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null && test_cmp saved .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 5/5] branch: show more information when HEAD is detached 2013-03-03 9:41 ` [PATCH 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy @ 2013-03-03 22:28 ` Junio C Hamano 0 siblings, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-03 22:28 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > This prints more helpful info when HEAD is detached: is it detached > because of bisect or rebase? What is the original branch name in those > cases? Is it detached because the user checks out a remote ref or a > tag (and which one)? > > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> > --- > builtin/branch.c | 25 ++++++++++++++++++++++++- > t/t6030-bisect-porcelain.sh | 2 +- > 2 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/builtin/branch.c b/builtin/branch.c > index 6371bf9..02dee0d 100644 > --- a/builtin/branch.c > +++ b/builtin/branch.c > @@ -18,6 +18,7 @@ > #include "string-list.h" > #include "column.h" > #include "utf8.h" > +#include "wt-status.h" > > static const char * const builtin_branch_usage[] = { > N_("git branch [options] [-r | -a] [--merged | --no-merged]"), > @@ -550,6 +551,28 @@ static int calc_maxwidth(struct ref_list *refs) > return w; > } > > +static char *get_head_description() s/()/(void)/; I think the series is much easier to read than the previous round (except for some nits, which I'll send separately). We would want to add tests to protect the "where did we detach from" feature done by [PATCH 4/5], which does not seem to have any. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (4 preceding siblings ...) 2013-03-03 9:41 ` [PATCH 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 ` Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 1/4] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy ` (4 more replies) 5 siblings, 5 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy Since the previous round: - reflog format change is dropped - almost always show "HEAD detached from/at xxx" instead of "currently not on any branch", where "xxx" is either a ref, or an abbreviated sha-1 I wanted to introduce something like @{-1:to} that resolves the "to" sha-1 in reflog, in addition to @{-1} which resolves the "from" part. But the syntax looks ugly so I dropped it. Meanwhile people could do git log -1 -g --grep-reflog checkout --pretty=format:%h to retrieve the same info. Nguyễn Thái Ngọc Duy (4): wt-status: split wt_status_state parsing function out wt-status: move wt_status_get_state() out to wt_status_print() status: show more info than "currently not on any branch" branch: show more information when HEAD is detached builtin/branch.c | 25 +++++++- t/t3203-branch-output.sh | 6 +- t/t6030-bisect-porcelain.sh | 2 +- t/t7406-submodule-update.sh | 6 +- t/t7512-status-help.sh | 52 +++++++++------ wt-status.c | 152 ++++++++++++++++++++++++++++++++++---------- wt-status.h | 7 +- 7 files changed, 190 insertions(+), 60 deletions(-) -- 1.8.1.2.536.gf441e6d ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 1/4] wt-status: split wt_status_state parsing function out 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 ` Nguyễn Thái Ngọc Duy 2013-03-06 18:48 ` Junio C Hamano 2013-03-06 12:21 ` [PATCH v2 2/4] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy ` (3 subsequent siblings) 4 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 52 +++++++++++++++++++++++++++++++--------------------- wt-status.h | 5 +++-- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/wt-status.c b/wt-status.c index ef405d0..183aafe 100644 --- a/wt-status.c +++ b/wt-status.c @@ -970,7 +970,7 @@ static void show_bisect_in_progress(struct wt_status *s, * Extract branch information from rebase/bisect */ static void read_and_strip_branch(struct strbuf *sb, - const char **branch, + char **branch, const char *path) { unsigned char sha1[20]; @@ -994,52 +994,62 @@ static void read_and_strip_branch(struct strbuf *sb, strbuf_addstr(sb, abbrev); *branch = sb->buf; } else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ - ; + *branch = NULL; else /* bisect */ *branch = sb->buf; + if (*branch) + *branch = xstrdup(*branch); } -static void wt_status_print_state(struct wt_status *s) +void wt_status_get_state(struct wt_status_state *state) { - const char *state_color = color(WT_STATUS_HEADER, s); struct strbuf branch = STRBUF_INIT; struct strbuf onto = STRBUF_INIT; - struct wt_status_state state; struct stat st; - memset(&state, 0, sizeof(state)); + memset(state, 0, sizeof(*state)); if (!stat(git_path("MERGE_HEAD"), &st)) { - state.merge_in_progress = 1; + state->merge_in_progress = 1; } else if (!stat(git_path("rebase-apply"), &st)) { if (!stat(git_path("rebase-apply/applying"), &st)) { - state.am_in_progress = 1; + state->am_in_progress = 1; if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size) - state.am_empty_patch = 1; + state->am_empty_patch = 1; } else { - state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, + state->rebase_in_progress = 1; + read_and_strip_branch(&branch, &state->branch, "rebase-apply/head-name"); - read_and_strip_branch(&onto, &state.onto, + read_and_strip_branch(&onto, &state->onto, "rebase-apply/onto"); } } else if (!stat(git_path("rebase-merge"), &st)) { if (!stat(git_path("rebase-merge/interactive"), &st)) - state.rebase_interactive_in_progress = 1; + state->rebase_interactive_in_progress = 1; else - state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, + state->rebase_in_progress = 1; + read_and_strip_branch(&branch, &state->branch, "rebase-merge/head-name"); - read_and_strip_branch(&onto, &state.onto, + read_and_strip_branch(&onto, &state->onto, "rebase-merge/onto"); } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { - state.cherry_pick_in_progress = 1; + state->cherry_pick_in_progress = 1; } if (!stat(git_path("BISECT_LOG"), &st)) { - state.bisect_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, + state->bisect_in_progress = 1; + read_and_strip_branch(&branch, &state->branch, "BISECT_START"); } + strbuf_release(&branch); + strbuf_release(&onto); +} + +static void wt_status_print_state(struct wt_status *s) +{ + const char *state_color = color(WT_STATUS_HEADER, s); + struct wt_status_state state; + + wt_status_get_state(&state); if (state.merge_in_progress) show_merge_in_progress(s, &state, state_color); @@ -1051,8 +1061,8 @@ static void wt_status_print_state(struct wt_status *s) show_cherry_pick_in_progress(s, &state, state_color); if (state.bisect_in_progress) show_bisect_in_progress(s, &state, state_color); - strbuf_release(&branch); - strbuf_release(&onto); + free(state.branch); + free(state.onto); } void wt_status_print(struct wt_status *s) diff --git a/wt-status.h b/wt-status.h index 81e1dcf..5ddcbf6 100644 --- a/wt-status.h +++ b/wt-status.h @@ -79,13 +79,14 @@ struct wt_status_state { int rebase_interactive_in_progress; int cherry_pick_in_progress; int bisect_in_progress; - const char *branch; - const char *onto; + char *branch; + char *onto; }; 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_shortstatus_print(struct wt_status *s); void wt_porcelain_print(struct wt_status *s); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] wt-status: split wt_status_state parsing function out 2013-03-06 12:21 ` [PATCH v2 1/4] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy @ 2013-03-06 18:48 ` Junio C Hamano 2013-03-06 23:53 ` Junio C Hamano 0 siblings, 1 reply; 38+ messages in thread From: Junio C Hamano @ 2013-03-06 18:48 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> > --- > wt-status.c | 52 +++++++++++++++++++++++++++++++--------------------- > wt-status.h | 5 +++-- > 2 files changed, 34 insertions(+), 23 deletions(-) > > diff --git a/wt-status.c b/wt-status.c > index ef405d0..183aafe 100644 > --- a/wt-status.c > +++ b/wt-status.c > @@ -970,7 +970,7 @@ static void show_bisect_in_progress(struct wt_status *s, > * Extract branch information from rebase/bisect > */ > static void read_and_strip_branch(struct strbuf *sb, > - const char **branch, > + char **branch, > const char *path) > { > unsigned char sha1[20]; > @@ -994,52 +994,62 @@ static void read_and_strip_branch(struct strbuf *sb, > strbuf_addstr(sb, abbrev); > *branch = sb->buf; > } else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ > - ; > + *branch = NULL; > else /* bisect */ > *branch = sb->buf; > + if (*branch) > + *branch = xstrdup(*branch); > } The reason why the original print_state() kept two strbufs in it was because its use of the return value (in *branch) from this function was private and it did not want to have to strdup anything. With this change, I suspect that it is much saner to make this function *not* take any external strbuf as input, because you are always returning a piece of memory that belongs to the caller, or a NULL. In other words, with the new world order, wouldn't a saner function signature be: static const char *read_and_strip_branch(const char **path); after this patch? Also I notice that the error-return cases of this function may be wrong even before your patch. Shouldn't it be doing *branch = NULL (and 'return NULL' after the suggested change)? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] wt-status: split wt_status_state parsing function out 2013-03-06 18:48 ` Junio C Hamano @ 2013-03-06 23:53 ` Junio C Hamano 0 siblings, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-06 23:53 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Junio C Hamano <gitster@pobox.com> writes: > In other words, with the new world order, wouldn't a saner function > signature be: > > static const char *read_and_strip_branch(const char **path); Eh, discard an asterisk from there. "Given a string to name the file, read it to find the branch name recorded in it". > after this patch? > > Also I notice that the error-return cases of this function may be > wrong even before your patch. Shouldn't it be doing *branch = NULL > (and 'return NULL' after the suggested change)? ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 2/4] wt-status: move wt_status_get_state() out to wt_status_print() 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 1/4] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 ` Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 3/4] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy ` (2 subsequent siblings) 4 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/wt-status.c b/wt-status.c index 183aafe..6a3566b 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1044,31 +1044,29 @@ void wt_status_get_state(struct wt_status_state *state) strbuf_release(&onto); } -static void wt_status_print_state(struct wt_status *s) +static void wt_status_print_state(struct wt_status *s, + struct wt_status_state *state) { const char *state_color = color(WT_STATUS_HEADER, s); - struct wt_status_state state; - - wt_status_get_state(&state); - - if (state.merge_in_progress) - show_merge_in_progress(s, &state, state_color); - else if (state.am_in_progress) - show_am_in_progress(s, &state, state_color); - else if (state.rebase_in_progress || state.rebase_interactive_in_progress) - show_rebase_in_progress(s, &state, state_color); - else if (state.cherry_pick_in_progress) - show_cherry_pick_in_progress(s, &state, state_color); - if (state.bisect_in_progress) - show_bisect_in_progress(s, &state, state_color); - free(state.branch); - free(state.onto); + if (state->merge_in_progress) + show_merge_in_progress(s, state, state_color); + else if (state->am_in_progress) + show_am_in_progress(s, state, state_color); + else if (state->rebase_in_progress || state->rebase_interactive_in_progress) + show_rebase_in_progress(s, state, state_color); + else if (state->cherry_pick_in_progress) + show_cherry_pick_in_progress(s, state, state_color); + if (state->bisect_in_progress) + show_bisect_in_progress(s, state, state_color); } void wt_status_print(struct wt_status *s) { const char *branch_color = color(WT_STATUS_ONBRANCH, s); const char *branch_status_color = color(WT_STATUS_HEADER, s); + struct wt_status_state state; + + wt_status_get_state(&state); if (s->branch) { const char *on_what = _("On branch "); @@ -1087,7 +1085,10 @@ void wt_status_print(struct wt_status *s) wt_status_print_tracking(s); } - wt_status_print_state(s); + wt_status_print_state(s, &state); + free(state.branch); + free(state.onto); + if (s->is_initial) { status_printf_ln(s, color(WT_STATUS_HEADER, s), ""); status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit")); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 3/4] status: show more info than "currently not on any branch" 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 1/4] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 2/4] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 ` Nguyễn Thái Ngọc Duy 2013-03-06 19:16 ` Junio C Hamano 2013-03-06 12:21 ` [PATCH v2 4/4] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 4 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy 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> --- t/t7406-submodule-update.sh | 6 ++-- t/t7512-status-help.sh | 52 +++++++++++++++++---------- wt-status.c | 85 ++++++++++++++++++++++++++++++++++++++++++--- wt-status.h | 4 ++- 4 files changed, 121 insertions(+), 26 deletions(-) diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 4975ec0..50ac020 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -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 ) ' diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index d2da89a..da22088 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -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 diff --git a/wt-status.c b/wt-status.c index 6a3566b..7797ccf 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1001,7 +1001,68 @@ static void read_and_strip_branch(struct strbuf *sb, *branch = xstrdup(*branch); } -void wt_status_get_state(struct wt_status_state *state) +struct grab_1st_switch_cbdata { + 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); + return 0; +} + +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_recent_reflog_ent("HEAD", grab_1st_switch, 4096, &cb)) + for_each_reflog_ent("HEAD", grab_1st_switch, &cb); + if (!cb.buf.len) + return; + + if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 && + (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 strbuf branch = STRBUF_INIT; struct strbuf onto = STRBUF_INIT; @@ -1040,6 +1101,10 @@ void wt_status_get_state(struct wt_status_state *state) read_and_strip_branch(&branch, &state->branch, "BISECT_START"); } + + if (get_detached_from) + wt_status_get_detached_from(state); + strbuf_release(&branch); strbuf_release(&onto); } @@ -1066,7 +1131,8 @@ void wt_status_print(struct wt_status *s) const char *branch_status_color = color(WT_STATUS_HEADER, s); struct wt_status_state 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 "); @@ -1074,9 +1140,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); @@ -1088,6 +1164,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), ""); diff --git a/wt-status.h b/wt-status.h index 5ddcbf6..5cb7df9 100644 --- a/wt-status.h +++ b/wt-status.h @@ -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); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] status: show more info than "currently not on any branch" 2013-03-06 12:21 ` [PATCH v2 3/4] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy @ 2013-03-06 19:16 ` Junio C Hamano 2013-03-08 11:04 ` Duy Nguyen 0 siblings, 1 reply; 38+ messages in thread From: Junio C Hamano @ 2013-03-06 19:16 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > +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_recent_reflog_ent("HEAD", grab_1st_switch, 4096, &cb)) > + for_each_reflog_ent("HEAD", grab_1st_switch, &cb); > + if (!cb.buf.len) > + return; Is this correct? What if the recent entries (i.e. the tail 4k) of the HEAD reflog did not have *any* checkout? Your callback never returns non-zero, so as long as the HEAD reflog is sufficiently long, for_each_recent_reflog_ent() will return 0 to signal success, and you do not dig deeper by retrying the full reflog for HEAD, missing the checkout that exists before the final 4k, no? It should be more like this, I would think: for_each_recent_reflog_ent(); if (!found) for_each_reflog_ent(); if (!found) return; Using cb.buf.len as the "found" marker may be correct, but I found it a bit subtle to my taste, without explanation. Adding an explicit bit to "struct grab_1st_switch_cbdata" would be cleaner and more resistant to future changes, I think. > + > + if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 && > + (commit = lookup_commit_reference_gently(sha1, 1)) != NULL && > + !hashcmp(cb.nsha1, commit->object.sha1)) { That feels unnecessarily expensive. Why not hashcmp before checking the type of the object to reject the case where the ref moved since the last checkout early? For that matter, does this even need to check the type of the object that currently sits at the ref? Isn't it sufficient to reject this case by seeing if sha1 is the same as cb.nsha1? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] status: show more info than "currently not on any branch" 2013-03-06 19:16 ` Junio C Hamano @ 2013-03-08 11:04 ` Duy Nguyen 2013-03-08 21:46 ` Junio C Hamano 0 siblings, 1 reply; 38+ messages in thread From: Duy Nguyen @ 2013-03-08 11:04 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Matthieu Moy, Jonathan Niedier On Thu, Mar 7, 2013 at 2:16 AM, Junio C Hamano <gitster@pobox.com> wrote: > Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > >> +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_recent_reflog_ent("HEAD", grab_1st_switch, 4096, &cb)) >> + for_each_reflog_ent("HEAD", grab_1st_switch, &cb); >> + if (!cb.buf.len) >> + return; > > Is this correct? What if the recent entries (i.e. the tail 4k) of > the HEAD reflog did not have *any* checkout? Your callback never > returns non-zero, so as long as the HEAD reflog is sufficiently > long, for_each_recent_reflog_ent() will return 0 to signal success, > and you do not dig deeper by retrying the full reflog for HEAD, > missing the checkout that exists before the final 4k, no? > > It should be more like this, I would think: > > for_each_recent_reflog_ent(); > if (!found) > for_each_reflog_ent(); > if (!found) > return; Yes. This "recent" optimization is tricky. > Using cb.buf.len as the "found" marker may be correct, but I found > it a bit subtle to my taste, without explanation. Adding an > explicit bit to "struct grab_1st_switch_cbdata" would be cleaner and > more resistant to future changes, I think. OK > >> + >> + if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 && >> + (commit = lookup_commit_reference_gently(sha1, 1)) != NULL && >> + !hashcmp(cb.nsha1, commit->object.sha1)) { > > That feels unnecessarily expensive. Why not hashcmp before checking > the type of the object to reject the case where the ref moved since > the last checkout early? > > For that matter, does this even need to check the type of the object > that currently sits at the ref? Isn't it sufficient to reject this > case by seeing if sha1 is the same as cb.nsha1? nsha1 is always a commit sha-1, sha-1 could be a tag sha-1 that refers to the same commit. hashcmp before lookup is a good idea. Although I don't think it's expensive in the big picture. When HEAD is not detached, we show "<n> commits ahead of @{u}" which is way more expensive than this. As long as "git status" on detached HEAD does not use up all the time that "git status" on branches normally does, I think we're fine. -- Duy ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] status: show more info than "currently not on any branch" 2013-03-08 11:04 ` Duy Nguyen @ 2013-03-08 21:46 ` Junio C Hamano 0 siblings, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-08 21:46 UTC (permalink / raw) To: Duy Nguyen; +Cc: git, Matthieu Moy, Jonathan Niedier Duy Nguyen <pclouds@gmail.com> writes: >> It should be more like this, I would think: >> >> for_each_recent_reflog_ent(); >> if (!found) >> for_each_reflog_ent(); >> if (!found) >> return; > > Yes. This "recent" optimization is tricky. Not really. What is tricky is that reflog is an append-only file and we only have an API to let us read it in the oldest to newer order, which is natural for the file format, but unsuited for the purpose of finding out nth most recent anything. See the other thread I am going to send out soon on this. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 4/4] branch: show more information when HEAD is detached 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (2 preceding siblings ...) 2013-03-06 12:21 ` [PATCH v2 3/4] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 ` Nguyễn Thái Ngọc Duy 2013-03-06 12:26 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 4 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy This prints more helpful info when HEAD is detached: is it detached because of bisect or rebase? What is the original branch name in those cases? Is it detached because the user checks out a remote ref or a tag (and which one)? Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- builtin/branch.c | 25 ++++++++++++++++++++++++- t/t3203-branch-output.sh | 6 +++--- t/t6030-bisect-porcelain.sh | 2 +- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 6371bf9..02dee0d 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -18,6 +18,7 @@ #include "string-list.h" #include "column.h" #include "utf8.h" +#include "wt-status.h" static const char * const builtin_branch_usage[] = { N_("git branch [options] [-r | -a] [--merged | --no-merged]"), @@ -550,6 +551,28 @@ static int calc_maxwidth(struct ref_list *refs) return w; } +static char *get_head_description() +{ + struct strbuf desc = STRBUF_INIT; + struct wt_status_state state; + wt_status_get_state(&state, 1); + if (state.rebase_in_progress || + state.rebase_interactive_in_progress) + strbuf_addf(&desc, _("(no branch, rebasing %s)"), + state.branch); + else if (state.bisect_in_progress) + strbuf_addf(&desc, _("(no branch, bisecting %s)"), + state.branch); + else if (state.detached_from) + strbuf_addf(&desc, _("(detached from %s)"), + state.detached_from); + else + strbuf_addstr(&desc, _("(no branch)")); + free(state.branch); + free(state.onto); + free(state.detached_from); + return strbuf_detach(&desc, NULL); +} static void show_detached(struct ref_list *ref_list) { @@ -557,7 +580,7 @@ static void show_detached(struct ref_list *ref_list) if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; - item.name = xstrdup(_("(no branch)")); + item.name = get_head_description(); item.width = utf8_strwidth(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 76fe7e0..ba4f98e 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -94,13 +94,13 @@ test_expect_success 'git branch -v pattern does not show branch summaries' ' test_must_fail git branch -v branch* ' -cat >expect <<'EOF' -* (no branch) +test_expect_success 'git branch shows detached HEAD properly' ' + cat >expect <<EOF && +* (detached from $(git rev-parse --short HEAD^0)) branch-one branch-two master EOF -test_expect_success 'git branch shows detached HEAD properly' ' git checkout HEAD^0 && git branch >actual && test_i18ncmp expect actual diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 3e0e15f..9b6f0d0 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - test_i18ngrep "* (no branch)" branch.output > /dev/null && + test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null && test_cmp saved .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates 2013-03-06 12:21 ` [PATCH v2 4/4] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy @ 2013-03-06 12:26 ` Nguyễn Thái Ngọc Duy 2013-03-06 12:26 ` [PATCH v2+ 4/4] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 0 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:26 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy Since the previous round: - reflog format change is dropped - almost always show "HEAD detached from/at xxx" instead of "currently not on any branch", where "xxx" is either a ref, or an abbreviated sha-1 I wanted to introduce something like @{-1:to} that resolves the "to" sha-1 in reflog, in addition to @{-1} which resolves the "from" part. But the syntax looks ugly so I dropped it. Meanwhile people could do git log -1 -g --grep-reflog checkout --pretty=format:%h to retrieve the same info. Nguyễn Thái Ngọc Duy (4): wt-status: split wt_status_state parsing function out wt-status: move wt_status_get_state() out to wt_status_print() status: show more info than "currently not on any branch" branch: show more information when HEAD is detached builtin/branch.c | 25 +++++++- t/t3203-branch-output.sh | 6 +- t/t6030-bisect-porcelain.sh | 2 +- t/t7406-submodule-update.sh | 6 +- t/t7512-status-help.sh | 52 +++++++++------ wt-status.c | 152 ++++++++++++++++++++++++++++++++++---------- wt-status.h | 7 +- 7 files changed, 190 insertions(+), 60 deletions(-) -- 1.8.1.2.536.gf441e6d ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2+ 4/4] branch: show more information when HEAD is detached 2013-03-06 12:26 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy @ 2013-03-06 12:26 ` Nguyễn Thái Ngọc Duy 0 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:26 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy This prints more helpful info when HEAD is detached: is it detached because of bisect or rebase? What is the original branch name in those cases? Is it detached because the user checks out a remote ref or a tag (and which one)? Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- Oops, the previous one did not do s/\(get_head_description\)()$/\1(void)/ This one does. builtin/branch.c | 25 ++++++++++++++++++++++++- t/t3203-branch-output.sh | 6 +++--- t/t6030-bisect-porcelain.sh | 2 +- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 6371bf9..02dee0d 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -18,6 +18,7 @@ #include "string-list.h" #include "column.h" #include "utf8.h" +#include "wt-status.h" static const char * const builtin_branch_usage[] = { N_("git branch [options] [-r | -a] [--merged | --no-merged]"), @@ -550,6 +551,28 @@ static int calc_maxwidth(struct ref_list *refs) return w; } +static char *get_head_description(void) +{ + struct strbuf desc = STRBUF_INIT; + struct wt_status_state state; + wt_status_get_state(&state, 1); + if (state.rebase_in_progress || + state.rebase_interactive_in_progress) + strbuf_addf(&desc, _("(no branch, rebasing %s)"), + state.branch); + else if (state.bisect_in_progress) + strbuf_addf(&desc, _("(no branch, bisecting %s)"), + state.branch); + else if (state.detached_from) + strbuf_addf(&desc, _("(detached from %s)"), + state.detached_from); + else + strbuf_addstr(&desc, _("(no branch)")); + free(state.branch); + free(state.onto); + free(state.detached_from); + return strbuf_detach(&desc, NULL); +} static void show_detached(struct ref_list *ref_list) { @@ -557,7 +580,7 @@ static void show_detached(struct ref_list *ref_list) if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; - item.name = xstrdup(_("(no branch)")); + item.name = get_head_description(); item.width = utf8_strwidth(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 76fe7e0..ba4f98e 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -94,13 +94,13 @@ test_expect_success 'git branch -v pattern does not show branch summaries' ' test_must_fail git branch -v branch* ' -cat >expect <<'EOF' -* (no branch) +test_expect_success 'git branch shows detached HEAD properly' ' + cat >expect <<EOF && +* (detached from $(git rev-parse --short HEAD^0)) branch-one branch-two master EOF -test_expect_success 'git branch shows detached HEAD properly' ' git checkout HEAD^0 && git branch >actual && test_i18ncmp expect actual diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 3e0e15f..9b6f0d0 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - test_i18ngrep "* (no branch)" branch.output > /dev/null && + test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null && test_cmp saved .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (3 preceding siblings ...) 2013-03-06 12:21 ` [PATCH v2 4/4] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 ` Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() Nguyễn Thái Ngọc Duy ` (5 more replies) 4 siblings, 6 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 UTC (permalink / raw) To: git Cc: Matthieu Moy, Jonathan Niedier, Junio C Hamano, Nguyễn Thái Ngọc Duy This round fixes the design issue of read_and_strip_branch(), makes use of jc/reflog-reverse-walk and performs cheaper sha-1 check on detached commits. Nguyễn Thái Ngọc Duy (5): wt-status: move strbuf into read_and_strip_branch() wt-status: split wt_status_state parsing function out wt-status: move wt_status_get_state() out to wt_status_print() status: show more info than "currently not on any branch" branch: show more information when HEAD is detached builtin/branch.c | 26 +++++- t/t3203-branch-output.sh | 6 +- t/t6030-bisect-porcelain.sh | 2 +- t/t7406-submodule-update.sh | 6 +- t/t7512-status-help.sh | 52 ++++++----- wt-status.c | 204 +++++++++++++++++++++++++++++++------------- wt-status.h | 7 +- 7 files changed, 214 insertions(+), 89 deletions(-) -- 1.8.1.2.536.gf441e6d ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 ` Nguyễn Thái Ngọc Duy 2013-03-13 16:20 ` Junio C Hamano 2013-03-16 2:12 ` [PATCH v3+ " Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 2/5] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy ` (4 subsequent siblings) 5 siblings, 2 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 UTC (permalink / raw) To: git Cc: Matthieu Moy, Jonathan Niedier, Junio C Hamano, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 65 ++++++++++++++++++++++++++++--------------------------------- wt-status.h | 4 ++-- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/wt-status.c b/wt-status.c index ef405d0..6cac27b 100644 --- a/wt-status.c +++ b/wt-status.c @@ -969,41 +969,41 @@ static void show_bisect_in_progress(struct wt_status *s, /* * Extract branch information from rebase/bisect */ -static void read_and_strip_branch(struct strbuf *sb, - const char **branch, - const char *path) +static char *read_and_strip_branch(const char *path) { + struct strbuf sb = STRBUF_INIT; unsigned char sha1[20]; - strbuf_reset(sb); - if (strbuf_read_file(sb, git_path("%s", path), 0) <= 0) - return; + if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0) + goto got_nothing; - while (sb->len && sb->buf[sb->len - 1] == '\n') - strbuf_setlen(sb, sb->len - 1); - if (!sb->len) - return; - if (!prefixcmp(sb->buf, "refs/heads/")) - *branch = sb->buf + strlen("refs/heads/"); - else if (!prefixcmp(sb->buf, "refs/")) - *branch = sb->buf; - else if (!get_sha1_hex(sb->buf, sha1)) { + while (&sb.len && sb.buf[sb.len - 1] == '\n') + strbuf_setlen(&sb, sb.len - 1); + if (!sb.len) + goto got_nothing; + if (!prefixcmp(sb.buf, "refs/heads/")) + strbuf_remove(&sb,0, strlen("refs/heads/")); + else if (!prefixcmp(sb.buf, "refs/")) + ; + else if (!get_sha1_hex(sb.buf, sha1)) { const char *abbrev; abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); - strbuf_reset(sb); - strbuf_addstr(sb, abbrev); - *branch = sb->buf; - } else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ - ; + strbuf_reset(&sb); + strbuf_addstr(&sb, abbrev); + } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */ + goto got_nothing; else /* bisect */ - *branch = sb->buf; + ; + return strbuf_detach(&sb, NULL); + +got_nothing: + strbuf_release(&sb); + return NULL; } static void wt_status_print_state(struct wt_status *s) { const char *state_color = color(WT_STATUS_HEADER, s); - struct strbuf branch = STRBUF_INIT; - struct strbuf onto = STRBUF_INIT; struct wt_status_state state; struct stat st; @@ -1018,27 +1018,22 @@ static void wt_status_print_state(struct wt_status *s) state.am_empty_patch = 1; } else { state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, - "rebase-apply/head-name"); - read_and_strip_branch(&onto, &state.onto, - "rebase-apply/onto"); + state.branch = read_and_strip_branch("rebase-apply/head-name"); + state.onto = read_and_strip_branch("rebase-apply/onto"); } } else if (!stat(git_path("rebase-merge"), &st)) { if (!stat(git_path("rebase-merge/interactive"), &st)) state.rebase_interactive_in_progress = 1; else state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, - "rebase-merge/head-name"); - read_and_strip_branch(&onto, &state.onto, - "rebase-merge/onto"); + state.branch = read_and_strip_branch("rebase-merge/head-name"); + state.onto = read_and_strip_branch("rebase-merge/onto"); } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { state.cherry_pick_in_progress = 1; } if (!stat(git_path("BISECT_LOG"), &st)) { state.bisect_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, - "BISECT_START"); + state.branch = read_and_strip_branch("BISECT_START"); } if (state.merge_in_progress) @@ -1051,8 +1046,8 @@ static void wt_status_print_state(struct wt_status *s) show_cherry_pick_in_progress(s, &state, state_color); if (state.bisect_in_progress) show_bisect_in_progress(s, &state, state_color); - strbuf_release(&branch); - strbuf_release(&onto); + free(state.branch); + free(state.onto); } void wt_status_print(struct wt_status *s) diff --git a/wt-status.h b/wt-status.h index 81e1dcf..b8c3512 100644 --- a/wt-status.h +++ b/wt-status.h @@ -79,8 +79,8 @@ struct wt_status_state { int rebase_interactive_in_progress; int cherry_pick_in_progress; int bisect_in_progress; - const char *branch; - const char *onto; + char *branch; + char *onto; }; void wt_status_prepare(struct wt_status *s); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() 2013-03-13 11:42 ` [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() Nguyễn Thái Ngọc Duy @ 2013-03-13 16:20 ` Junio C Hamano 2013-03-16 2:12 ` [PATCH v3+ " Nguyễn Thái Ngọc Duy 1 sibling, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-13 16:20 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> You do not have anything to say above the S-o-b line? The primary effect of this patch is to change the lifespan and ownership rule of the piece of memory used for state.branch/state.onto and moving the strbuf is a mere logical consequence of that change. It is not explained why this change is a good idea. > --- > wt-status.c | 65 ++++++++++++++++++++++++++++--------------------------------- > wt-status.h | 4 ++-- > 2 files changed, 32 insertions(+), 37 deletions(-) > > diff --git a/wt-status.c b/wt-status.c > index ef405d0..6cac27b 100644 > --- a/wt-status.c > +++ b/wt-status.c > @@ -969,41 +969,41 @@ static void show_bisect_in_progress(struct wt_status *s, > /* > * Extract branch information from rebase/bisect > */ > -static void read_and_strip_branch(struct strbuf *sb, > - const char **branch, > - const char *path) > +static char *read_and_strip_branch(const char *path) > { > + struct strbuf sb = STRBUF_INIT; > unsigned char sha1[20]; > > - strbuf_reset(sb); > - if (strbuf_read_file(sb, git_path("%s", path), 0) <= 0) > - return; > + if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0) > + goto got_nothing; > > - while (sb->len && sb->buf[sb->len - 1] == '\n') > - strbuf_setlen(sb, sb->len - 1); > - if (!sb->len) > - return; > - if (!prefixcmp(sb->buf, "refs/heads/")) > - *branch = sb->buf + strlen("refs/heads/"); > - else if (!prefixcmp(sb->buf, "refs/")) > - *branch = sb->buf; > - else if (!get_sha1_hex(sb->buf, sha1)) { > + while (&sb.len && sb.buf[sb.len - 1] == '\n') > + strbuf_setlen(&sb, sb.len - 1); > + if (!sb.len) > + goto got_nothing; > + if (!prefixcmp(sb.buf, "refs/heads/")) > + strbuf_remove(&sb,0, strlen("refs/heads/")); > + else if (!prefixcmp(sb.buf, "refs/")) > + ; > + else if (!get_sha1_hex(sb.buf, sha1)) { > const char *abbrev; > abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); > - strbuf_reset(sb); > - strbuf_addstr(sb, abbrev); > - *branch = sb->buf; > - } else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ > - ; > + strbuf_reset(&sb); > + strbuf_addstr(&sb, abbrev); > + } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */ > + goto got_nothing; > else /* bisect */ > - *branch = sb->buf; > + ; > + return strbuf_detach(&sb, NULL); > + > +got_nothing: > + strbuf_release(&sb); > + return NULL; > } > > static void wt_status_print_state(struct wt_status *s) > { > const char *state_color = color(WT_STATUS_HEADER, s); > - struct strbuf branch = STRBUF_INIT; > - struct strbuf onto = STRBUF_INIT; > struct wt_status_state state; > struct stat st; > > @@ -1018,27 +1018,22 @@ static void wt_status_print_state(struct wt_status *s) > state.am_empty_patch = 1; > } else { > state.rebase_in_progress = 1; > - read_and_strip_branch(&branch, &state.branch, > - "rebase-apply/head-name"); > - read_and_strip_branch(&onto, &state.onto, > - "rebase-apply/onto"); > + state.branch = read_and_strip_branch("rebase-apply/head-name"); > + state.onto = read_and_strip_branch("rebase-apply/onto"); > } > } else if (!stat(git_path("rebase-merge"), &st)) { > if (!stat(git_path("rebase-merge/interactive"), &st)) > state.rebase_interactive_in_progress = 1; > else > state.rebase_in_progress = 1; > - read_and_strip_branch(&branch, &state.branch, > - "rebase-merge/head-name"); > - read_and_strip_branch(&onto, &state.onto, > - "rebase-merge/onto"); > + state.branch = read_and_strip_branch("rebase-merge/head-name"); > + state.onto = read_and_strip_branch("rebase-merge/onto"); > } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { > state.cherry_pick_in_progress = 1; > } > if (!stat(git_path("BISECT_LOG"), &st)) { > state.bisect_in_progress = 1; > - read_and_strip_branch(&branch, &state.branch, > - "BISECT_START"); > + state.branch = read_and_strip_branch("BISECT_START"); > } > > if (state.merge_in_progress) > @@ -1051,8 +1046,8 @@ static void wt_status_print_state(struct wt_status *s) > show_cherry_pick_in_progress(s, &state, state_color); > if (state.bisect_in_progress) > show_bisect_in_progress(s, &state, state_color); > - strbuf_release(&branch); > - strbuf_release(&onto); > + free(state.branch); > + free(state.onto); > } > > void wt_status_print(struct wt_status *s) > diff --git a/wt-status.h b/wt-status.h > index 81e1dcf..b8c3512 100644 > --- a/wt-status.h > +++ b/wt-status.h > @@ -79,8 +79,8 @@ struct wt_status_state { > int rebase_interactive_in_progress; > int cherry_pick_in_progress; > int bisect_in_progress; > - const char *branch; > - const char *onto; > + char *branch; > + char *onto; > }; > > void wt_status_prepare(struct wt_status *s); ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3+ 1/5] wt-status: move strbuf into read_and_strip_branch() 2013-03-13 11:42 ` [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() Nguyễn Thái Ngọc Duy 2013-03-13 16:20 ` Junio C Hamano @ 2013-03-16 2:12 ` Nguyễn Thái Ngọc Duy 1 sibling, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-16 2:12 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy The strbufs are placed outside read_and_strip_branch as a premature optimization: when it reads "refs/heads/foo" to strbuf and wants to return just "foo", it could do so without memory movement. In return the caller must not use the returned pointer after releasing strbufs, which own the buffers that contain the returned strings. It's a clumsy design. By moving strbufs into read_and_strip_branch(), the returned pointer always points to a malloc'd buffer or NULL. The pointer can be passed around and freed after use. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- Fixed the commit message. No code change. wt-status.c | 65 ++++++++++++++++++++++++++++--------------------------------- wt-status.h | 4 ++-- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/wt-status.c b/wt-status.c index ef405d0..6cac27b 100644 --- a/wt-status.c +++ b/wt-status.c @@ -969,41 +969,41 @@ static void show_bisect_in_progress(struct wt_status *s, /* * Extract branch information from rebase/bisect */ -static void read_and_strip_branch(struct strbuf *sb, - const char **branch, - const char *path) +static char *read_and_strip_branch(const char *path) { + struct strbuf sb = STRBUF_INIT; unsigned char sha1[20]; - strbuf_reset(sb); - if (strbuf_read_file(sb, git_path("%s", path), 0) <= 0) - return; + if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0) + goto got_nothing; - while (sb->len && sb->buf[sb->len - 1] == '\n') - strbuf_setlen(sb, sb->len - 1); - if (!sb->len) - return; - if (!prefixcmp(sb->buf, "refs/heads/")) - *branch = sb->buf + strlen("refs/heads/"); - else if (!prefixcmp(sb->buf, "refs/")) - *branch = sb->buf; - else if (!get_sha1_hex(sb->buf, sha1)) { + while (&sb.len && sb.buf[sb.len - 1] == '\n') + strbuf_setlen(&sb, sb.len - 1); + if (!sb.len) + goto got_nothing; + if (!prefixcmp(sb.buf, "refs/heads/")) + strbuf_remove(&sb,0, strlen("refs/heads/")); + else if (!prefixcmp(sb.buf, "refs/")) + ; + else if (!get_sha1_hex(sb.buf, sha1)) { const char *abbrev; abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); - strbuf_reset(sb); - strbuf_addstr(sb, abbrev); - *branch = sb->buf; - } else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ - ; + strbuf_reset(&sb); + strbuf_addstr(&sb, abbrev); + } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */ + goto got_nothing; else /* bisect */ - *branch = sb->buf; + ; + return strbuf_detach(&sb, NULL); + +got_nothing: + strbuf_release(&sb); + return NULL; } static void wt_status_print_state(struct wt_status *s) { const char *state_color = color(WT_STATUS_HEADER, s); - struct strbuf branch = STRBUF_INIT; - struct strbuf onto = STRBUF_INIT; struct wt_status_state state; struct stat st; @@ -1018,27 +1018,22 @@ static void wt_status_print_state(struct wt_status *s) state.am_empty_patch = 1; } else { state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, - "rebase-apply/head-name"); - read_and_strip_branch(&onto, &state.onto, - "rebase-apply/onto"); + state.branch = read_and_strip_branch("rebase-apply/head-name"); + state.onto = read_and_strip_branch("rebase-apply/onto"); } } else if (!stat(git_path("rebase-merge"), &st)) { if (!stat(git_path("rebase-merge/interactive"), &st)) state.rebase_interactive_in_progress = 1; else state.rebase_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, - "rebase-merge/head-name"); - read_and_strip_branch(&onto, &state.onto, - "rebase-merge/onto"); + state.branch = read_and_strip_branch("rebase-merge/head-name"); + state.onto = read_and_strip_branch("rebase-merge/onto"); } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { state.cherry_pick_in_progress = 1; } if (!stat(git_path("BISECT_LOG"), &st)) { state.bisect_in_progress = 1; - read_and_strip_branch(&branch, &state.branch, - "BISECT_START"); + state.branch = read_and_strip_branch("BISECT_START"); } if (state.merge_in_progress) @@ -1051,8 +1046,8 @@ static void wt_status_print_state(struct wt_status *s) show_cherry_pick_in_progress(s, &state, state_color); if (state.bisect_in_progress) show_bisect_in_progress(s, &state, state_color); - strbuf_release(&branch); - strbuf_release(&onto); + free(state.branch); + free(state.onto); } void wt_status_print(struct wt_status *s) diff --git a/wt-status.h b/wt-status.h index 81e1dcf..b8c3512 100644 --- a/wt-status.h +++ b/wt-status.h @@ -79,8 +79,8 @@ struct wt_status_state { int rebase_interactive_in_progress; int cherry_pick_in_progress; int bisect_in_progress; - const char *branch; - const char *onto; + char *branch; + char *onto; }; void wt_status_prepare(struct wt_status *s); -- 1.8.2.83.gc99314b ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v3 2/5] wt-status: split wt_status_state parsing function out 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 ` Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 3/5] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy ` (3 subsequent siblings) 5 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 UTC (permalink / raw) To: git Cc: Matthieu Moy, Jonathan Niedier, Junio C Hamano, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 41 +++++++++++++++++++++++------------------ wt-status.h | 1 + 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/wt-status.c b/wt-status.c index 6cac27b..0d8989f 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1001,40 +1001,45 @@ got_nothing: return NULL; } -static void wt_status_print_state(struct wt_status *s) +void wt_status_get_state(struct wt_status_state *state) { - const char *state_color = color(WT_STATUS_HEADER, s); - struct wt_status_state state; struct stat st; - memset(&state, 0, sizeof(state)); - if (!stat(git_path("MERGE_HEAD"), &st)) { - state.merge_in_progress = 1; + state->merge_in_progress = 1; } else if (!stat(git_path("rebase-apply"), &st)) { if (!stat(git_path("rebase-apply/applying"), &st)) { - state.am_in_progress = 1; + state->am_in_progress = 1; if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size) - state.am_empty_patch = 1; + state->am_empty_patch = 1; } else { - state.rebase_in_progress = 1; - state.branch = read_and_strip_branch("rebase-apply/head-name"); - state.onto = read_and_strip_branch("rebase-apply/onto"); + state->rebase_in_progress = 1; + state->branch = read_and_strip_branch("rebase-apply/head-name"); + state->onto = read_and_strip_branch("rebase-apply/onto"); } } else if (!stat(git_path("rebase-merge"), &st)) { if (!stat(git_path("rebase-merge/interactive"), &st)) - state.rebase_interactive_in_progress = 1; + state->rebase_interactive_in_progress = 1; else - state.rebase_in_progress = 1; - state.branch = read_and_strip_branch("rebase-merge/head-name"); - state.onto = read_and_strip_branch("rebase-merge/onto"); + state->rebase_in_progress = 1; + state->branch = read_and_strip_branch("rebase-merge/head-name"); + state->onto = read_and_strip_branch("rebase-merge/onto"); } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { - state.cherry_pick_in_progress = 1; + state->cherry_pick_in_progress = 1; } if (!stat(git_path("BISECT_LOG"), &st)) { - state.bisect_in_progress = 1; - state.branch = read_and_strip_branch("BISECT_START"); + state->bisect_in_progress = 1; + state->branch = read_and_strip_branch("BISECT_START"); } +} + +static void wt_status_print_state(struct wt_status *s) +{ + const char *state_color = color(WT_STATUS_HEADER, s); + struct wt_status_state state; + + memset(&state, 0, sizeof(state)); + wt_status_get_state(&state); if (state.merge_in_progress) show_merge_in_progress(s, &state, state_color); diff --git a/wt-status.h b/wt-status.h index b8c3512..5ddcbf6 100644 --- a/wt-status.h +++ b/wt-status.h @@ -86,6 +86,7 @@ struct wt_status_state { 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_shortstatus_print(struct wt_status *s); void wt_porcelain_print(struct wt_status *s); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v3 3/5] wt-status: move wt_status_get_state() out to wt_status_print() 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 2/5] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 ` Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 4/5] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy ` (2 subsequent siblings) 5 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 UTC (permalink / raw) To: git Cc: Matthieu Moy, Jonathan Niedier, Junio C Hamano, Nguyễn Thái Ngọc Duy Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- wt-status.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/wt-status.c b/wt-status.c index 0d8989f..17690d8 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1033,32 +1033,30 @@ void wt_status_get_state(struct wt_status_state *state) } } -static void wt_status_print_state(struct wt_status *s) +static void wt_status_print_state(struct wt_status *s, + struct wt_status_state *state) { const char *state_color = color(WT_STATUS_HEADER, s); - struct wt_status_state state; - - memset(&state, 0, sizeof(state)); - wt_status_get_state(&state); - - if (state.merge_in_progress) - show_merge_in_progress(s, &state, state_color); - else if (state.am_in_progress) - show_am_in_progress(s, &state, state_color); - else if (state.rebase_in_progress || state.rebase_interactive_in_progress) - show_rebase_in_progress(s, &state, state_color); - else if (state.cherry_pick_in_progress) - show_cherry_pick_in_progress(s, &state, state_color); - if (state.bisect_in_progress) - show_bisect_in_progress(s, &state, state_color); - free(state.branch); - free(state.onto); + if (state->merge_in_progress) + show_merge_in_progress(s, state, state_color); + else if (state->am_in_progress) + show_am_in_progress(s, state, state_color); + else if (state->rebase_in_progress || state->rebase_interactive_in_progress) + show_rebase_in_progress(s, state, state_color); + else if (state->cherry_pick_in_progress) + show_cherry_pick_in_progress(s, state, state_color); + if (state->bisect_in_progress) + show_bisect_in_progress(s, state, state_color); } void wt_status_print(struct wt_status *s) { const char *branch_color = color(WT_STATUS_ONBRANCH, s); const char *branch_status_color = color(WT_STATUS_HEADER, s); + struct wt_status_state state; + + memset(&state, 0, sizeof(state)); + wt_status_get_state(&state); if (s->branch) { const char *on_what = _("On branch "); @@ -1077,7 +1075,10 @@ void wt_status_print(struct wt_status *s) wt_status_print_tracking(s); } - wt_status_print_state(s); + wt_status_print_state(s, &state); + free(state.branch); + free(state.onto); + if (s->is_initial) { status_printf_ln(s, color(WT_STATUS_HEADER, s), ""); status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit")); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v3 4/5] status: show more info than "currently not on any branch" 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (2 preceding siblings ...) 2013-03-13 11:42 ` [PATCH v3 3/5] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 ` Nguyễn Thái Ngọc Duy 2013-03-13 16:25 ` Junio C Hamano 2013-03-13 11:42 ` [PATCH v3 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-19 18:37 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Junio C Hamano 5 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 UTC (permalink / raw) To: git Cc: Matthieu Moy, Jonathan Niedier, Junio C Hamano, Nguyễn Thái Ngọc Duy 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> --- t/t7406-submodule-update.sh | 6 ++- t/t7512-status-help.sh | 52 ++++++++++++++++---------- wt-status.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- wt-status.h | 4 +- 4 files changed, 125 insertions(+), 26 deletions(-) diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index ea61761..a4ffea0 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -665,8 +665,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 && @@ -675,7 +677,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 ) ' diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index d2da89a..da22088 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -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 diff --git a/wt-status.c b/wt-status.c index 17690d8..8c6e0c8 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1001,7 +1001,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; @@ -1031,6 +1097,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, @@ -1056,7 +1125,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 "); @@ -1064,9 +1134,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); @@ -1078,6 +1158,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), ""); diff --git a/wt-status.h b/wt-status.h index 5ddcbf6..5cb7df9 100644 --- a/wt-status.h +++ b/wt-status.h @@ -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); -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v3 4/5] status: show more info than "currently not on any branch" 2013-03-13 11:42 ` [PATCH v3 4/5] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy @ 2013-03-13 16:25 ` Junio C Hamano 0 siblings, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-13 16:25 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > 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> > --- It does look like using the for_each_in_reverse() does make the caller less error prone (by the way, I'd love to see people review, poke holes and plug them in the implementation of reading the reflog file in reverse; I am not sure if it covered all the corner cases right). Thanks. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 5/5] branch: show more information when HEAD is detached 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (3 preceding siblings ...) 2013-03-13 11:42 ` [PATCH v3 4/5] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 ` Nguyễn Thái Ngọc Duy 2013-03-19 18:37 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Junio C Hamano 5 siblings, 0 replies; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-13 11:42 UTC (permalink / raw) To: git Cc: Matthieu Moy, Jonathan Niedier, Junio C Hamano, Nguyễn Thái Ngọc Duy This prints more helpful info when HEAD is detached: is it detached because of bisect or rebase? What is the original branch name in those cases? Is it detached because the user checks out a remote ref or a tag (and which one)? Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- builtin/branch.c | 26 +++++++++++++++++++++++++- t/t3203-branch-output.sh | 6 +++--- t/t6030-bisect-porcelain.sh | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 00d17d2..2ab0e4f 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -18,6 +18,7 @@ #include "string-list.h" #include "column.h" #include "utf8.h" +#include "wt-status.h" static const char * const builtin_branch_usage[] = { N_("git branch [options] [-r | -a] [--merged | --no-merged]"), @@ -550,6 +551,29 @@ static int calc_maxwidth(struct ref_list *refs) return w; } +static char *get_head_description(void) +{ + struct strbuf desc = STRBUF_INIT; + struct wt_status_state state; + memset(&state, 0, sizeof(state)); + wt_status_get_state(&state, 1); + if (state.rebase_in_progress || + state.rebase_interactive_in_progress) + strbuf_addf(&desc, _("(no branch, rebasing %s)"), + state.branch); + else if (state.bisect_in_progress) + strbuf_addf(&desc, _("(no branch, bisecting %s)"), + state.branch); + else if (state.detached_from) + strbuf_addf(&desc, _("(detached from %s)"), + state.detached_from); + else + strbuf_addstr(&desc, _("(no branch)")); + free(state.branch); + free(state.onto); + free(state.detached_from); + return strbuf_detach(&desc, NULL); +} static void show_detached(struct ref_list *ref_list) { @@ -557,7 +581,7 @@ static void show_detached(struct ref_list *ref_list) if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; - item.name = xstrdup(_("(no branch)")); + item.name = get_head_description(); item.width = utf8_strwidth(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 76fe7e0..ba4f98e 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -94,13 +94,13 @@ test_expect_success 'git branch -v pattern does not show branch summaries' ' test_must_fail git branch -v branch* ' -cat >expect <<'EOF' -* (no branch) +test_expect_success 'git branch shows detached HEAD properly' ' + cat >expect <<EOF && +* (detached from $(git rev-parse --short HEAD^0)) branch-one branch-two master EOF -test_expect_success 'git branch shows detached HEAD properly' ' git checkout HEAD^0 && git branch >actual && test_i18ncmp expect actual diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 3e0e15f..9b6f0d0 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - test_i18ngrep "* (no branch)" branch.output > /dev/null && + test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null && test_cmp saved .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' -- 1.8.1.2.536.gf441e6d ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy ` (4 preceding siblings ...) 2013-03-13 11:42 ` [PATCH v3 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy @ 2013-03-19 18:37 ` Junio C Hamano 2013-03-20 12:40 ` Duy Nguyen 5 siblings, 1 reply; 38+ messages in thread From: Junio C Hamano @ 2013-03-19 18:37 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > This round fixes the design issue of read_and_strip_branch(), makes > use of jc/reflog-reverse-walk and performs cheaper sha-1 check on > detached commits. I was running "git bisect start pu jch" (jch is a branch I do not push out everywhere that is somewhere in the middle of "master..pu"), and then after bisection finished, saw this: $ git branch --with 66887099e096f0258a5ef3b1e7458748597bdffe * (no branch, bisecting jch) nd/magic-pathspecs pu which is obviously bogus. I only said "I know the tip of pu is bad and the tip of jch is good". If anything, I was bisecting the breakage in 'pu', not in 'jch'. I think the message should better say "before you started to bisect you were on 'jch'" or something instead. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates 2013-03-19 18:37 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Junio C Hamano @ 2013-03-20 12:40 ` Duy Nguyen 2013-03-20 14:37 ` Junio C Hamano 0 siblings, 1 reply; 38+ messages in thread From: Duy Nguyen @ 2013-03-20 12:40 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Matthieu Moy, Jonathan Niedier On Wed, Mar 20, 2013 at 1:37 AM, Junio C Hamano <gitster@pobox.com> wrote: > I was running "git bisect start pu jch" (jch is a branch I do not > push out everywhere that is somewhere in the middle of > "master..pu"), and then after bisection finished, saw this: > > $ git branch --with 66887099e096f0258a5ef3b1e7458748597bdffe > * (no branch, bisecting jch) > nd/magic-pathspecs > pu > > which is obviously bogus. I only said "I know the tip of pu is bad > and the tip of jch is good". If anything, I was bisecting the > breakage in 'pu', not in 'jch'. > > I think the message should better say "before you started to bisect > you were on 'jch'" or something instead. How about * (no branch, bisect started on jch) then? I don't want to make it too long because it'll waste space in column layout. -- Duy ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates 2013-03-20 12:40 ` Duy Nguyen @ 2013-03-20 14:37 ` Junio C Hamano 2013-03-23 3:52 ` [PATCH] status, branch: fix the misleading "bisecting" message Nguyễn Thái Ngọc Duy 0 siblings, 1 reply; 38+ messages in thread From: Junio C Hamano @ 2013-03-20 14:37 UTC (permalink / raw) To: Duy Nguyen; +Cc: git, Matthieu Moy, Jonathan Niedier Duy Nguyen <pclouds@gmail.com> writes: >> I think the message should better say "before you started to bisect >> you were on 'jch'" or something instead. > > How about > > * (no branch, bisect started on jch) > > then? Sure. What you are showing is used only to decide where "git bisect reset" goes to, I think. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH] status, branch: fix the misleading "bisecting" message 2013-03-20 14:37 ` Junio C Hamano @ 2013-03-23 3:52 ` Nguyễn Thái Ngọc Duy 2013-03-24 5:30 ` Junio C Hamano 0 siblings, 1 reply; 38+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2013-03-23 3:52 UTC (permalink / raw) To: git Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier, Nguyễn Thái Ngọc Duy The current message is "bisecting %s" (or "bisecting branch %s"). "%s" is the current branch when we started bisecting. Clarify that to avoid confusion with good and bad refs passed to "bisect" command. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- builtin/branch.c | 2 +- t/t6030-bisect-porcelain.sh | 2 +- t/t7512-status-help.sh | 2 +- wt-status.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 99105f8..8f00203 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -562,7 +562,7 @@ static char *get_head_description(void) strbuf_addf(&desc, _("(no branch, rebasing %s)"), state.branch); else if (state.bisect_in_progress) - strbuf_addf(&desc, _("(no branch, bisecting %s)"), + strbuf_addf(&desc, _("(no branch, bisect started on %s)"), state.branch); else if (state.detached_from) strbuf_addf(&desc, _("(detached from %s)"), diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 9b6f0d0..2fce99a 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null && + test_i18ngrep "* (no branch, bisect started on other)" branch.output > /dev/null && test_cmp saved .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index 5adba4f..c35d01d 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -578,7 +578,7 @@ test_expect_success 'status when bisecting' ' TGT=$(git rev-parse --short two_bisect) && cat >expected <<-EOF && # HEAD detached at $TGT - # You are currently bisecting branch '\''bisect'\''. + # You are currently bisecting, started from branch '\''bisect'\''. # (use "git bisect reset" to get back to the original branch) # nothing to commit (use -u to show untracked files) diff --git a/wt-status.c b/wt-status.c index 32a51e1..cf3d81a 100644 --- a/wt-status.c +++ b/wt-status.c @@ -953,7 +953,7 @@ static void show_bisect_in_progress(struct wt_status *s, { if (state->branch) status_printf_ln(s, color, - _("You are currently bisecting branch '%s'."), + _("You are currently bisecting, started from branch '%s'."), state->branch); else status_printf_ln(s, color, -- 1.8.2.83.gc99314b ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH] status, branch: fix the misleading "bisecting" message 2013-03-23 3:52 ` [PATCH] status, branch: fix the misleading "bisecting" message Nguyễn Thái Ngọc Duy @ 2013-03-24 5:30 ` Junio C Hamano 0 siblings, 0 replies; 38+ messages in thread From: Junio C Hamano @ 2013-03-24 5:30 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Jonathan Niedier Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > The current message is "bisecting %s" (or "bisecting branch %s"). > "%s" is the current branch when we started bisecting. Clarify that to > avoid confusion with good and bad refs passed to "bisect" command. > > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> > --- Sounds sensible. Is this something we should squash in to nd/branch-show-rebase-bisect-state topic, or just apply it to the top (the latter is easier for me, but you may want to keep the history free of "oops, that was a bad idea" changes). Will queue on top, at least for now, as the topic is not in 'next'. Thanks. > builtin/branch.c | 2 +- > t/t6030-bisect-porcelain.sh | 2 +- > t/t7512-status-help.sh | 2 +- > wt-status.c | 2 +- > 4 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/builtin/branch.c b/builtin/branch.c > index 99105f8..8f00203 100644 > --- a/builtin/branch.c > +++ b/builtin/branch.c > @@ -562,7 +562,7 @@ static char *get_head_description(void) > strbuf_addf(&desc, _("(no branch, rebasing %s)"), > state.branch); > else if (state.bisect_in_progress) > - strbuf_addf(&desc, _("(no branch, bisecting %s)"), > + strbuf_addf(&desc, _("(no branch, bisect started on %s)"), > state.branch); > else if (state.detached_from) > strbuf_addf(&desc, _("(detached from %s)"), > diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh > index 9b6f0d0..2fce99a 100755 > --- a/t/t6030-bisect-porcelain.sh > +++ b/t/t6030-bisect-porcelain.sh > @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if > cp .git/BISECT_START saved && > test_must_fail git bisect start $HASH4 foo -- && > git branch > branch.output && > - test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null && > + test_i18ngrep "* (no branch, bisect started on other)" branch.output > /dev/null && > test_cmp saved .git/BISECT_START > ' > test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' > diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh > index 5adba4f..c35d01d 100755 > --- a/t/t7512-status-help.sh > +++ b/t/t7512-status-help.sh > @@ -578,7 +578,7 @@ test_expect_success 'status when bisecting' ' > TGT=$(git rev-parse --short two_bisect) && > cat >expected <<-EOF && > # HEAD detached at $TGT > - # You are currently bisecting branch '\''bisect'\''. > + # You are currently bisecting, started from branch '\''bisect'\''. > # (use "git bisect reset" to get back to the original branch) > # > nothing to commit (use -u to show untracked files) > diff --git a/wt-status.c b/wt-status.c > index 32a51e1..cf3d81a 100644 > --- a/wt-status.c > +++ b/wt-status.c > @@ -953,7 +953,7 @@ static void show_bisect_in_progress(struct wt_status *s, > { > if (state->branch) > status_printf_ln(s, color, > - _("You are currently bisecting branch '%s'."), > + _("You are currently bisecting, started from branch '%s'."), > state->branch); > else > status_printf_ln(s, color, ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2013-03-24 5:31 UTC | newest] Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-03-03 9:41 [PATCH 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 1/5] checkout: record full target ref in reflog Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 2/5] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 3/5] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy 2013-03-03 9:41 ` [PATCH 4/5] status: show the ref that is checked out, even if it's detached Nguyễn Thái Ngọc Duy 2013-03-03 22:25 ` Junio C Hamano 2013-03-04 12:17 ` Duy Nguyen 2013-03-04 15:49 ` Junio C Hamano 2013-03-05 11:39 ` Duy Nguyen 2013-03-05 12:18 ` Matthieu Moy 2013-03-03 9:41 ` [PATCH 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-03 22:28 ` Junio C Hamano 2013-03-06 12:21 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 1/4] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy 2013-03-06 18:48 ` Junio C Hamano 2013-03-06 23:53 ` Junio C Hamano 2013-03-06 12:21 ` [PATCH v2 2/4] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy 2013-03-06 12:21 ` [PATCH v2 3/4] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy 2013-03-06 19:16 ` Junio C Hamano 2013-03-08 11:04 ` Duy Nguyen 2013-03-08 21:46 ` Junio C Hamano 2013-03-06 12:21 ` [PATCH v2 4/4] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-06 12:26 ` [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-06 12:26 ` [PATCH v2+ 4/4] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 1/5] wt-status: move strbuf into read_and_strip_branch() Nguyễn Thái Ngọc Duy 2013-03-13 16:20 ` Junio C Hamano 2013-03-16 2:12 ` [PATCH v3+ " Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 2/5] wt-status: split wt_status_state parsing function out Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 3/5] wt-status: move wt_status_get_state() out to wt_status_print() Nguyễn Thái Ngọc Duy 2013-03-13 11:42 ` [PATCH v3 4/5] status: show more info than "currently not on any branch" Nguyễn Thái Ngọc Duy 2013-03-13 16:25 ` Junio C Hamano 2013-03-13 11:42 ` [PATCH v3 5/5] branch: show more information when HEAD is detached Nguyễn Thái Ngọc Duy 2013-03-19 18:37 ` [PATCH v3 0/5] nd/branch-show-rebase-bisect-state updates Junio C Hamano 2013-03-20 12:40 ` Duy Nguyen 2013-03-20 14:37 ` Junio C Hamano 2013-03-23 3:52 ` [PATCH] status, branch: fix the misleading "bisecting" message Nguyễn Thái Ngọc Duy 2013-03-24 5:30 ` Junio C Hamano
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).