{"thread":{"id":"10713","subject":"[PATCH] git-branch --with=commit","startedAt":"2007-11-07T23:15:42Z","lastAt":"2007-11-15T17:27:26Z","messageCount":9,"participants":["Junio C Hamano","Jakub Narebski","Johannes Schindelin","Johannes Sixt","Andreas Ericsson","Jan Hudec"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"58755","messageId":"7vpryl8x5t.fsf@gitster.siamese.dyndns.org","threadId":"10713","inReplyTo":null,"subject":"[PATCH] git-branch --with=commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-07T23:15:42Z","receivedAt":"2007-11-07T23:15:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This teaches git-branch to limit its listing to branches that\nare descendants to the named commit.\n\nWhen you are using many topic branches, you often would want to\nsee which branch already includes a commit, so that you know\nwhich can and cannot be rewound without disrupting other people.\n\nOne thing that sometimes happens to me is:\n\n * Somebody sends a patch that is a good maint material.  I\n   apply it to 'maint':\n\n     $ git checkout maint\n     $ git am -3 -s obvious-fix.patch\n\n * Then somebody else sends another patch that is possibly a\n   good maint material, but I'd want to cook it in 'next' to be\n   extra sure.  I fork a topic from 'maint' and apply the patch:\n\n     $ git checkout -b xx/maint-fix-foo\n     $ git am -3 -s ,xx-maint-fix-foo.patch\n\n * A minor typo is found in the \"obvious-fix.patch\".\n\nThe above happens without pushing the results out, so I can\nfreely recover from it by amending 'maint', as long as I do not\nforget to rebase the topics that were forked previously.\n\nWith this patch, I could do this to find out which topic\nbranches already contain the faulty commit:\n\n    $ git branch --with=maint^ | grep /\n      xx/maint-fix-foo\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-branch.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++--\n 1 files changed, 48 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 3bf40f1..d13e64f 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -184,9 +184,30 @@ struct ref_item {\n struct ref_list {\n \tint index, alloc, maxwidth;\n \tstruct ref_item *list;\n+\tstruct commit_list *with_commit;\n \tint kinds;\n };\n \n+static int has_commit(const unsigned char *sha1, struct commit_list *with_commit)\n+{\n+\tstruct commit *commit;\n+\n+\tif (!with_commit)\n+\t\treturn 1;\n+\tcommit = lookup_commit_reference_gently(sha1, 1);\n+\tif (!commit)\n+\t\treturn 0;\n+\twhile (with_commit) {\n+\t\tstruct commit *other;\n+\n+\t\tother = with_commit->item;\n+\t\twith_commit = with_commit->next;\n+\t\tif (in_merge_bases(other, &commit, 1))\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)\n {\n \tstruct ref_list *ref_list = (struct ref_list*)(cb_data);\n@@ -206,6 +227,10 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,\n \t\trefname += 10;\n \t}\n \n+\t/* Filter with with_commit if specified */\n+\tif (!has_commit(sha1, ref_list->with_commit))\n+\t\treturn 0;\n+\n \t/* Don't add types the caller doesn't want */\n \tif ((kind & ref_list->kinds) == 0)\n \t\treturn 0;\n@@ -296,13 +321,14 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t}\n }\n \n-static void print_ref_list(int kinds, int detached, int verbose, int abbrev)\n+static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit)\n {\n \tint i;\n \tstruct ref_list ref_list;\n \n \tmemset(&ref_list, 0, sizeof(ref_list));\n \tref_list.kinds = kinds;\n+\tref_list.with_commit = with_commit;\n \tfor_each_ref(append_ref, &ref_list);\n \n \tqsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n@@ -505,6 +531,22 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \t\tdie(\"Branch is renamed, but update of config-file failed\");\n }\n \n+static int opt_parse_with_commit(const struct option *opt, const char *arg, int unset)\n+{\n+\tunsigned char sha1[20];\n+\tstruct commit *commit;\n+\n+\tif (!arg)\n+\t\treturn -1;\n+\tif (get_sha1(arg, sha1))\n+\t\tdie(\"malformed object name %s\", arg);\n+\tcommit = lookup_commit_reference(sha1);\n+\tif (!commit)\n+\t\tdie(\"no such commit %s\", arg);\n+\tcommit_list_insert(commit, opt->value);\n+\treturn 0;\n+}\n+\n int cmd_branch(int argc, const char **argv, const char *prefix)\n {\n \tint delete = 0, force_delete = 0, force_create = 0;\n@@ -512,6 +554,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tint verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;\n \tint reflog = 0, track;\n \tint kinds = REF_LOCAL_BRANCH, kind_remote = 0, kind_any = 0;\n+\tstruct commit_list *with_commit = NULL;\n \n \tstruct option options[] = {\n \t\tOPT_GROUP(\"Generic options\"),\n@@ -519,6 +562,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOLEAN( 0 , \"track\",  &track, \"set up tracking mode (see git-pull(1))\"),\n \t\tOPT_BOOLEAN( 0 , \"color\",  &branch_use_color, \"use colored output\"),\n \t\tOPT_BOOLEAN('r', NULL,     &kind_remote, \"act on remote-tracking branches\"),\n+\t\tOPT_CALLBACK(0, \"with\",    &with_commit, \"commit\",\n+\t\t\t     \"print only branches that contain the commit\",\n+\t\t\t     opt_parse_with_commit),\n \t\tOPT__ABBREV(&abbrev),\n \n \t\tOPT_GROUP(\"Specific git-branch actions:\"),\n@@ -566,7 +612,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (delete)\n \t\treturn delete_branches(argc, argv, force_delete, kinds);\n \telse if (argc == 0)\n-\t\tprint_ref_list(kinds, detached, verbose, abbrev);\n+\t\tprint_ref_list(kinds, detached, verbose, abbrev, with_commit);\n \telse if (rename && (argc == 1))\n \t\trename_branch(head, argv[0], force_rename);\n \telse if (rename && (argc == 2))\n-- \n1.5.3.5.1593.g5baf\n"},{"id":"58763","messageId":"fgthvm$m79$1@ger.gmane.org","threadId":"10713","inReplyTo":"7vpryl8x5t.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-07T23:33:11Z","receivedAt":"2007-11-07T23:33:11Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> ---\n>  builtin-branch.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++--\n>  1 files changed, 48 insertions(+), 2 deletions(-)\n\nDocumentation/git-branch.txt, please?\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"58766","messageId":"Pine.LNX.4.64.0711080008050.4362@racer.site","threadId":"10713","inReplyTo":"7vpryl8x5t.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-08T00:09:19Z","receivedAt":"2007-11-08T00:09:19Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nwould it not be better to call it --containing=commit?  Besides, I think \nthat the opt_parse_with_commit() function would be better named \nopt_parse_commit() and be put into parse-options.[ch].\n\nCiao,\nDscho\n"},{"id":"58787","messageId":"7vk5ot7aqz.fsf@gitster.siamese.dyndns.org","threadId":"10713","inReplyTo":"Pine.LNX.4.64.0711080008050.4362@racer.site","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-08T02:05:08Z","receivedAt":"2007-11-08T02:05:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> would it not be better to call it --containing=commit?  Besides, I think \n> that the opt_parse_with_commit() function would be better named \n> opt_parse_commit() and be put into parse-options.[ch].\n\ngit-describe has \"--contains\" so that may be a better match.  I\ndo not know the particular function is generic enough to be in\nparse-options.\n"},{"id":"58791","messageId":"Pine.LNX.4.64.0711080300100.4362@racer.site","threadId":"10713","inReplyTo":"7vk5ot7aqz.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-08T03:02:03Z","receivedAt":"2007-11-08T03:02:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 7 Nov 2007, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > would it not be better to call it --containing=commit?  Besides, I \n> > think that the opt_parse_with_commit() function would be better named \n> > opt_parse_commit() and be put into parse-options.[ch].\n> \n> git-describe has \"--contains\" so that may be a better match.\n\nI just thought what I would understand when reading \"git branch \n--with=master\".  I would have expected that it branches off of master.\n\n> I do not know the particular function is generic enough to be in \n> parse-options.\n\nMaybe not, you're right.  And we can always come back later, and expose \nthe function if need be.\n\nCiao,\nDscho\n"},{"id":"58810","messageId":"4732BC6F.7070005@viscovery.net","threadId":"10713","inReplyTo":"7vpryl8x5t.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2007-11-08T07:36:15Z","receivedAt":"2007-11-08T07:36:15Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Junio C Hamano schrieb:\n>      $ git checkout -b xx/maint-fix-foo\n>      $ git am -3 -s ,xx-maint-fix-foo.patch\n\nIs this comma a hidden feature?\n\n> With this patch, I could do this to find out which topic\n> branches already contain the faulty commit:\n> \n>     $ git branch --with=maint^ | grep /\n>       xx/maint-fix-foo\n\nIt'd be helpful if you could construct the example in this commit message \nsuch that you don't need the \"grep /\" here; otherwise, the reader doesn't \nknow which part of the effect is hidden by the grep.\n\n-- Hannes\n"},{"id":"58821","messageId":"7vejf140jd.fsf@gitster.siamese.dyndns.org","threadId":"10713","inReplyTo":"4732BC6F.7070005@viscovery.net","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-08T08:13:58Z","receivedAt":"2007-11-08T08:13:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> Junio C Hamano schrieb:\n>>      $ git checkout -b xx/maint-fix-foo\n>>      $ git am -3 -s ,xx-maint-fix-foo.patch\n>\n> Is this comma a hidden feature?\n\nNo, just my personal convention to queue e-mails from my mailbox.\n\n>> With this patch, I could do this to find out which topic\n>> branches already contain the faulty commit:\n>>\n>>     $ git branch --with=maint^ | grep /\n>>       xx/maint-fix-foo\n>\n> It'd be helpful if you could construct the example in this commit\n> message such that you don't need the \"grep /\" here; otherwise, the\n> reader doesn't know which part of the effect is hidden by the grep.\n\nYeah, in the example sequence, I think only maint itself and\nxx/maint-fix-foo are shown, so there is no need for grep.\n"},{"id":"58836","messageId":"4732D440.2020504@op5.se","threadId":"10713","inReplyTo":"7vejf140jd.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2007-11-08T09:17:52Z","receivedAt":"2007-11-08T09:17:52Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Junio C Hamano wrote:\n> Johannes Sixt <j.sixt@viscovery.net> writes:\n> \n>> Junio C Hamano schrieb:\n> \n>>> With this patch, I could do this to find out which topic\n>>> branches already contain the faulty commit:\n>>>\n>>>     $ git branch --with=maint^ | grep /\n>>>       xx/maint-fix-foo\n>> It'd be helpful if you could construct the example in this commit\n>> message such that you don't need the \"grep /\" here; otherwise, the\n>> reader doesn't know which part of the effect is hidden by the grep.\n> \n> Yeah, in the example sequence, I think only maint itself and\n> xx/maint-fix-foo are shown, so there is no need for grep.\n\nAnd \"maint\" could certainly be stripped by the code itself, since the\nuser can reasonably be expected to know that plain maint will have\neverything maint^ has.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"60006","messageId":"20071115172726.GA4525@efreet.light.src","threadId":"10713","inReplyTo":"4732D440.2020504@op5.se","subject":"Re: [PATCH] git-branch --with=commit","fromName":"Jan Hudec","fromEmail":"bulb@ucw.cz","sentAt":"2007-11-15T17:27:26Z","receivedAt":"2007-11-15T17:27:26Z","isPatch":true,"sender":{"key":"bulb@ucw.cz","avatar":null},"body":"On Thu, Nov 08, 2007 at 10:17:52 +0100, Andreas Ericsson wrote:\n> Junio C Hamano wrote:\n>> Johannes Sixt <j.sixt@viscovery.net> writes:\n>>\n>>> Junio C Hamano schrieb:\n>>\n>>>> With this patch, I could do this to find out which topic\n>>>> branches already contain the faulty commit:\n>>>>\n>>>>     $ git branch --with=maint^ | grep /\n>>>>       xx/maint-fix-foo\n>>> It'd be helpful if you could construct the example in this commit\n>>> message such that you don't need the \"grep /\" here; otherwise, the\n>>> reader doesn't know which part of the effect is hidden by the grep.\n>>\n>> Yeah, in the example sequence, I think only maint itself and\n>> xx/maint-fix-foo are shown, so there is no need for grep.\n>\n> And \"maint\" could certainly be stripped by the code itself, since the\n> user can reasonably be expected to know that plain maint will have\n> everything maint^ has.\n\nDWIDNS (Do what I did not say).\n\nNormally one would expect 'git branch --with=maint^' and\n'git branch --with=$(git ref-parse maint^)' to be exactly the same. Alas,\nwith your suggestion, they would not.\n\n-- \n\t\t\t\t\t\t Jan 'Bulb' Hudec <bulb@ucw.cz>\n"}]}