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 <dani...@umanovskis.se>
---
 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", &copy, N_("copy a branch and its reflog"), 
1),
                OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target 
exists"), 2),
                OPT_BOOL('l', "list", &list, N_("list branch names")),
+               OPT_BOOL(0, "current", &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")),
@@ -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 <<EOF &&
 * (HEAD detached at $(git rev-parse --short HEAD^0))
-- 
2.19.1.274.g059d67db4.dirty

Reply via email to