From f3d985c38090b77e46dcc00d42574b9ba49bdc22 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Dec 2006 23:58:16 -0800 Subject: [PATCH 1/2] Teach git-branch to delete tracking branches with -r -d Because -r already means "remote" when listing, you can say: $ git branch -d -r origin/todo origin/html origin/man I just twisted it not to check fast-forwardness with the current branch when you are removing a tracking branch. Most likely, removal of a tracking branch is not because you are "done with" it (for a local branch, it usually means "you merged it up"), but because you are not even interested in it. In other words, remote tracking branches are more like tags than branches. Signed-off-by: Junio C Hamano --- builtin-branch.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/builtin-branch.c b/builtin-branch.c index 560309cb15..7fb93e7796 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -12,8 +12,12 @@ #include "builtin.h" static const char builtin_branch_usage[] = - "git-branch (-d | -D) | [-l] [-f] [] | (-m | -M) [] | [-r | -a] [-v [--abbrev=]]"; + "git-branch [-r] (-d | -D) | [-l] [-f] [] | (-m | -M) [] | [-r | -a] [-v [--abbrev=]]"; +#define REF_UNKNOWN_TYPE 0x00 +#define REF_LOCAL_BRANCH 0x01 +#define REF_REMOTE_BRANCH 0x02 +#define REF_TAG 0x04 static const char *head; static unsigned char head_sha1[20]; @@ -89,25 +93,40 @@ static int in_merge_bases(const unsigned char *sha1, return ret; } -static void delete_branches(int argc, const char **argv, int force) +static void delete_branches(int argc, const char **argv, int force, int kinds) { struct commit *rev, *head_rev = head_rev; unsigned char sha1[20]; char *name; + const char *fmt, *remote; int i; + switch (kinds) { + case REF_REMOTE_BRANCH: + fmt = "refs/remotes/%s"; + remote = "remote "; + force = 1; + break; + case REF_LOCAL_BRANCH: + fmt = "refs/heads/%s"; + remote = ""; + break; + default: + die("cannot use -a with -d"); + } + if (!force) { head_rev = lookup_commit_reference(head_sha1); if (!head_rev) die("Couldn't look up commit object for HEAD"); } for (i = 0; i < argc; i++) { - if (!strcmp(head, argv[i])) + if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) die("Cannot delete the branch you are currently on."); - name = xstrdup(mkpath("refs/heads/%s", argv[i])); + name = xstrdup(mkpath(fmt, argv[i])); if (!resolve_ref(name, sha1, 1, NULL)) - die("Branch '%s' not found.", argv[i]); + die("%sbranch '%s' not found.", remote, argv[i]); rev = lookup_commit_reference(sha1); if (!rev) @@ -128,19 +147,15 @@ static void delete_branches(int argc, const char **argv, int force) } if (delete_ref(name, sha1)) - printf("Error deleting branch '%s'\n", argv[i]); + printf("Error deleting %sbranch '%s'\n", remote, + argv[i]); else - printf("Deleted branch %s.\n", argv[i]); + printf("Deleted %sbranch %s.\n", remote, argv[i]); free(name); } } -#define REF_UNKNOWN_TYPE 0x00 -#define REF_LOCAL_BRANCH 0x01 -#define REF_REMOTE_BRANCH 0x02 -#define REF_TAG 0x04 - struct ref_item { char *name; unsigned int kind; @@ -435,7 +450,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) head += 11; if (delete) - delete_branches(argc - i, argv + i, force_delete); + delete_branches(argc - i, argv + i, force_delete, kinds); else if (i == argc) print_ref_list(kinds, verbose, abbrev); else if (rename && (i == argc - 1)) From b8e9a00d40839a76928c54366a1c46ad54d7fd5d Mon Sep 17 00:00:00 2001 From: Quy Tonthat Date: Tue, 19 Dec 2006 09:42:16 +1100 Subject: [PATCH 2/2] git-branch -d: do not stop at the first failure. If there are more than one branches to be deleted, failure on one will no longer stop git-branch to process the next ones. The command still reports failures by exitting non-zero status. Signed-off-by: Quy Tonthat Signed-off-by: Junio C Hamano --- builtin-branch.c | 57 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/builtin-branch.c b/builtin-branch.c index 7fb93e7796..011ef3a265 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -93,13 +93,14 @@ static int in_merge_bases(const unsigned char *sha1, return ret; } -static void delete_branches(int argc, const char **argv, int force, int kinds) +static int delete_branches(int argc, const char **argv, int force, int kinds) { struct commit *rev, *head_rev = head_rev; unsigned char sha1[20]; - char *name; + char *name = NULL; const char *fmt, *remote; int i; + int ret = 0; switch (kinds) { case REF_REMOTE_BRANCH: @@ -121,16 +122,30 @@ static void delete_branches(int argc, const char **argv, int force, int kinds) die("Couldn't look up commit object for HEAD"); } for (i = 0; i < argc; i++) { - if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) - die("Cannot delete the branch you are currently on."); + if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) { + error("Cannot delete the branch '%s' " + "which you are currently on.", argv[i]); + ret = 1; + continue; + } + + if (name) + free(name); name = xstrdup(mkpath(fmt, argv[i])); - if (!resolve_ref(name, sha1, 1, NULL)) - die("%sbranch '%s' not found.", remote, argv[i]); + if (!resolve_ref(name, sha1, 1, NULL)) { + error("%sbranch '%s' not found.", + remote, argv[i]); + ret = 1; + continue; + } rev = lookup_commit_reference(sha1); - if (!rev) - die("Couldn't look up commit object for '%s'", name); + if (!rev) { + error("Couldn't look up commit object for '%s'", name); + ret = 1; + continue; + } /* This checks whether the merge bases of branch and * HEAD contains branch -- which means that the HEAD @@ -139,21 +154,27 @@ static void delete_branches(int argc, const char **argv, int force, int kinds) if (!force && !in_merge_bases(sha1, rev, head_rev)) { - fprintf(stderr, - "The branch '%s' is not a strict subset of your current HEAD.\n" - "If you are sure you want to delete it, run 'git branch -D %s'.\n", - argv[i], argv[i]); - exit(1); + error("The branch '%s' is not a strict subset of " + "your current HEAD.\n" + "If you are sure you want to delete it, " + "run 'git branch -D %s'.", argv[i], argv[i]); + ret = 1; + continue; } - if (delete_ref(name, sha1)) - printf("Error deleting %sbranch '%s'\n", remote, + if (delete_ref(name, sha1)) { + error("Error deleting %sbranch '%s'", remote, argv[i]); - else + ret = 1; + } else printf("Deleted %sbranch %s.\n", remote, argv[i]); - free(name); } + + if (name) + free(name); + + return(ret); } struct ref_item { @@ -450,7 +471,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) head += 11; if (delete) - delete_branches(argc - i, argv + i, force_delete, kinds); + return delete_branches(argc - i, argv + i, force_delete, kinds); else if (i == argc) print_ref_list(kinds, verbose, abbrev); else if (rename && (i == argc - 1))