`git show-branch --upstream` is equivalent to `git show-branch $(git for-each-ref refs/heads --format '%(refname:short)') $(git for-each-ref refs/heads --format '%(upstream:short)')` `git show-branch --upstream foo bar` is equivalent to `git show-branch foo bar $(git for-each-ref refs/heads/foo refs/heads/bar --format '%(upstream:short)')` Combined with --topics, it shows commits that are NOT on any of the upstream branches. Signed-off-by: Mike Hommey <mh@xxxxxxxxxxxx> --- Note that in the --topics --upstream case, when there are different upstreams branches involved, only the merge-base of all of them is shown. I'm not sure if it's desirable to show more. The output as it is works for my own use cases. Documentation/git-show-branch.txt | 6 ++++++ builtin/show-branch.c | 42 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index b91d4e5..fd29c8d 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -53,6 +53,10 @@ OPTIONS branch to the list of revs to be shown when it is not given on the command line. +--upstream:: + With this option, the command includes the upstream + branch of each rev to be shown. + --topo-order:: By default, the branches and their commits are shown in reverse chronological order. This option makes them @@ -102,6 +106,8 @@ OPTIONS --topics:: Shows only commits that are NOT on the first branch given. + When used with `--upstream`, shows only commits that are NOT + on any upstream branch. This helps track topic branches by hiding any commit that is already in the main line of development. When given "git show-branch --topics master topic1 topic2", this diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 270e39c..90e2ac3 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -4,9 +4,10 @@ #include "builtin.h" #include "color.h" #include "parse-options.h" +#include "remote.h" static const char* show_branch_usage[] = { - N_("git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color[=<when>] | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]"), + N_("git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--upstream] [--color[=<when>] | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]"), N_("git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"), NULL }; @@ -640,6 +641,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) int sha1_name = 0; int shown_merge_point = 0; int with_current_branch = 0; + int with_upstream_branches = 0; int head_at = -1; int topics = 0; int dense = 1; @@ -658,6 +660,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")), OPT_BOOL(0, "current", &with_current_branch, N_("include the current branch")), + OPT_BOOL(0, "upstream", &with_upstream_branches, + N_("include upstream branches")), OPT_BOOL(0, "sha1-name", &sha1_name, N_("name commits with their object names")), OPT_BOOL(0, "merge-base", &merge_base, @@ -848,7 +852,41 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) if (commit->object.flags == flag) commit_list_insert_by_date(commit, &list); rev[num_rev] = commit; + + if (with_upstream_branches) { + unsigned char branch_sha1[20]; + struct branch *branch; + int current_ref_name_cnt = ref_name_cnt; + + /* If this ref is already marked as an upstream, skip */ + if (topics & flag) + continue; + + branch = branch_get(ref_name[num_rev]); + + if (!branch || !branch->merge || !branch->merge[0] || + !branch->merge[0]->dst) + continue; + if (get_sha1(branch->merge[0]->dst, branch_sha1)) + continue; + append_remote_ref(branch->merge[0]->dst, branch_sha1, 0, 0); + /* If append_remote_ref didn't add a ref, it's either + * because it's an upstream of a previous ref, or because + * it was given on the command line. In neither case we + * want the bit being set. */ + if (topics && current_ref_name_cnt != ref_name_cnt) + topics |= 1u << (ref_name_cnt + REV_SHIFT - 1); + } else if (topics && num_rev == 0) { + topics |= flag; + } } + /* topics is filled above with a mask of refs corresponding to + * upstream branches, or the first given ref. It also still contains + * the original bool value, which may match some bookkeeping flags, + * so filter that out. + */ + topics &= ~0u << REV_SHIFT; + for (i = 0; i < num_rev; i++) rev_mask[i] = rev[i]->object.flags; @@ -925,7 +963,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) commit->parents->next); if (topics && !is_merge_point && - (this_flag & (1u << REV_SHIFT))) + (this_flag & topics)) continue; if (dense && is_merge && omit_in_dense(commit, rev, num_rev)) -- 2.2.1.4.g99d39fe.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html