{"thread":{"id":"38354","subject":"[PATCH] format-patch: print format-patch usage if there are no arguments","startedAt":"2015-01-13T17:54:22Z","lastAt":"2015-01-14T01:28:19Z","messageCount":10,"participants":["Alexander Kuleshov","Junio C Hamano","Stefan Beller","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"254609","messageId":"1421171662-12164-1-git-send-email-kuleshovmail@gmail.com","threadId":"38354","inReplyTo":null,"subject":"[PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Alexander Kuleshov","fromEmail":"kuleshovmail@gmail.com","sentAt":"2015-01-13T17:54:22Z","receivedAt":"2015-01-13T17:54:22Z","isPatch":true,"sender":{"key":"kuleshovmail@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2699235?v=4"},"body":"Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n---\n builtin/log.c | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex ad3cfd8..4431b50 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1246,6 +1246,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tOPT_END()\n \t};\n \n+\t/* We need at least one revision */\n+\tif (argc == 1)\n+\t\tusage_with_options(builtin_format_patch_usage, builtin_format_patch_options);\n+\n \textra_hdr.strdup_strings = 1;\n \textra_to.strdup_strings = 1;\n \textra_cc.strdup_strings = 1;\n-- \n2.3.0.rc0.239.g0ae1f56.dirty\n"},{"id":"254613","messageId":"xmqq387eed30.fsf@gitster.dls.corp.google.com","threadId":"38354","inReplyTo":"1421171662-12164-1-git-send-email-kuleshovmail@gmail.com","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-01-13T18:43:15Z","receivedAt":"2015-01-13T18:43:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Why?\n"},{"id":"254615","messageId":"CANCZXo7UtCXF_bJe9exT1pUwwsgUuYs5mvHHGtDORoJew_UXnQ@mail.gmail.com","threadId":"38354","inReplyTo":"xmqq387eed30.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Alexander Kuleshov","fromEmail":"kuleshovmail@gmail.com","sentAt":"2015-01-13T18:52:27Z","receivedAt":"2015-01-13T18:52:27Z","isPatch":true,"sender":{"key":"kuleshovmail@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2699235?v=4"},"body":"Hello Junio,\n\nAs some commands does it when they are executed without arguments,\nlike git config, git blame and etc...\n\n2015-01-14 0:43 GMT+06:00 Junio C Hamano <gitster@pobox.com>:\n> Why?\n\n\n\n-- \n_________________________\n0xAX\n"},{"id":"254617","messageId":"xmqqppaicwww.fsf@gitster.dls.corp.google.com","threadId":"38354","inReplyTo":"CANCZXo7UtCXF_bJe9exT1pUwwsgUuYs5mvHHGtDORoJew_UXnQ@mail.gmail.com","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-01-13T19:17:51Z","receivedAt":"2015-01-13T19:17:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alexander Kuleshov <kuleshovmail@gmail.com> writes:\n\n> 2015-01-14 0:43 GMT+06:00 Junio C Hamano <gitster@pobox.com>:\n>> Why?\n>\n> As some commands does it when they are executed without arguments,\n> like git config, git blame and etc...\n\nFor format-patch, I think the current behaviour is more of the lack\nof implementation of the obvious default.  \"git blame\" does not have\nany obvious default (would there be a single file you would want to\ndig the history when the user does not tell you which one?  No), so\nit proabaly is the right thing to do to error out.\n\nBut I would not surprised if those who build on top of others' work\nto wish that \"git format-patch\" that was invoked without argument on\na branch created by \"git checkout -t -b\" to default to format commits\nsince the branch forked from @{upstream}, for example.\n"},{"id":"254620","messageId":"CAGZ79kYJ+XNktc7_C81xz=BfCP4_hrE=pWW5QGJ1kdXKMf4Jjw@mail.gmail.com","threadId":"38354","inReplyTo":"xmqqppaicwww.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2015-01-13T20:00:18Z","receivedAt":"2015-01-13T20:00:18Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Jan 13, 2015 at 11:17 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Alexander Kuleshov <kuleshovmail@gmail.com> writes:\n>\n>> 2015-01-14 0:43 GMT+06:00 Junio C Hamano <gitster@pobox.com>:\n>>> Why?\n>>\n>> As some commands does it when they are executed without arguments,\n>> like git config, git blame and etc...\n>\n> For format-patch, I think the current behaviour is more of the lack\n> of implementation of the obvious default.  \"git blame\" does not have\n> any obvious default (would there be a single file you would want to\n> dig the history when the user does not tell you which one?  No), so\n> it proabaly is the right thing to do to error out.\n>\n> But I would not surprised if those who build on top of others' work\n> to wish that \"git format-patch\" that was invoked without argument on\n> a branch created by \"git checkout -t -b\" to default to format commits\n> since the branch forked from @{upstream}, for example.\n\nMy initial reaction was to assume HEAD^ if no arguments are given to\nformat-patch. Though after thinking about it, the behavior you're\nproposing makes more sense.\n\nAnother idea would be to take the first commit which is pointed to by\nanother branch as the first commit in the commit range. I am currently\nthinking about the atomic patch series which I developed on top of\norigin/mh/reflog-expire and that would be the first branch you find if\nyou just go back in history and look for any branches. Usually that\nwould be the upstream tracking branch though, so this would be an\nextension to your proposal.\n\nThough I am not sure if this scales. (Who has many branches anyway? ;)\n"},{"id":"254623","messageId":"xmqqiogaco3m.fsf@gitster.dls.corp.google.com","threadId":"38354","inReplyTo":"CAGZ79kYJ+XNktc7_C81xz=BfCP4_hrE=pWW5QGJ1kdXKMf4Jjw@mail.gmail.com","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-01-13T22:28:13Z","receivedAt":"2015-01-13T22:28:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> Another idea would be to take the first commit which is pointed to by\n> another branch as the first commit in the commit range.\n\nTrying to figure out what happened from the topology of the history\nis certainly attractive proposition, but I suspect that it would be\ntoo fragile to be practically useful.  The other topic you may have\nbased your work on may have advanced independently (e.g. a \"oops, I\nforgot this one\" bugfix), resulting in a fork like this:\n\n ---o---o---o---o (fixed reflog-expire)\n             \\\n              x---x---x (atomic-push)\n\nand the fork-point is no longer at the tip of anything.  \"Excluding\nanything that is on another branch\" would cover the forked case much\nbetter, but that is only true if there is no integration branch like\n'pu' or 'next', in which case, only an early part of atomic-push may\nalready be part of another branch 'next' while the remainder is not,\nor the entirety of atomic-push may be part of another branch 'pu'.\n\nOn the other hand, \"I am forked from building on this one\" done with\n\"checkout -t\" is an explicit mark the user leaves, so it would serve\nas a better hint to base the default heuristics on, I think.\n\nBut nobody is asking for such a feature ;-)\n"},{"id":"254626","messageId":"20150113224531.GB3144@peff.net","threadId":"38354","inReplyTo":"xmqqiogaco3m.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-01-13T22:45:31Z","receivedAt":"2015-01-13T22:45:31Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jan 13, 2015 at 02:28:13PM -0800, Junio C Hamano wrote:\n\n> On the other hand, \"I am forked from building on this one\" done with\n> \"checkout -t\" is an explicit mark the user leaves, so it would serve\n> as a better hint to base the default heuristics on, I think.\n> \n> But nobody is asking for such a feature ;-)\n\nFWIW, I very rarely run format-patch directly, but have a wrapper script\nthat dumps the patches into a tempfile and runs mutt. I taught it in\n2007 to use the upstream branch as the default[1], and was puzzled\nreading the start of this thread, thinking we already did that.\n\nSo that is perhaps not asking for the feature (I am already happy with\nmy homegrown wrapper), but is maybe an endorsement of it. :)\n\n-Peff\n\n[1] You may note in 2007 that we did not even have @{upstream}. I\n    implemented it manually using git-config! Then in 2009, I switched\n    it to use for-each-ref's \"%(upstream)\" placeholder. Literally 5 days\n    later, Dscho introduced @{upstream}, but I never got around to\n    switching. Maybe now it is time. :)\n"},{"id":"254627","messageId":"CAGZ79kZ87ZKT5-OMTEHAMEAmZVOfku_D4vZ9jcWJ4cHrA06cSw@mail.gmail.com","threadId":"38354","inReplyTo":"20150113224531.GB3144@peff.net","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2015-01-13T22:48:15Z","receivedAt":"2015-01-13T22:48:15Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Jan 13, 2015 at 2:45 PM, Jeff King <peff@peff.net> wrote:\n> On Tue, Jan 13, 2015 at 02:28:13PM -0800, Junio C Hamano wrote:\n>\n>> On the other hand, \"I am forked from building on this one\" done with\n>> \"checkout -t\" is an explicit mark the user leaves, so it would serve\n>> as a better hint to base the default heuristics on, I think.\n>>\n>> But nobody is asking for such a feature ;-)\n>\n> So that is perhaps not asking for the feature (I am already happy with\n> my homegrown wrapper), but is maybe an endorsement of it. :)\n>\n\nWould you mind to share (parts of) the wrapper script? We could see if that\nmakes sense to incorporate into format-patch as well.\n\nThanks,\nStefan\n"},{"id":"254630","messageId":"xmqqzj9mb65d.fsf@gitster.dls.corp.google.com","threadId":"38354","inReplyTo":"20150113224531.GB3144@peff.net","subject":"Re: [PATCH] format-patch: print format-patch usage if there are no arguments","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-01-13T23:41:18Z","receivedAt":"2015-01-13T23:41:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> So that is perhaps not asking for the feature (I am already happy with\n> my homegrown wrapper), but is maybe an endorsement of it. :)\n\nOK.  A patch to add this should be reasonably clean and trivial, I\nwould guess.\n"},{"id":"254634","messageId":"20150114012819.GA7520@peff.net","threadId":"38354","inReplyTo":"CAGZ79kZ87ZKT5-OMTEHAMEAmZVOfku_D4vZ9jcWJ4cHrA06cSw@mail.gmail.com","subject":"my hacky mutt-specific format-patch workflow","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-01-14T01:28:19Z","receivedAt":"2015-01-14T01:28:19Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"[retitling in case there is a wider audience]\n\nOn Tue, Jan 13, 2015 at 02:48:15PM -0800, Stefan Beller wrote:\n\n> Would you mind to share (parts of) the wrapper script? We could see if that\n> makes sense to incorporate into format-patch as well.\n\nSure, but I'll warn you it's kind of gross and specific to my workflow. :)\n\nThe script (which I call mpatch) is at the end of this message. The main\nthing which may be of interest to other people is the cover-letter\nhandling. I write my cover letters in my normal MUA (mutt), and then\ngenerate the series as a reply to that. The two ways it supports that\nare:\n\n  1. It generates the list of patches that I include in my cover letter\n     from the mbox.  This _should_ be a \"git log\" one-liner, but our\n     --pretty placeholders do not know how to count. Ideally I could say\n     \"[%i/%n]: %s\", but neither of those first two exist (and %n would\n     require counting all of the commits first, which might require some\n     surgery to git-log).\n\n  2. Given an existing message, it will pick out the to, cc, and\n     message-id headers, and generate corresponding --to, --cc, and\n     --in-reply-to arguments to feed to format-patch. I do it hackily in\n     perl, but probably format-patch could do it internally if it built\n     on git-mailinfo.\n\nI typically have my MUA in one terminal and a shell running git in the\nother. Even though I could run mpatch directly from the MUA, it is often\nmissing the context of which repo I am working in. So instead, I\ntypically use ~/patch as a go-between for the two sessions (both for\ngenerating patch series, but also for applying with git-am). So I have\nthis in my muttrc:\n\n  macro pager,index D '<shell-escape>rm -f $HOME/patch<enter>'\n  macro pager,index A '<copy-message>~/patch<enter><enter>'\n\nApplying a patch series from the list is just 'D' to clear the state,\nthen 'A' to collect whatever patches. And then I \"git am ~/patch\" from\nthe terminal window.\n\nGenerating a patch series is more like:\n\n  1. \"mpatch >~/patch\" from the git terminal to generate the list of\n      commits. No arguments necessary, because it uses @{upstream} as\n      the base (but occasionally I use \"-3\" or similar if I am sending\n      out new patches on top of somebody else's work).\n\n  2. Reply or start a new thread in mutt, as normal. This becomes the\n     cover letter (the to/cc comes from the reply, or I have mutt\n     aliases for the list and frequent contributors, and/or I may cut\n     and paste from \"git log\" in some cases).  Mutt dumps me in vim to\n     write the actual message, and I \":r ~/patch\" to pull it in.\n\n  3. Finish and send off the cover letter. This gives it a message-id.\n\n  4. Drop the newly-sent message into ~/patch. I usually just open my\n     sent folder and use 'D', 'A' to copy it there.\n\n  5. \"mpatch\" from the git terminal. The headers are picked up from\n     ~/patch. Sometimes I use \"-v2\", which is passed to format-patch\n     to get \"[PATCH v2 i/n]\".\n\nAfter that, I'm in mutt with an mbox full of the patches. I have this\nhotkey in mutt:\n\n  macro index,pager b \":set edit_headers=yes<enter><resend-message>:set edit_headers=no<enter>\"\n\nwhich dumps me vim, with the headers. From there I give a final\nproofread, write any comments below the \"---\", and then send it.\n\nI imagine for the last bit many people have a similar workflow without\nmutt that is something like:\n\n  1. format-patch into ~/patch/*\n\n  2. $EDITOR ~/patch/*\n\n  3. git send-email ~/patch/*\n\nThose people would potentially benefit from the format-patch in step 1\npicking up the headers from an existing message.\n\n-Peff\n\n-- >8 --\n#!/bin/sh\n\nupstream_branch() {\n  current=`git symbolic-ref HEAD`\n  upstream=`git for-each-ref --format='%(upstream)' \"$current\"`\n  if test -n \"$upstream\"; then\n    echo $upstream\n  else\n    echo origin\n  fi\n}\n\nget_reply_headers() {\n  perl -ne '\n    if (defined $opt && /^\\s+(.*)/) {\n      $val .= \" $1\";\n      next;\n    }\n    if (defined $opt) {\n      print \"--$opt=\", quotemeta($val), \" \";\n      $opt = $val = undef;\n    }\n    if (/^(cc|to):\\s*(.*)/i) {\n      $opt = lc($1);\n      $val = $2;\n    }\n    elsif (/^message-id:\\s*(.*)/i) {\n      $opt = \"in-reply-to\";\n      $val = $1;\n    }\n  '\n}\n\nhas_nonoption=\nfor i in \"$@\"; do\n  case \"$i\" in\n    -[0-9]) has_nonoption=yes ;;\n    -*) ;;\n     *) has_nonoption=yes\n  esac\ndone\n\n: ${REPLY:=$HOME/patch}\ntest -n \"$REPLY\" && eval \"set -- `get_reply_headers <\\\"$REPLY\\\"` \\\"\\$@\\\"\"\ntest \"$has_nonoption\" = \"yes\" || set -- \"$@\" `upstream_branch`\n\ngit format-patch -s --stdout --from \"$@\" >.mbox\nif test -t 1; then\n  mutt -f .mbox\nelse\n  perl -lne '\n    if (/^Subject: (.*)/) {\n      $subject = $1;\n    }\n    elsif ($subject && /^\\s+(.*)/) {\n      $subject .= \" $1\";\n    }\n    elsif ($subject) {\n      print $subject;\n      $subject = undef;\n    }\n  ' .mbox |\n  sed -e 's/\\[PATCH /[/' \\\n      -e 's/]/]:/' \\\n      -e 's/^/  /'\nfi\nrm -f .mbox\n"}]}