# [PATCH] Show branch information in short output of git status

3 messages from 2010-05-25 to 2010-05-25. Participants: Michael J Gruber.
Thread: https://gitlist.dev/t/23900

## Michael J Gruber, 2010-05-25 13:45

Subject: [PATCH] Show branch information in short output of git status
Message-ID: <284d7af64fec2dc0cabdb5cf29ab3fd34fad79f0.1274794889.git.git@drmicha.warpmail.net>
URL: https://gitlist.dev/e/284d7af64fec2dc0cabdb5cf29ab3fd34fad79f0.1274794889.git.git%40drmicha.warpmail.net
In-Reply-To: <AANLkTinNYcuiyRpgMGpQAEaStj2MDg9UooozooLPwv_0@mail.gmail.com>

```
From: Daniel Knittl-Frank <knittl89+git@googlemail.com>

This patch adds a first line in the output of `git status -s` when given
the option `-b` or `--branch`, showing which branch the user is
currently on, and in case of tracking branches the number of commits on
each branch.

Signed-off-by: Daniel Knittl-Frank <knittl89+git@googlemail.com>
---
Sent by the not-so-atomatic mob-robot...
I noticed some white space issue but assume Junio fixes that automatically
when applying.

 builtin/commit.c |    8 ++++-
 wt-status.c      |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 wt-status.h      |    6 +++-
 3 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index ddf77e4..2328293 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -93,6 +93,7 @@ static enum {
 	STATUS_FORMAT_SHORT,
 	STATUS_FORMAT_PORCELAIN,
 } status_format = STATUS_FORMAT_LONG;
+static int status_show_branch;
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
@@ -134,6 +135,7 @@ static struct option builtin_commit_options[] = {
 	OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
 	OPT_SET_INT(0, "short", &status_format, "show status concisely",
 		    STATUS_FORMAT_SHORT),
+	OPT_BOOLEAN(0, "branch", &status_show_branch, "show branch information"),
 	OPT_SET_INT(0, "porcelain", &status_format,
 		    "show porcelain output format", STATUS_FORMAT_PORCELAIN),
 	OPT_BOOLEAN('z', "null", &null_termination,
@@ -424,7 +426,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
 
 	switch (status_format) {
 	case STATUS_FORMAT_SHORT:
-		wt_shortstatus_print(s, null_termination);
+		wt_shortstatus_print(s, null_termination, status_show_branch);
 		break;
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(s, null_termination);
@@ -1030,6 +1032,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 		OPT__VERBOSE(&verbose),
 		OPT_SET_INT('s', "short", &status_format,
 			    "show status concisely", STATUS_FORMAT_SHORT),
+		OPT_BOOLEAN('b', "branch", &status_show_branch,
+		            "show branch information"),
 		OPT_SET_INT(0, "porcelain", &status_format,
 			    "show porcelain output format",
 			    STATUS_FORMAT_PORCELAIN),
@@ -1082,7 +1086,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 
 	switch (status_format) {
 	case STATUS_FORMAT_SHORT:
-		wt_shortstatus_print(&s, null_termination);
+		wt_shortstatus_print(&s, null_termination, status_show_branch);
 		break;
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(&s, null_termination);
diff --git a/wt-status.c b/wt-status.c
index 14e0acc..871315a 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -9,6 +9,7 @@
 #include "quote.h"
 #include "run-command.h"
 #include "remote.h"
+#include "refs.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -17,6 +18,8 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_RED,    /* WT_STATUS_UNTRACKED */
 	GIT_COLOR_RED,    /* WT_STATUS_NOBRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_UNMERGED */
+	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
+	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -756,9 +759,70 @@ static void wt_shortstatus_other(int null_termination, struct string_list_item *
 	}
 }
 
-void wt_shortstatus_print(struct wt_status *s, int null_termination)
+static void wt_shortstatus_print_tracking(struct wt_status *s)
+{
+	struct branch *branch;
+	const char *header_color = color(WT_STATUS_HEADER, s);
+	const char *branch_color_local = color(WT_STATUS_LOCAL_BRANCH, s);
+	const char *branch_color_remote = color(WT_STATUS_REMOTE_BRANCH, s);
+
+	const char *base;
+	const char *branch_name;
+	int num_ours, num_theirs;
+
+	color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "## ");
+
+	if(!s->branch)
+		return;
+	branch_name = s->branch;
+
+	if (!prefixcmp(branch_name, "refs/heads/"))
+		branch_name += 11;
+	else if (!strcmp(branch_name, "HEAD")) {
+		branch_name = "HEAD (no branch)";
+		branch_color_local = color(WT_STATUS_NOBRANCH, s);
+	}
+
+	branch = branch_get(s->branch + 11);
+	if(s->is_initial) {
+		color_fprintf(s->fp, header_color, "Initial commit on ");
+	}
+	if (!stat_tracking_info(branch, &num_ours, &num_theirs)) {
+		color_fprintf_ln(s->fp, branch_color_local,
+			"%s", branch_name);
+		return;
+	}
+
+	base = branch->merge[0]->dst;
+	base = shorten_unambiguous_ref(base, 0);
+	color_fprintf(s->fp, branch_color_local, "%s", branch_name);
+	color_fprintf(s->fp, header_color, "...");
+	color_fprintf(s->fp, branch_color_remote, "%s", base);
+
+	color_fprintf(s->fp, header_color, " [");
+	if (!num_ours) {
+		color_fprintf(s->fp, header_color, "behind ");
+		color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
+	} else if (!num_theirs) {
+		color_fprintf(s->fp, header_color, "ahead ");
+		color_fprintf(s->fp, branch_color_local, "%d", num_ours);
+	} else {
+		color_fprintf(s->fp, header_color, "ahead ");
+		color_fprintf(s->fp, branch_color_local, "%d", num_ours);
+		color_fprintf(s->fp, header_color, ", behind ");
+		color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
+	}
+
+	color_fprintf_ln(s->fp, header_color, "]");
+}
+
+void wt_shortstatus_print(struct wt_status *s, int null_termination, int show_branch)
 {
 	int i;
+
+	if(show_branch)
+		wt_shortstatus_print_tracking(s);
+
 	for (i = 0; i < s->change.nr; i++) {
 		struct wt_status_change_data *d;
 		struct string_list_item *it;
@@ -789,5 +853,5 @@ void wt_porcelain_print(struct wt_status *s, int null_termination)
 	s->use_color = 0;
 	s->relative_paths = 0;
 	s->prefix = NULL;
-	wt_shortstatus_print(s, null_termination);
+	wt_shortstatus_print(s, null_termination, 0);
 }
diff --git a/wt-status.h b/wt-status.h
index 1093e65..4f19045 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -12,6 +12,8 @@ enum color_wt_status {
 	WT_STATUS_UNTRACKED,
 	WT_STATUS_NOBRANCH,
 	WT_STATUS_UNMERGED,
+	WT_STATUS_LOCAL_BRANCH,
+	WT_STATUS_REMOTE_BRANCH,
 };
 
 enum untracked_status_type {
@@ -43,7 +45,7 @@ struct wt_status {
 	int submodule_summary;
 	int show_ignored_files;
 	enum untracked_status_type show_untracked_files;
-	char color_palette[WT_STATUS_UNMERGED+1][COLOR_MAXLEN];
+	char color_palette[WT_STATUS_REMOTE_BRANCH+1][COLOR_MAXLEN];
 
 	/* These are computed during processing of the individual sections */
 	int commitable;
@@ -60,7 +62,7 @@ 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_shortstatus_print(struct wt_status *s, int null_termination);
+void wt_shortstatus_print(struct wt_status *s, int null_termination, int show_branch);
 void wt_porcelain_print(struct wt_status *s, int null_termination);
 
 #endif /* STATUS_H */
-- 
1.7.1.342.g1c280

```

## Michael J Gruber, 2010-05-25 14:03

Subject: Re: [PATCH] Show branch information in short output of git status
Message-ID: <4BFBD8A3.8040203@drmicha.warpmail.net>
URL: https://gitlist.dev/e/4BFBD8A3.8040203%40drmicha.warpmail.net
In-Reply-To: <284d7af64fec2dc0cabdb5cf29ab3fd34fad79f0.1274794889.git.git@drmicha.warpmail.net>

```
> From: Daniel Knittl-Frank <knittl89+git@googlemail.com>
> 
> This patch adds a first line in the output of `git status -s` when given
> the option `-b` or `--branch`, showing which branch the user is
> currently on, and in case of tracking branches the number of commits on
> each branch.
> 
> Signed-off-by: Daniel Knittl-Frank <knittl89+git@googlemail.com>
> ---
> Sent by the not-so-atomatic mob-robot...

...with the not so automagic spell-checker...

> I noticed some white space issue but assume Junio fixes that automatically
> when applying.
> 
>  builtin/commit.c |    8 ++++-
>  wt-status.c      |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  wt-status.h      |    6 +++-
>  3 files changed, 76 insertions(+), 6 deletions(-)

I tried it and I like it! [Ordinary status could use the same colors for
tracking info, they're helpful.]

I also like the fact that --porcelain -b does what it should (unchanged
by the patch).

I'm wondering what "git status -b" should do. Currently, "-b" is ignored
silently. One may argue it's okay since ordinary status shows tracking
info anyways.

Michael

```

## Michael J Gruber, 2010-05-25 14:52

Subject: [PATCH] Documentation+t5708: document and test status -s -b
Message-ID: <d007399dfec8e1346f6b3ba5d1f34469026fb90f.1274798738.git.git@drmicha.warpmail.net>
URL: https://gitlist.dev/e/d007399dfec8e1346f6b3ba5d1f34469026fb90f.1274798738.git.git%40drmicha.warpmail.net
In-Reply-To: <4BFBD8A3.8040203@drmicha.warpmail.net>

```
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
---
Since I liked -b so much...
Cheers!

 Documentation/git-status.txt |   12 +++++++++-
 t/t7508-status.sh            |   47 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 2d4bbfc..beb1c8a 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -27,6 +27,10 @@ OPTIONS
 --short::
 	Give the output in the short-format.
 
+-b::
+--branch::
+	Show the branch and tracking info even in short-format.
+
 --porcelain::
 	Give the output in a stable, easy-to-parse format for scripts.
 	Currently this is identical to --short output, but is guaranteed
@@ -73,7 +77,7 @@ In short-format, the status of each path is shown as
 where `PATH1` is the path in the `HEAD`, and ` -> PATH2` part is
 shown only when `PATH1` corresponds to a different path in the
 index/worktree (i.e. the file is renamed). The 'XY' is a two-letter
-status code.
+status code. 
 
 The fields (including the `->`) are separated from each other by a
 single space. If a filename contains whitespace or other nonprintable
@@ -120,6 +124,10 @@ Ignored files are not listed.
     ?           ?    untracked
     -------------------------------------------------
 
+If -b is used the short-format status is preceded by a line
+
+## branchname tracking info
+
 There is an alternate -z format recommended for machine parsing.  In
 that format, the status field is the same, but some other things
 change.  First, the '->' is omitted from rename entries and the field
@@ -128,7 +136,7 @@ order is reversed (e.g 'from -> to' becomes 'to from'). Second, a NUL
 and the terminating newline (but a space still separates the status
 field from the first filename).  Third, filenames containing special
 characters are not specially formatted; no quoting or
-backslash-escaping is performed.
+backslash-escaping is performed. Fourth, there is no branch line.
 
 CONFIGURATION
 -------------
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 008d571..9e08107 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -107,13 +107,32 @@ A  dir2/added
 ?? untracked
 EOF
 
-test_expect_success 'status -s (2)' '
+test_expect_success 'status -s' '
 
 	git status -s >output &&
 	test_cmp expect output
 
 '
 
+cat >expect <<\EOF
+## master
+ M dir1/modified
+A  dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status -s -b' '
+
+	git status -s -b >output &&
+	test_cmp expect output
+
+'
+
 cat >expect <<EOF
 # On branch master
 # Changes to be committed:
@@ -437,6 +456,25 @@ test_expect_success 'status -s with color.status' '
 '
 
 cat >expect <<\EOF
+## <GREEN>master<RESET>
+ <RED>M<RESET> dir1/modified
+<GREEN>A<RESET>  dir2/added
+<BLUE>??<RESET> dir1/untracked
+<BLUE>??<RESET> dir2/modified
+<BLUE>??<RESET> dir2/untracked
+<BLUE>??<RESET> expect
+<BLUE>??<RESET> output
+<BLUE>??<RESET> untracked
+EOF
+
+test_expect_success 'status -s -b with color.status' '
+
+	git status -s -b | test_decode_color >output &&
+	test_cmp expect output
+
+'
+
+cat >expect <<\EOF
  M dir1/modified
 A  dir2/added
 ?? dir1/untracked
@@ -469,6 +507,13 @@ test_expect_success 'status --porcelain ignores color.status' '
 git config --unset color.status
 git config --unset color.ui
 
+test_expect_success 'status --porcelain ignores -b' '
+
+	git status --porcelain -b >output &&
+	test_cmp expect output
+
+'
+
 cat >expect <<\EOF
 # On branch master
 # Changes to be committed:
-- 
1.7.1.342.g1c280

```
