diff options
author | Junio C Hamano <gitster@pobox.com> | 2010-01-22 16:08:19 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2010-01-22 16:08:19 -0800 |
commit | 630724ca79b1a7893a8d9c04367eae857ff1a7b0 (patch) | |
tree | b1eb1c999bf904e164a0f48e1621ee74c981514d /builtin-branch.c | |
parent | 78bc024ab075f4d5d9cc0b6540b538f3d93d04cb (diff) | |
parent | 99c419c91554e9f60940228006b7d39d42704da7 (diff) | |
download | git-630724ca79b1a7893a8d9c04367eae857ff1a7b0.tar.gz git-630724ca79b1a7893a8d9c04367eae857ff1a7b0.tar.xz |
Merge branch 'jc/branch-d'
* jc/branch-d:
branch -d: base the "already-merged" safety on the branch it merges with
Diffstat (limited to 'builtin-branch.c')
-rw-r--r-- | builtin-branch.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/builtin-branch.c b/builtin-branch.c index 970cf3181..a28a13986 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -93,9 +93,60 @@ static const char *branch_get_color(enum color_branch ix) return ""; } +static int branch_merged(int kind, const char *name, + struct commit *rev, struct commit *head_rev) +{ + /* + * This checks whether the merge bases of branch and HEAD (or + * the other branch this branch builds upon) contains the + * branch, which means that the branch has already been merged + * safely to HEAD (or the other branch). + */ + struct commit *reference_rev = NULL; + const char *reference_name = NULL; + int merged; + + if (kind == REF_LOCAL_BRANCH) { + struct branch *branch = branch_get(name); + unsigned char sha1[20]; + + if (branch && + branch->merge && + branch->merge[0] && + branch->merge[0]->dst && + (reference_name = + resolve_ref(branch->merge[0]->dst, sha1, 1, NULL)) != NULL) + reference_rev = lookup_commit_reference(sha1); + } + if (!reference_rev) + reference_rev = head_rev; + + merged = in_merge_bases(rev, &reference_rev, 1); + + /* + * After the safety valve is fully redefined to "check with + * upstream, if any, otherwise with HEAD", we should just + * return the result of the in_merge_bases() above without + * any of the following code, but during the transition period, + * a gentle reminder is in order. + */ + if ((head_rev != reference_rev) && + in_merge_bases(rev, &head_rev, 1) != merged) { + if (merged) + warning("deleting branch '%s' that has been merged to\n" + " '%s', but it is not yet merged to HEAD.", + name, reference_name); + else + warning("not deleting branch '%s' that is not yet merged to\n" + " '%s', even though it is merged to HEAD.", + name, reference_name); + } + return merged; +} + static int delete_branches(int argc, const char **argv, int force, int kinds) { - struct commit *rev, *head_rev = head_rev; + struct commit *rev, *head_rev = NULL; unsigned char sha1[20]; char *name = NULL; const char *fmt, *remote; @@ -148,15 +199,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) continue; } - /* This checks whether the merge bases of branch and - * HEAD contains branch -- which means that the HEAD - * contains everything in both. - */ - - if (!force && - !in_merge_bases(rev, &head_rev, 1)) { - error("The branch '%s' is not an ancestor of " - "your current HEAD.\n" + if (!force && !branch_merged(kinds, bname.buf, rev, head_rev)) { + error("The branch '%s' is not fully merged.\n" "If you are sure you want to delete it, " "run 'git branch -D %s'.", bname.buf, bname.buf); ret = 1; |