提交 b79c9859 编写于 作者: J Junio C Hamano

Merge branch 'lh/branch-merged'

* lh/branch-merged:
  Add tests for `branch --[no-]merged`
  git-branch.txt: compare --contains, --merged and --no-merged
  git-branch: add support for --merged and --no-merged
...@@ -8,7 +8,7 @@ git-branch - List, create, or delete branches ...@@ -8,7 +8,7 @@ git-branch - List, create, or delete branches
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
'git-branch' [--color | --no-color] [-r | -a] 'git-branch' [--color | --no-color] [-r | -a] [--merged | --no-merged]
[-v [--abbrev=<length> | --no-abbrev]] [-v [--abbrev=<length> | --no-abbrev]]
[--contains <commit>] [--contains <commit>]
'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>] 'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
...@@ -24,6 +24,8 @@ and option `-a` shows both. ...@@ -24,6 +24,8 @@ and option `-a` shows both.
With `--contains <commit>`, shows only the branches that With `--contains <commit>`, shows only the branches that
contains the named commit (in other words, the branches whose contains the named commit (in other words, the branches whose
tip commits are descendant of the named commit). 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.
In its second form, a new branch named <branchname> will be created. In its second form, a new branch named <branchname> will be created.
It will start out with a head equal to the one given as <start-point>. It will start out with a head equal to the one given as <start-point>.
...@@ -118,6 +120,15 @@ OPTIONS ...@@ -118,6 +120,15 @@ OPTIONS
--no-track:: --no-track::
Ignore the branch.autosetupmerge configuration variable. Ignore the branch.autosetupmerge configuration variable.
--contains <commit>::
Only list branches which contain the specified commit.
--merged::
Only list branches which are fully contained by HEAD.
--no-merged::
Do not list branches which are fully contained by HEAD.
<branchname>:: <branchname>::
The name of the branch to create or delete. The name of the branch to create or delete.
The new branch name must pass all checks defined by The new branch name must pass all checks defined by
...@@ -175,6 +186,18 @@ If you are creating a branch that you want to immediately checkout, it's ...@@ -175,6 +186,18 @@ If you are creating a branch that you want to immediately checkout, it's
easier to use the git checkout command with its `-b` option to create easier to use the git checkout command with its `-b` option to create
a branch and check it out with a single command. a branch and check it out with a single command.
The options `--contains`, `--merged` and `--no-merged` serves three related
but different purposes:
- `--contains <commit>` is used to find all branches which will need
special attention if <commit> were to be rebased or amended, since those
branches contain the specified <commit>.
- `--merged` is used to find all branches which can be safely deleted,
since those branches are fully contained by HEAD.
- `--no-merged` is used to find branches which are candidates for merging
into HEAD, since those branches are not fully contained by HEAD.
Author Author
------ ------
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include "branch.h" #include "branch.h"
static const char * const builtin_branch_usage[] = { static const char * const builtin_branch_usage[] = {
"git-branch [options] [-r | -a]", "git-branch [options] [-r | -a] [--merged | --no-merged]",
"git-branch [options] [-l] [-f] <branchname> [<start-point>]", "git-branch [options] [-l] [-f] <branchname> [<start-point>]",
"git-branch [options] [-r] (-d | -D) <branchname>", "git-branch [options] [-r] (-d | -D) <branchname>",
"git-branch [options] (-m | -M) [<oldbranch>] <newbranch>", "git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
...@@ -46,6 +46,8 @@ enum color_branch { ...@@ -46,6 +46,8 @@ enum color_branch {
COLOR_BRANCH_CURRENT = 4, COLOR_BRANCH_CURRENT = 4,
}; };
static int mergefilter = -1;
static int parse_branch_color_slot(const char *var, int ofs) static int parse_branch_color_slot(const char *var, int ofs)
{ {
if (!strcasecmp(var+ofs, "plain")) if (!strcasecmp(var+ofs, "plain"))
...@@ -210,6 +212,7 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags, ...@@ -210,6 +212,7 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
struct ref_item *newitem; struct ref_item *newitem;
int kind = REF_UNKNOWN_TYPE; int kind = REF_UNKNOWN_TYPE;
int len; int len;
static struct commit_list branch;
/* Detect kind */ /* Detect kind */
if (!prefixcmp(refname, "refs/heads/")) { if (!prefixcmp(refname, "refs/heads/")) {
...@@ -231,6 +234,16 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags, ...@@ -231,6 +234,16 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
if ((kind & ref_list->kinds) == 0) if ((kind & ref_list->kinds) == 0)
return 0; return 0;
if (mergefilter > -1) {
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))
return 0;
if (mergefilter == 1 && !has_commit(head_sha1, &branch))
return 0;
}
/* Resize buffer */ /* Resize buffer */
if (ref_list->index >= ref_list->alloc) { if (ref_list->index >= ref_list->alloc) {
ref_list->alloc = alloc_nr(ref_list->alloc); ref_list->alloc = alloc_nr(ref_list->alloc);
...@@ -444,6 +457,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) ...@@ -444,6 +457,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2), 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('l', NULL, &reflog, "create the branch's reflog"),
OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"), OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"),
OPT_SET_INT(0, "merged", &mergefilter, "list only merged branches", 1),
OPT_END(), OPT_END(),
}; };
......
#!/bin/sh #!/bin/sh
test_description='branch --contains <commit>' test_description='branch --contains <commit>, --merged, and --no-merged'
. ./test-lib.sh . ./test-lib.sh
...@@ -55,4 +55,44 @@ test_expect_success 'branch --contains=side' ' ...@@ -55,4 +55,44 @@ test_expect_success 'branch --contains=side' '
' '
test_expect_success 'side: branch --merged' '
git branch --merged >actual &&
{
echo " master" &&
echo "* side"
} >expect &&
test_cmp expect actual
'
test_expect_success 'side: branch --no-merged' '
git branch --no-merged >actual &&
>expect &&
test_cmp expect actual
'
test_expect_success 'master: branch --merged' '
git checkout master &&
git branch --merged >actual &&
{
echo "* master"
} >expect &&
test_cmp expect actual
'
test_expect_success 'master: branch --no-merged' '
git branch --no-merged >actual &&
{
echo " side"
} >expect &&
test_cmp expect actual
'
test_done test_done
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册