On Tue, Feb 22, 2011 at 07:17:20AM +0100, Christian Halstrick wrote: > On Mon, Feb 21, 2011 at 18:21, Christian Halstrick > <christian.halstrick@xxxxxxxxx> wrote: > > I would like to create such tags to mark released states of my sources > > which should never be garbage collected in case no branch is pointing > > them anymore. On the other hand these tags should not pollute the > > namespace of normal tags, means: don't want a 'git tag' command to > > list those technical tags. > > Is there any better way to achieve that certain commits are not > garbage collected than to create such tags. I love my foot and don't > want to "shoot if off" but I want to make sure the the > "release-process-machinery" in our company can be sure that certain > source states are never gc'ed. I can also live with creating normal > tags 'refs/tags/release/1.20' but would prefer a solution where 'git > tags' shows only developer created tags. It sounds a lot saner to me to fix "git tag", then, to ignore certain uninteresting bits of the tag namespace. We already do allow pattern matching the tags shown, but: 1. It's an fnmatch, so I don't think there is a way to do a negative match like "ignore everything that matches release/*". 2. It can only be specified on the command-line, whereas obviously you would want this as the default for a repo when you type "git tag". So I think we could do something like the patch below, which allows: # set up some boring and interesting tags for i in boring more-boring interesting; do for j in one two three; do git tag $i/$j done done # tell git to ignore boring stuff git config tag.ignore 'boring/*' git config --add tag.ignore 'more-boring/*' # only interesting tags are shown git tag # only interesting tags are checked for --contains git tag --contains HEAD # all tags are shown git tag --no-ignore One alternative would be to allow specifying a default pattern in the config, and then some way of marking it as a regex instead of fnmatch. Then you could (in theory) construct a regex that negatively matches your boring refs. Although without perl-compatibile negative look-ahead, such regexes can get pretty hard to write. Anyway, here's what the patch looks like. Obviously missing docs and tests. --- diff --git a/builtin/tag.c b/builtin/tag.c index 46f7138..629dfa3 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -12,6 +12,7 @@ #include "tag.h" #include "run-command.h" #include "parse-options.h" +#include "string-list.h" static const char * const git_tag_usage[] = { "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]", @@ -27,8 +28,11 @@ struct tag_filter { const char *pattern; int lines; struct commit_list *with_commit; + const struct string_list *ignore; }; +static struct string_list ignore_tags = STRING_LIST_INIT_DUP; + static int show_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data) { @@ -41,6 +45,13 @@ static int show_reference(const char *refname, const unsigned char *sha1, char *buf, *sp, *eol; size_t len; + if (filter->ignore) { + for (i = 0; i < filter->ignore->nr; i++) + if (!fnmatch(filter->ignore->items[i].string, + refname, 0)) + return 0; + } + if (filter->with_commit) { struct commit *commit; @@ -89,7 +100,8 @@ static int show_reference(const char *refname, const unsigned char *sha1, } static int list_tags(const char *pattern, int lines, - struct commit_list *with_commit) + struct commit_list *with_commit, + const struct string_list *ignore) { struct tag_filter filter; @@ -99,6 +111,7 @@ static int list_tags(const char *pattern, int lines, filter.pattern = pattern; filter.lines = lines; filter.with_commit = with_commit; + filter.ignore = ignore; for_each_tag_ref(show_reference, (void *) &filter); @@ -233,6 +246,13 @@ static int git_tag_config(const char *var, const char *value, void *cb) return 0; } + if (!strcmp(var, "tag.ignore")) { + if (!value) + return config_error_nonbool(var); + string_list_append(&ignore_tags, value); + return 0; + } + return git_default_config(var, value, cb); } @@ -365,6 +385,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) const char *msgfile = NULL, *keyid = NULL; struct msg_arg msg = { 0, STRBUF_INIT }; struct commit_list *with_commit = NULL; + int ignore = 1; struct option options[] = { OPT_BOOLEAN('l', NULL, &list, "list tag names"), { OPTION_INTEGER, 'n', NULL, &lines, "n", @@ -391,6 +412,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) PARSE_OPT_LASTARG_DEFAULT, parse_opt_with_commit, (intptr_t)"HEAD", }, + OPT_BOOLEAN(0, "ignore", &ignore, "respect tag.ignore config"), OPT_END() }; @@ -415,7 +437,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) usage_with_options(git_tag_usage, options); if (list) return list_tags(argv[0], lines == -1 ? 0 : lines, - with_commit); + with_commit, + ignore ? &ignore_tags : NULL); if (lines != -1) die("-n option is only allowed with -l."); if (with_commit) -- 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