From: Junio C Hamano Date: Tue, 15 Jul 2008 06:47:01 +0000 (-0700) Subject: Merge branch 'jc/branch-merged' X-Git-Tag: v1.6.0-rc0~66 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b773fc34a0425790db7fe7c6a2d02d742ff41081?ds=inline;hp=-c Merge branch 'jc/branch-merged' * jc/branch-merged: branch --merged/--no-merged: allow specifying arbitrary commit branch --contains: default to HEAD parse-options: add PARSE_OPT_LASTARG_DEFAULT flag Conflicts: Documentation/git-branch.txt --- b773fc34a0425790db7fe7c6a2d02d742ff41081 diff --combined Documentation/git-branch.txt index b3e62ed011,450f90368f..fc5a4a602f --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@@ -8,24 -8,27 +8,27 @@@ git-branch - List, create, or delete br SYNOPSIS -------- [verse] - 'git branch' [--color | --no-color] [-r | -a] [--merged | --no-merged] - [-v [--abbrev= | --no-abbrev]] - [--contains ] -'git-branch' [--color | --no-color] [-r | -a] ++'git branch' [--color | --no-color] [-r | -a] + [-v [--abbrev= | --no-abbrev]] + [(--merged | --no-merged | --contains) []] -'git-branch' [--track | --no-track] [-l] [-f] [] -'git-branch' (-m | -M) [] -'git-branch' (-d | -D) [-r] ... +'git branch' [--track | --no-track] [-l] [-f] [] +'git branch' (-m | -M) [] +'git branch' (-d | -D) [-r] ... DESCRIPTION ----------- - With no arguments given a list of existing branches - will be shown, the current branch will be highlighted with an asterisk. - Option `-r` causes the remote-tracking branches to be listed, - and option `-a` shows both. - With `--contains `, shows only the branches that - contains the named commit (in other words, the branches whose - tip commits are descendant of the named commit). - With `--merged`, only branches merged into HEAD will be listed, and - with `--no-merged` only branches not merged into HEAD will be listed. + + With no arguments, existing branches are listed, the current branch will + be highlighted with an asterisk. Option `-r` causes the remote-tracking + branches to be listed, and option `-a` shows both. + + With `--contains`, shows only the branches that contains the named commit + (in other words, the branches whose tip commits are descendant of the + named commit). With `--merged`, only branches merged into the named + commit (i.e. the branches whose tip commits are reachable from the named + commit) will be listed. With `--no-merged` only branches not merged into + the named commit will be listed. Missing argument defaults to + 'HEAD' (i.e. the tip of the current branch). In its second form, a new branch named will be created. It will start out with a head equal to the one given as . @@@ -37,7 -40,7 +40,7 @@@ working tree to it; use "git checkout < new branch. When a local branch is started off a remote branch, git sets up the -branch so that linkgit:git-pull[1] will appropriately merge from +branch so that 'git-pull' will appropriately merge from the remote branch. This behavior may be changed via the global `branch.autosetupmerge` configuration flag. That setting can be overridden by using the `--track` and `--no-track` options. @@@ -54,7 -57,7 +57,7 @@@ has a reflog then the reflog will also Use -r together with -d to delete remote-tracking branches. Note, that it only makes sense to delete remote-tracking branches if they no longer exist -in remote repository or if linkgit:git-fetch[1] was configured not to fetch +in remote repository or if 'git-fetch' was configured not to fetch them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to clean up all obsolete remote-tracking branches. @@@ -107,14 -110,14 +110,14 @@@ OPTION Display the full sha1s in output listing rather than abbreviating them. --track:: - When creating a new branch, set up configuration so that git-pull + When creating a new branch, set up configuration so that 'git-pull' will automatically retrieve data from the start point, which must be a branch. Use this if you always pull from the same upstream branch into the new branch, and if you don't want to use "git pull " explicitly. This behavior is the default when the start point is a remote branch. Set the branch.autosetupmerge configuration variable to `false` if you want - git-checkout and git-branch to always behave as if '--no-track' were + 'git-checkout' and 'git-branch' to always behave as if '--no-track' were given. Set it to `always` if you want this behavior when the start-point is either a local or remote branch. diff --combined builtin-branch.c index ff71f3d8a6,1926c47581..7dae22c019 --- a/builtin-branch.c +++ b/builtin-branch.c @@@ -46,7 -46,12 +46,12 @@@ enum color_branch COLOR_BRANCH_CURRENT = 4, }; - static int mergefilter = -1; + static enum merge_filter { + NO_FILTER = 0, + SHOW_NOT_MERGED, + SHOW_MERGED, + } merge_filter; + static unsigned char merge_filter_ref[20]; static int parse_branch_color_slot(const char *var, int ofs) { @@@ -234,13 -239,15 +239,15 @@@ static int append_ref(const char *refna if ((kind & ref_list->kinds) == 0) return 0; - if (mergefilter > -1) { + if (merge_filter != NO_FILTER) { branch.item = lookup_commit_reference_gently(sha1, 1); if (!branch.item) die("Unable to lookup tip of branch %s", refname); - if (mergefilter == 0 && has_commit(head_sha1, &branch)) + if (merge_filter == SHOW_NOT_MERGED && + has_commit(merge_filter_ref, &branch)) return 0; - if (mergefilter == 1 && !has_commit(head_sha1, &branch)) + if (merge_filter == SHOW_MERGED && + !has_commit(merge_filter_ref, &branch)) return 0; } @@@ -282,21 -289,6 +289,21 @@@ static int ref_cmp(const void *r1, cons return strcmp(c1->name, c2->name); } +static void fill_tracking_info(char *stat, const char *branch_name) +{ + int ours, theirs; + struct branch *branch = branch_get(branch_name); + + if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs)) + return; + if (!ours) + sprintf(stat, "[behind %d] ", theirs); + else if (!theirs) + sprintf(stat, "[ahead %d] ", ours); + else + sprintf(stat, "[ahead %d, behind %d] ", ours, theirs); +} + static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, int abbrev, int current) { @@@ -325,10 -317,8 +332,10 @@@ if (verbose) { struct strbuf subject; const char *sub = " **** invalid ref ****"; + char stat[128]; strbuf_init(&subject, 0); + stat[0] = '\0'; commit = lookup_commit(item->sha1); if (commit && !parse_commit(commit)) { @@@ -336,15 -326,10 +343,15 @@@ &subject, 0, NULL, NULL, 0, 0); sub = subject.buf; } - printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color), + + if (item->kind == REF_LOCAL_BRANCH) + fill_tracking_info(stat, item->name); + + printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color), maxwidth, item->name, branch_get_color(COLOR_BRANCH_RESET), - find_unique_abbrev(item->sha1, abbrev), sub); + find_unique_abbrev(item->sha1, abbrev), + stat, sub); strbuf_release(&subject); } else { printf("%c %s%s%s\n", c, branch_get_color(color), item->name, @@@ -443,6 -428,20 +450,20 @@@ static int opt_parse_with_commit(const return 0; } + static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset) + { + merge_filter = ((opt->long_name[0] == 'n') + ? SHOW_NOT_MERGED + : SHOW_MERGED); + if (unset) + merge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */ + if (!arg) + arg = "HEAD"; + if (get_sha1(arg, merge_filter_ref)) + die("malformed object name %s", arg); + return 0; + } + int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, force_create = 0; @@@ -460,13 -459,17 +481,17 @@@ OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"), OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches", REF_REMOTE_BRANCH), - OPT_CALLBACK(0, "contains", &with_commit, "commit", - "print only branches that contain the commit", - opt_parse_with_commit), + { + OPTION_CALLBACK, 0, "contains", &with_commit, "commit", + "print only branches that contain the commit", + PARSE_OPT_LASTARG_DEFAULT, + opt_parse_with_commit, (intptr_t)"HEAD", + }, { OPTION_CALLBACK, 0, "with", &with_commit, "commit", "print only branches that contain the commit", - PARSE_OPT_HIDDEN, opt_parse_with_commit, + PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT, + opt_parse_with_commit, (intptr_t) "HEAD", }, OPT__ABBREV(&abbrev), @@@ -479,7 -482,18 +504,18 @@@ OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2), OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"), OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"), - OPT_SET_INT(0, "merged", &mergefilter, "list only merged branches", 1), + { + OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref, + "commit", "print only not merged branches", + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, + opt_parse_merge_filter, (intptr_t) "HEAD", + }, + { + OPTION_CALLBACK, 0, "merged", &merge_filter_ref, + "commit", "print only merged branches", + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, + opt_parse_merge_filter, (intptr_t) "HEAD", + }, OPT_END(), }; @@@ -489,9 -503,6 +525,6 @@@ branch_use_color = git_use_color_default; track = git_branch_track; - argc = parse_options(argc, argv, options, builtin_branch_usage, 0); - if (!!delete + !!rename + !!force_create > 1) - usage_with_options(builtin_branch_usage, options); head = resolve_ref("HEAD", head_sha1, 0, NULL); if (!head) @@@ -504,6 -515,11 +537,11 @@@ die("HEAD not found below refs/heads!"); head += 11; } + hashcpy(merge_filter_ref, head_sha1); + + argc = parse_options(argc, argv, options, builtin_branch_usage, 0); + if (!!delete + !!rename + !!force_create > 1) + usage_with_options(builtin_branch_usage, options); if (delete) return delete_branches(argc, argv, delete > 1, kinds);