[PATCH v5] branch: introduce --show-current display option
When called with --show-current, git branch will print the current branch name and terminate. Only the actual name gets printed, without refs/heads. In detached HEAD state, nothing is output. Intended both for scripting and interactive/informative use. Unlike git branch --list, no filtering is needed to just get the branch name. Signed-off-by: Daniels Umanovskis --- Submitting v5 now that a week has passed since latest maintainer comments. This is basically v4 but with small fixes to the test, as proposed by Junio on pu, and additionally replacing a subshell with { .. } since Dscho and Eric discovered the negative performance effects of subshell invocations. Documentation/git-branch.txt | 6 - builtin/branch.c | 25 ++-- t/t3203-branch-output.sh | 44 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bf5316ffa9..0babb9b1be 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -9,7 +9,7 @@ SYNOPSIS [verse] 'git branch' [--color[=] | --no-color] [-r | -a] - [--list] [-v [--abbrev= | --no-abbrev]] + [--list] [--show-current] [-v [--abbrev= | --no-abbrev]] [--column[=] | --no-column] [--sort=] [(--merged | --no-merged) []] [--contains []] @@ -160,6 +160,10 @@ This option is only applicable in non-verbose mode. branch --list 'maint-*'`, list only the branches that match the pattern(s). +--show-current:: + Print the name of the current branch. In detached HEAD state, + nothing is printed. + -v:: -vv:: --verbose:: diff --git a/builtin/branch.c b/builtin/branch.c index c396c41533..46f91dc06d 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -443,6 +443,21 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin free(to_free); } +static void print_current_branch_name(void) +{ + int flags; + const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags); + const char *shortname; + if (!refname) + die(_("could not resolve HEAD")); + else if (!(flags & REF_ISSYMREF)) + return; + else if (skip_prefix(refname, "refs/heads/", &shortname)) + puts(shortname); + else + die(_("HEAD (%s) points outside of refs/heads/"), refname); +} + static void reject_rebase_or_bisect_branch(const char *target) { struct worktree **worktrees = get_worktrees(0); @@ -581,6 +596,7 @@ static int edit_branch_description(const char *branch_name) int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, copy = 0, force = 0, list = 0; + int show_current = 0; int reflog = 0, edit_description = 0; int quiet = 0, unset_upstream = 0; const char *new_upstream = NULL; @@ -620,6 +636,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BIT('c', "copy", ©, N_("copy a branch and its reflog"), 1), OPT_BIT('C', NULL, ©, N_("copy a branch, even if target exists"), 2), OPT_BOOL('l', "list", &list, N_("list branch names")), + OPT_BOOL(0, "show-current", &show_current, N_("show current branch name")), OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")), OPT_BOOL(0, "edit-description", &edit_description, N_("edit the description for the branch")), @@ -662,14 +679,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_branch_usage, 0); - if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0) + if (!delete && !rename && !copy && !edit_description && !new_upstream && + !show_current && !unset_upstream && argc == 0) list = 1; if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr || filter.no_commit) list = 1; - if (!!delete + !!rename + !!copy + !!new_upstream + + if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current + list + unset_upstream > 1) usage_with_options(builtin_branch_usage, options); @@ -697,6 +715,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) die(_("branch n
[PATCH 0/2] branch: introduce --current display option
I often find myself needing the current branch name, for which currently there's git rev-parse --abrev-ref HEAD. I would expect `git branch` to have an option to output the branch name instead. This is my first patch to Git, so process-related comments (patch formatting, et cetera) are quite welcome. Daniels Umanovskis (2): branch: introduce --current display option doc/git-branch: Document the --current option Documentation/git-branch.txt | 6 +- builtin/branch.c | 16 t/t3203-branch-output.sh | 18 ++ 3 files changed, 39 insertions(+), 1 deletion(-) -- 2.19.1.272.gf84b9b09d.dirty
[PATCH 1/2] branch: introduce --current display option
When called with --current, git branch will print the current branch name and terminate. It will print HEAD in detached-head state. Rationale: finding out the current branch is useful interactively, but especially in scripting. git branch --list prints many branches, and prepends the current one with an asterisk, meaning sed or other filtering is necessary to just get the current branch. git rev-parse --abbrev-ref HEAD is the current way to achieve this output, but that is not intuitive or easy to understand. Signed-off-by: Daniels Umanovskis --- builtin/branch.c | 17 + t/t3203-branch-output.sh | 18 ++ 2 files changed, 35 insertions(+) diff --git a/builtin/branch.c b/builtin/branch.c index c396c4153..e4c6b0490 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -443,6 +443,18 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin free(to_free); } +static void print_current_branch_name() +{ + struct strbuf out = STRBUF_INIT; + const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL); + char *shortname = shorten_unambiguous_ref(refname, 0); + strbuf_addf(&out, _("%s"), shortname); + fwrite(out.buf, 1, out.len, stdout); + putchar('\n'); + free(shortname); + strbuf_release(&out); +} + static void reject_rebase_or_bisect_branch(const char *target) { struct worktree **worktrees = get_worktrees(0); @@ -581,6 +593,7 @@ static int edit_branch_description(const char *branch_name) int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, copy = 0, force = 0, list = 0; + int current = 0; int reflog = 0, edit_description = 0; int quiet = 0, unset_upstream = 0; const char *new_upstream = NULL; @@ -620,6 +633,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BIT('c', "copy", ©, N_("copy a branch and its reflog"), 1), OPT_BIT('C', NULL, ©, N_("copy a branch, even if target exists"), 2), OPT_BOOL('l', "list", &list, N_("list branch names")), + OPT_BOOL(0, "current", ¤t, N_("show current branch name")), OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")), OPT_BOOL(0, "edit-description", &edit_description, N_("edit the description for the branch")), @@ -697,6 +711,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) die(_("branch name required")); return delete_branches(argc, argv, delete > 1, filter.kind, quiet); + } else if (current) { + print_current_branch_name(); + return 0; } else if (list) { /* git branch --local also shows HEAD when it is detached */ if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached) diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index ee6787614..396d81568 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -100,6 +100,24 @@ test_expect_success 'git branch -v pattern does not show branch summaries' ' test_must_fail git branch -v branch* ' +test_expect_success 'git branch `--current` shows current branch' ' + cat >expect <<-\EOF && + branch-two + EOF +git checkout branch-two && + git branch --current >actual && + test_cmp expect actual +' + +test_expect_success 'git branch `--current` shows detached HEAD properly' ' + cat >expect <<-\EOF && + HEAD + EOF +git checkout HEAD^0 && + git branch --current >actual && + test_cmp expect actual +' + test_expect_success 'git branch shows detached HEAD properly' ' cat >expect <
[PATCH 2/2] doc/git-branch: Document the --current option
Signed-off-by: Daniels Umanovskis --- Documentation/git-branch.txt | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bf5316ffa..a7167df74 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -9,7 +9,7 @@ SYNOPSIS [verse] 'git branch' [--color[=] | --no-color] [-r | -a] - [--list] [-v [--abbrev= | --no-abbrev]] + [--list] [--current] [-v [--abbrev= | --no-abbrev]] [--column[=] | --no-column] [--sort=] [(--merged | --no-merged) []] [--contains []] @@ -160,6 +160,10 @@ This option is only applicable in non-verbose mode. branch --list 'maint-*'`, list only the branches that match the pattern(s). +--current:: + Print the name of the current branch. In detached HEAD state, + or if otherwise impossible to resolve the branch name, print + "HEAD". -v:: -vv:: --verbose:: -- 2.19.1.274.g059d67db4.dirty
Re: [PATCH 1/2] branch: introduce --current display option
Thanks for the feedback! On 10/9/18 9:54 PM, Stefan Beller wrote: > How does it play with worktrees? (I would expect it to just work as expected: > each worktree would print its current branch, but a test might help?) I'll see about writing a test for that. I've never used git-worktree so this is a good chance to learn. > Git used to have (and still has) the approach of dividing its commands > into high level ("porcelain") commands and low level ("plumbing") commands, > with the porcelain facing the user and plumbing being good for scripting. > > This patch proposes a radically different approach, which is convenience > of use. Right - a couple of points in response. First, it strikes me that "print current branch" is one of those things that are both for scripting and for normal/interactive use. Much like the entirety of git-status, which is very used by itself, and also in scripts with --porcelain. Current branch is often used in things like your shell prompt, vim statusline, etc, as well as scripts. The amount of upvotes on the stackoverflow question "how to get the current branch name in git?" illustrates my point :) Second, it seems arguable whether `git ref-parse` is guaranteed to be scripting-safe, it's not actually a plumbing command, at least if we trust the main git manpage, which lists git-rev-parse as porcelain anyway. > Why do we need to add the shortname to a strbuf? > (and using _( ) that denotes the string should be translated?) > I would think we could just > > puts(shortname) > > here and leave out all the strbuf out ? > Of course, has to be changed for v2. Pitfalls of learning the code from just its surroundings, didn't realize that the underscores are for i18n.
Re: [PATCH 0/2] branch: introduce --current display option
On 10/10/18 5:03 PM, Ævar Arnfjörð Bjarmason wrote: > > I'm mildly negative on this because git-rev-parse is plumbing, but > git-branch is porcelain [..] > > We also list git-rev-parse as porcelain, just under "Porcelain / Ancillary > Commands / Interrogators". > > Should we just move it to plumbing? I don't know. >From my perspective as a Git user, not developer, git-rev-parse is between plumbing and porcelain, but much more plumbing. It's listed as porcelain but is connected to the plumbing git-rev-list, and for the most part it does things incomprehensible without understanding Git internals. Then it also has a bunch of options that are very useful in scripts but unrelated to revisions, here I mean --git-dir or --is-inside-work-tree. I'd be happy to submit a documentation patch for discussion that formally moves rev-parse to plumbing. > Also, as much as our current scripting interface can be very confusing > (you might not think "get current branch" is under rev-parse), I can't > help but think that adding two different ways to spew out the exact same > thing to two different commands is heading in the wrong > direction. Agreed, so I'm very much inclined to move forward with Junio's preferred solution on this, which would also act differently by only outputting the branch when you're really on a branch, and being silent in e.g. detached HEAD.
[PATCH v2 0/1] branch: introduce --show-current display option
v2 reroll of a previously-discussed patch. Thanks to everyone for their comments. Based on feedback: 1. Command is now a verb: git branch --show-current. 2. Changed to gitster's suggested implementation: nothing is printed if HEAD does not point to a symbolic ref. A fatal error if HEAD is a symbolic ref but does not start with refs/heads/. 3. Added a test to show this works with worktrees A process question to the list. The patch adds a new localizable string that gets output in case of repository corruption. I happen to speak a couple of the languages that have po files. Is it accepted practice to also include po edits in my patch in such a case, or should that be left to the regular l10n workflow? Daniels Umanovskis (1): branch: introduce --show-current display option Documentation/git-branch.txt | 6 +- builtin/branch.c | 21 -- t/t3203-branch-output.sh | 41 3 files changed, 65 insertions(+), 3 deletions(-) -- 2.19.1.330.g93276587c.dirty
[PATCH v2 1/1] branch: introduce --show-current display option
When called with --show-current, git branch will print the current branch name and terminate. Only the actual name gets printed, without refs/heads. In detached HEAD state, nothing is output. Intended both for scripting and interactive/informative use. Unlike git branch --list, no filtering is needed to just get the branch name. Signed-off-by: Daniels Umanovskis --- Documentation/git-branch.txt | 6 +- builtin/branch.c | 21 -- t/t3203-branch-output.sh | 41 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bf5316ffa..0babb9b1b 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -9,7 +9,7 @@ SYNOPSIS [verse] 'git branch' [--color[=] | --no-color] [-r | -a] - [--list] [-v [--abbrev= | --no-abbrev]] + [--list] [--show-current] [-v [--abbrev= | --no-abbrev]] [--column[=] | --no-column] [--sort=] [(--merged | --no-merged) []] [--contains []] @@ -160,6 +160,10 @@ This option is only applicable in non-verbose mode. branch --list 'maint-*'`, list only the branches that match the pattern(s). +--show-current:: + Print the name of the current branch. In detached HEAD state, + nothing is printed. + -v:: -vv:: --verbose:: diff --git a/builtin/branch.c b/builtin/branch.c index c396c4153..ab03073b2 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -443,6 +443,17 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin free(to_free); } +static void print_current_branch_name() +{ + const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL); + const char *shortname; + if (refname == NULL || !strcmp(refname, "HEAD")) + return; + if (!skip_prefix(refname, "refs/heads/", &shortname)) + die(_("unexpected symbolic ref for HEAD: %s"), refname); + puts(shortname); +} + static void reject_rebase_or_bisect_branch(const char *target) { struct worktree **worktrees = get_worktrees(0); @@ -581,6 +592,7 @@ static int edit_branch_description(const char *branch_name) int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, copy = 0, force = 0, list = 0; + int show_current = 0; int reflog = 0, edit_description = 0; int quiet = 0, unset_upstream = 0; const char *new_upstream = NULL; @@ -620,6 +632,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BIT('c', "copy", ©, N_("copy a branch and its reflog"), 1), OPT_BIT('C', NULL, ©, N_("copy a branch, even if target exists"), 2), OPT_BOOL('l', "list", &list, N_("list branch names")), + OPT_BOOL(0, "show-current", &show_current, N_("show current branch name")), OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")), OPT_BOOL(0, "edit-description", &edit_description, N_("edit the description for the branch")), @@ -662,14 +675,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_branch_usage, 0); - if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0) + if (!delete && !rename && !copy && !edit_description && !new_upstream && + !show_current && !unset_upstream && argc == 0) list = 1; if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr || filter.no_commit) list = 1; - if (!!delete + !!rename + !!copy + !!new_upstream + + if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current + list + unset_upstream > 1) usage_with_options(builtin_branch_usage, options); @@ -697,6 +711,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) die(_("branch name required")); return delete_branches(argc, argv, delete > 1, filter.kind, quiet); + } else if (show_current) { + print_current_branch_name(); + return 0; } else if (list) { /* git branch --local also shows HEAD when it is detached */ if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached) diff --git a/t/t3203-br
[PATCH] doc: move git-rev-parse from porcelain to plumbing
git-rev-parse mostly seems like plumbing, and is more usd in scripts than in regular use. Online it's often mentioned as a plumbing command. Nonetheless it's listed under porcelain interrogators in `man git`. It seems appropriate to formally move git-rev-parse to plumbing interrogators. Signed-off-by: Daniels Umanovskis --- command-list.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command-list.txt b/command-list.txt index c36ea3c18..e6364e167 100644 --- a/command-list.txt +++ b/command-list.txt @@ -153,7 +153,7 @@ git-rerere ancillaryinterrogators git-reset mainporcelain worktree git-revert mainporcelain git-rev-listplumbinginterrogators -git-rev-parse ancillaryinterrogators +git-rev-parse plumbinginterrogators git-rm mainporcelain worktree git-send-email foreignscminterface complete git-send-pack synchingrepositories -- 2.19.1.330.g93276587c.dirty
Re: [PATCH] doc: move git-rev-parse from porcelain to plumbing
On 10/11/18 12:26 AM, Junio C Hamano wrote: > Among the remaining ones in the list, cherry and get-tar-commit-id > are probably better classified as plumbing. I do not know why > cherry is marked for completion; perhaps some crazy people use that > on the command line? I think cherry could go either way, get-tar-commit-id is definitely plumbing. Would you like me to fix those two on the same patch then?
Re: [PATCH v2 1/1] branch: introduce --show-current display option
On 10/11/18 5:43 PM, Rafael Ascensão wrote: > I agree it feels a bit out of place, and still think that > > $ git branch --list HEAD > > would be a good candidate to be taught how to print the current branch. I am not a fan because it would be yet another inconsistency in the Git command interface. An argument given after git branch --list means a pattern for the branches to list. Making HEAD print the current branch would be an exception to what an argument in that place means. Yes, HEAD itself is a very special string in git, but I'm not a fan of syntax where a specific argument value does something very different from any other value in that place.
Re: [PATCH v2 1/1] branch: introduce --show-current display option
On 10/11/18 8:54 AM, Junio C Hamano wrote: > Is it a normal situation to have refname==NULL, or is it something > worth reporting as an error? Looks like that would be in the case of looping symrefs or file backend failure, so seems a good idea to die() in that case. > Without passing the &flag argument, I do not think there is a > reliable way to ask resolve_ref_unsafe() if "HEAD" is a symbolic > ref. If I'm reading the code correctly, resolve_ref_unsafe() will return "HEAD" or NULL if there's no symbolic reference, so anything else would indicate a symref, but even in that case checking the flag explicitly is definitely better to clearly show intent. Will soon reply with v3 cleaning up the suggested patch accordingly.
[PATCH] doc: move git-cherry to plumbing
Also remove git-cherry from Bash completion because plumbing commands do not belong there. Signed-off-by: Daniels Umanovskis --- Up to discussion whether cherry should be considered plumbing. I lean towards considering it a rarely-used porcelain command, but a case could be made either way so let's see what the list thinks. command-list.txt | 2 +- contrib/completion/git-completion.bash | 11 --- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/command-list.txt b/command-list.txt index c36ea3c18..bdca6e3d3 100644 --- a/command-list.txt +++ b/command-list.txt @@ -62,7 +62,7 @@ git-check-mailmap purehelpers git-checkoutmainporcelain history git-checkout-index plumbingmanipulators git-check-ref-formatpurehelpers -git-cherry ancillaryinterrogators complete +git-cherry plumbinginterrogators complete git-cherry-pick mainporcelain git-citool mainporcelain git-clean mainporcelain diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index d63d2dffd..12f7ce0c5 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1340,17 +1340,6 @@ _git_checkout () esac } -_git_cherry () -{ - case "$cur" in - --*) - __gitcomp_builtin cherry - return - esac - - __git_complete_refs -} - __git_cherry_pick_inprogress_options="--continue --quit --abort" _git_cherry_pick () -- 2.19.1.330.g93276587c.dirty
[PATCH] doc: move git-get-tar-commit-id to plumbing
This is definitely a low-level command, it's hard to argue against it belonging in plumbing. Signed-off-by: Daniels Umanovskis --- command-list.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command-list.txt b/command-list.txt index c36ea3c18..966705358 100644 --- a/command-list.txt +++ b/command-list.txt @@ -96,7 +96,7 @@ git-for-each-refplumbinginterrogators git-format-patchmainporcelain git-fsckancillaryinterrogators complete git-gc mainporcelain -git-get-tar-commit-id ancillaryinterrogators +git-get-tar-commit-id plumbinginterrogators git-grepmainporcelain info git-gui mainporcelain git-hash-object plumbingmanipulators -- 2.19.1.330.g93276587c.dirty
Re: [PATCH v2 1/1] branch: introduce --show-current display option
On 10/11/18 10:35 PM, Rafael Ascensão wrote: > The output of the proposed command is also a bit inconsistent with the > usual output given by git branch, specifically the space alignment on > the left, color and * marker. The proposed command therefore takes a new switch. It's definitely not perfect, but doesn't give the existing --list new and different behavior. > At this stage it's closer to what I would expect from > $git rev-parse --abbrev-ref HEAD; The proposal is largely to have similar output to that command, yes. I expect that "show current branch" is something that's available in the branch command, even completely disregarding questions of whether it's API stable, etc.
[PATCH v3] branch: introduce --show-current display option
When called with --show-current, git branch will print the current branch name and terminate. Only the actual name gets printed, without refs/heads. In detached HEAD state, nothing is output. Intended both for scripting and interactive/informative use. Unlike git branch --list, no filtering is needed to just get the branch name. Signed-off-by: Daniels Umanovskis --- Cleaned up per suggestions, explicitly passing flags to clearly denote intent. If you consider the patch good conceptually, this implementation should hopefully be good enough to include. Documentation/git-branch.txt | 6 +- builtin/branch.c | 25 -- t/t3203-branch-output.sh | 41 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bf5316ffa..0babb9b1b 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -9,7 +9,7 @@ SYNOPSIS [verse] 'git branch' [--color[=] | --no-color] [-r | -a] - [--list] [-v [--abbrev= | --no-abbrev]] + [--list] [--show-current] [-v [--abbrev= | --no-abbrev]] [--column[=] | --no-column] [--sort=] [(--merged | --no-merged) []] [--contains []] @@ -160,6 +160,10 @@ This option is only applicable in non-verbose mode. branch --list 'maint-*'`, list only the branches that match the pattern(s). +--show-current:: + Print the name of the current branch. In detached HEAD state, + nothing is printed. + -v:: -vv:: --verbose:: diff --git a/builtin/branch.c b/builtin/branch.c index c396c4153..46f91dc06 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -443,6 +443,21 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin free(to_free); } +static void print_current_branch_name(void) +{ + int flags; + const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags); + const char *shortname; + if (!refname) + die(_("could not resolve HEAD")); + else if (!(flags & REF_ISSYMREF)) + return; + else if (skip_prefix(refname, "refs/heads/", &shortname)) + puts(shortname); + else + die(_("HEAD (%s) points outside of refs/heads/"), refname); +} + static void reject_rebase_or_bisect_branch(const char *target) { struct worktree **worktrees = get_worktrees(0); @@ -581,6 +596,7 @@ static int edit_branch_description(const char *branch_name) int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, copy = 0, force = 0, list = 0; + int show_current = 0; int reflog = 0, edit_description = 0; int quiet = 0, unset_upstream = 0; const char *new_upstream = NULL; @@ -620,6 +636,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BIT('c', "copy", ©, N_("copy a branch and its reflog"), 1), OPT_BIT('C', NULL, ©, N_("copy a branch, even if target exists"), 2), OPT_BOOL('l', "list", &list, N_("list branch names")), + OPT_BOOL(0, "show-current", &show_current, N_("show current branch name")), OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")), OPT_BOOL(0, "edit-description", &edit_description, N_("edit the description for the branch")), @@ -662,14 +679,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_branch_usage, 0); - if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0) + if (!delete && !rename && !copy && !edit_description && !new_upstream && + !show_current && !unset_upstream && argc == 0) list = 1; if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr || filter.no_commit) list = 1; - if (!!delete + !!rename + !!copy + !!new_upstream + + if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current + list + unset_upstream > 1) usage_with_options(builtin_branch_usage, options); @@ -697,6 +715,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) die(_("branch name required")); return delete_branches(argc, argv, delete > 1, filter.kind, quiet); +
Re: [PATCH v2 1/1] branch: introduce --show-current display option
On 10/12/18 12:56 AM, SZEDER Gábor wrote: > Ah, OK, just noticed v3 which has already fixed this. > Yeah - squashed the wrong commits locally for v2. Thanks for pointing this out anyway!
Re: [PATCH v3] branch: introduce --show-current display option
On 10/12/18 1:15 AM, Junio C Hamano wrote: > It is a bit curious why you remove the branch but not the tag after > this test. [..] > > So two equally valid choices are to remove "branch -d" and then > either: > > (1) leave both branch and tag after this test in the test > repository > > (2) use test_when_finished [..] Thanks for this explanation! You're right, I removed the branch because it otherwise breaks subsequent tests, while the tag doesn't matter. I'll go take a look at how test_when_finished can be used. > Please do *not* cd around without being in a subshell. Understood, thanks for explaining this as well.
[PATCH v4] branch: introduce --show-current display option
When called with --show-current, git branch will print the current branch name and terminate. Only the actual name gets printed, without refs/heads. In detached HEAD state, nothing is output. Intended both for scripting and interactive/informative use. Unlike git branch --list, no filtering is needed to just get the branch name. Signed-off-by: Daniels Umanovskis --- Compared to v3, fixed up test cases according to Junio's input Documentation/git-branch.txt | 6 +- builtin/branch.c | 25 +++-- t/t3203-branch-output.sh | 43 +++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bf5316ffa..0babb9b1b 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -9,7 +9,7 @@ SYNOPSIS [verse] 'git branch' [--color[=] | --no-color] [-r | -a] - [--list] [-v [--abbrev= | --no-abbrev]] + [--list] [--show-current] [-v [--abbrev= | --no-abbrev]] [--column[=] | --no-column] [--sort=] [(--merged | --no-merged) []] [--contains []] @@ -160,6 +160,10 @@ This option is only applicable in non-verbose mode. branch --list 'maint-*'`, list only the branches that match the pattern(s). +--show-current:: + Print the name of the current branch. In detached HEAD state, + nothing is printed. + -v:: -vv:: --verbose:: diff --git a/builtin/branch.c b/builtin/branch.c index c396c4153..46f91dc06 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -443,6 +443,21 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin free(to_free); } +static void print_current_branch_name(void) +{ + int flags; + const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags); + const char *shortname; + if (!refname) + die(_("could not resolve HEAD")); + else if (!(flags & REF_ISSYMREF)) + return; + else if (skip_prefix(refname, "refs/heads/", &shortname)) + puts(shortname); + else + die(_("HEAD (%s) points outside of refs/heads/"), refname); +} + static void reject_rebase_or_bisect_branch(const char *target) { struct worktree **worktrees = get_worktrees(0); @@ -581,6 +596,7 @@ static int edit_branch_description(const char *branch_name) int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, copy = 0, force = 0, list = 0; + int show_current = 0; int reflog = 0, edit_description = 0; int quiet = 0, unset_upstream = 0; const char *new_upstream = NULL; @@ -620,6 +636,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BIT('c', "copy", ©, N_("copy a branch and its reflog"), 1), OPT_BIT('C', NULL, ©, N_("copy a branch, even if target exists"), 2), OPT_BOOL('l', "list", &list, N_("list branch names")), + OPT_BOOL(0, "show-current", &show_current, N_("show current branch name")), OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")), OPT_BOOL(0, "edit-description", &edit_description, N_("edit the description for the branch")), @@ -662,14 +679,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_branch_usage, 0); - if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0) + if (!delete && !rename && !copy && !edit_description && !new_upstream && + !show_current && !unset_upstream && argc == 0) list = 1; if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr || filter.no_commit) list = 1; - if (!!delete + !!rename + !!copy + !!new_upstream + + if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current + list + unset_upstream > 1) usage_with_options(builtin_branch_usage, options); @@ -697,6 +715,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) die(_("branch name required")); return delete_branches(argc, argv, delete > 1, filter.kind, quiet); + } else if (show_current) { + print_current_branch_name(); + return 0;
Re: [PATCH v4] branch: introduce --show-current display option
On 10/17/18 11:39 AM, Rafael Ascensão wrote: > On Fri, Oct 12, 2018 at 03:33:21PM +0200, Daniels Umanovskis wrote: >> Intended both for scripting and interactive/informative use. >> Unlike git branch --list, no filtering is needed to just get the >> branch name. > > Are we going forward with advertising this as a scriptable alternative? That's probably up to the maintainers, but I would not explicitly point it out as a script command, so my patch doesn't mention scripting use in the documentation for it. In reality it's useful for "soft scripting" like setting the shell $PS1, which doesn't require API stability guarantees the way proper scripts do.