{"thread":{"id":"35213","subject":"[PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","startedAt":"2013-10-27T01:34:02Z","lastAt":"2013-11-02T12:54:52Z","messageCount":49,"participants":["Josh Triplett","Michael Haggerty","Theodore Ts'o","Michel Lespinasse","Thomas Rast","Duy Nguyen","Stefan Beller","Johan Herland","Christian Couder","Jim Hill","Junio C Hamano","Christoph Hellwig","Benjamin Herrenschmidt","Russell King - ARM Linux","Jeff King","Matthieu Moy","Tony Luck","brian m. carlson"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"229580","messageId":"20131027013402.GA7146@leaf","threadId":"35213","inReplyTo":"20131026181709.GB10488@kroah.com","subject":"[PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Josh Triplett","fromEmail":"josh@joshtriplett.org","sentAt":"2013-10-27T01:34:02Z","receivedAt":"2013-10-27T01:34:02Z","isPatch":true,"sender":{"key":"josh@joshtriplett.org","avatar":"https://avatars.githubusercontent.com/u/162737?v=4"},"body":"Linux Kernel Summit 2013 decided on a commit message convention to\nidentify commits containing bugs fixed by a commit: a \"Fixes:\" line,\nincluded in the standard commit footer (along with \"Signed-off-by:\" if\npresent), containing an abbreviated commit hash (at least 12 characters\nto keep it valid for a long time) and the subject of the commit (for\nhuman readers).  This helps people (or automated tools) determine how\nfar to backport a commit.\n\nAdd a command line option for git commit to automatically construct the\n\"Fixes:\" line for a commit.  This avoids the need to manually construct\nthat line by copy-pasting the commit hash and subject.\n\nAlso works with --amend to modify an existing commit's message.  To add\na Fixes line to an earlier commit in a series, use rebase -i and add the\nfollowing line after the existing commit:\nx git commit --amend --no-edit -f $commit_containing_bug\n\nGeneralize append_signoff to support appending arbitrary extra lines to\na commit in the signoff block; this avoids duplicating the logic to find\nor construct that block.\n\nSigned-off-by: Josh Triplett <josh@joshtriplett.org>\n---\n Documentation/git-commit.txt | 12 ++++++++++--\n builtin/commit.c             | 29 +++++++++++++++++++++++++++--\n sequencer.c                  | 31 +++++++++++++++++++++++--------\n sequencer.h                  |  3 +++\n t/t7502-commit.sh            | 39 ++++++++++++++++++++++++++++++++++++++-\n 5 files changed, 101 insertions(+), 13 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 1a7616c..fcc6ed2 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -8,8 +8,8 @@ git-commit - Record changes to the repository\n SYNOPSIS\n --------\n [verse]\n-'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n-\t   [--dry-run] [(-c | -C | --fixup | --squash) <commit>]\n+'git commit' [-a | --interactive | --patch] [-s] [-f <commit>] [-v] [-u<mode>]\n+\t   [--amend] [--dry-run] [(-c | -C | --fixup | --squash) <commit>]\n \t   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n@@ -156,6 +156,14 @@ OPTIONS\n \tAdd Signed-off-by line by the committer at the end of the commit\n \tlog message.\n \n+-f <commit>::\n+--fixes=<commit>::\n+\tAdd Fixes line for the specified commit at the end of the commit\n+\tlog message.  This line includes an abbreviated commit hash for\n+\tthe specified commit; the `core.abbrev` option determines the\n+\tlength of the abbreviated commit hash used, with a minimum length\n+\tof 12 hex digits.\n+\n -n::\n --no-verify::\n \tThis option bypasses the pre-commit and commit-msg hooks.\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 6ab4605..9bbcd8a 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -123,6 +123,7 @@ static int use_editor = 1, include_status = 1;\n static int show_ignored_in_status, have_option_m;\n static const char *only_include_assumed;\n static struct strbuf message = STRBUF_INIT;\n+static struct strbuf fixes = STRBUF_INIT;\n \n static enum status_format {\n \tSTATUS_FORMAT_NONE = 0,\n@@ -133,6 +134,28 @@ static enum status_format {\n \tSTATUS_FORMAT_UNSPECIFIED\n } status_format = STATUS_FORMAT_UNSPECIFIED;\n \n+static int opt_parse_f(const struct option *opt, const char *arg, int unset)\n+{\n+\tstruct strbuf *sb = opt->value;\n+\tif (unset) {\n+\t\tstrbuf_setlen(sb, 0);\n+\t} else {\n+\t\tstruct pretty_print_context ctx = {0};\n+\t\tstruct commit *commit;\n+\n+\t\tcommit = lookup_commit_reference_by_name(arg);\n+\t\tif (!commit)\n+\t\t\tdie(_(\"could not lookup commit %s\"), arg);\n+\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\tctx.abbrev = DEFAULT_ABBREV;\n+\t\tif (ctx.abbrev < 12)\n+\t\t\tctx.abbrev = 12;\n+\t\tformat_commit_message(commit, \"Fixes: %h ('%s')\\n\", sb, &ctx);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int opt_parse_m(const struct option *opt, const char *arg, int unset)\n {\n \tstruct strbuf *buf = opt->value;\n@@ -718,7 +741,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \tif (clean_message_contents)\n \t\tstripspace(&sb, 0);\n \n-\tif (signoff) {\n+\tif (signoff || fixes.len) {\n \t\t/*\n \t\t * See if we have a Conflicts: block at the end. If yes, count\n \t\t * its size, so we can ignore it.\n@@ -742,7 +765,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\tprevious = eol;\n \t\t}\n \n-\t\tappend_signoff(&sb, ignore_footer, 0);\n+\t\tappend_signoff_extra(&sb, ignore_footer,\n+\t\t\t\t     signoff ? 0 : APPEND_EXTRA_ONLY, &fixes);\n \t}\n \n \tif (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)\n@@ -1463,6 +1487,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING(0, \"squash\", &squash_message, N_(\"commit\"), N_(\"use autosquash formatted message to squash specified commit\")),\n \t\tOPT_BOOL(0, \"reset-author\", &renew_authorship, N_(\"the commit is authored by me now (used with -C/-c/--amend)\")),\n \t\tOPT_BOOL('s', \"signoff\", &signoff, N_(\"add Signed-off-by:\")),\n+\t\tOPT_CALLBACK('f', \"fixes\", &fixes, N_(\"commit\"), N_(\"add Fixes: for the specified commit\"), opt_parse_f),\n \t\tOPT_FILENAME('t', \"template\", &template_file, N_(\"use specified template file\")),\n \t\tOPT_BOOL('e', \"edit\", &edit_flag, N_(\"force edit of commit\")),\n \t\tOPT_STRING(0, \"cleanup\", &cleanup_arg, N_(\"default\"), N_(\"how to strip spaces and #comments from message\")),\ndiff --git a/sequencer.c b/sequencer.c\nindex 06e52b4..f4cf0e1 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1135,26 +1135,33 @@ int sequencer_pick_revisions(struct replay_opts *opts)\n \treturn pick_commits(todo_list, opts);\n }\n \n-void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)\n+void append_signoff_extra(struct strbuf *msgbuf, int ignore_footer,\n+\t\t\t  unsigned flag, struct strbuf *extrabuf)\n {\n \tunsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;\n+\tunsigned append_sob = !(flag & APPEND_EXTRA_ONLY);\n \tstruct strbuf sob = STRBUF_INIT;\n \tint has_footer;\n \n-\tstrbuf_addstr(&sob, sign_off_header);\n-\tstrbuf_addstr(&sob, fmt_name(getenv(\"GIT_COMMITTER_NAME\"),\n-\t\t\t\tgetenv(\"GIT_COMMITTER_EMAIL\")));\n-\tstrbuf_addch(&sob, '\\n');\n+\tif (append_sob) {\n+\t\tstrbuf_addstr(&sob, sign_off_header);\n+\t\tstrbuf_addstr(&sob, fmt_name(getenv(\"GIT_COMMITTER_NAME\"),\n+\t\t\t\t\tgetenv(\"GIT_COMMITTER_EMAIL\")));\n+\t\tstrbuf_addch(&sob, '\\n');\n+\t}\n \n \t/*\n \t * If the whole message buffer is equal to the sob, pretend that we\n \t * found a conforming footer with a matching sob\n \t */\n-\tif (msgbuf->len - ignore_footer == sob.len &&\n+\tif (append_sob &&\n+\t    msgbuf->len - ignore_footer == sob.len &&\n \t    !strncmp(msgbuf->buf, sob.buf, sob.len))\n \t\thas_footer = 3;\n \telse\n-\t\thas_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);\n+\t\thas_footer = has_conforming_footer(msgbuf,\n+\t\t\t\t\t\t   append_sob ? &sob : NULL,\n+\t\t\t\t\t\t   ignore_footer);\n \n \tif (!has_footer) {\n \t\tconst char *append_newlines = NULL;\n@@ -1193,9 +1200,17 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)\n \t\t\t\tappend_newlines, strlen(append_newlines));\n \t}\n \n-\tif (has_footer != 3 && (!no_dup_sob || has_footer != 2))\n+\tif (append_sob && has_footer != 3 && (!no_dup_sob || has_footer != 2))\n \t\tstrbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,\n \t\t\t\tsob.buf, sob.len);\n+\tif (extrabuf)\n+\t\tstrbuf_insert(msgbuf, msgbuf->len - ignore_footer,\n+\t\t\t\textrabuf->buf, extrabuf->len);\n \n \tstrbuf_release(&sob);\n }\n+\n+void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)\n+{\n+\tappend_signoff_extra(msgbuf, ignore_footer, flag, NULL);\n+}\ndiff --git a/sequencer.h b/sequencer.h\nindex 1fc22dc..8716ad0 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -7,6 +7,7 @@\n #define SEQ_OPTS_FILE\t\"sequencer/opts\"\n \n #define APPEND_SIGNOFF_DEDUP (1u << 0)\n+#define APPEND_EXTRA_ONLY (1u << 1)\n \n enum replay_action {\n \tREPLAY_REVERT,\n@@ -51,5 +52,7 @@ int sequencer_pick_revisions(struct replay_opts *opts);\n extern const char sign_off_header[];\n \n void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag);\n+void append_signoff_extra(struct strbuf *msgbuf, int ignore_footer,\n+\t\t\t  unsigned flag, struct strbuf *extrabuf);\n \n #endif\ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex 6313da2..12b123a 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -137,13 +137,50 @@ test_expect_success 'partial removal' '\n \n '\n \n+signoff_ident () {\n+\tgit var GIT_COMMITTER_IDENT | sed -e \"s/>.*/>/\"\n+}\n+\n test_expect_success 'sign off' '\n \n \t>positive &&\n \tgit add positive &&\n \tgit commit -s -m \"thank you\" &&\n \tactual=$(git cat-file commit HEAD | sed -ne \"s/Signed-off-by: //p\") &&\n-\texpected=$(git var GIT_COMMITTER_IDENT | sed -e \"s/>.*/>/\") &&\n+\texpected=$(signoff_ident) &&\n+\ttest \"z$actual\" = \"z$expected\"\n+\n+'\n+\n+fixes_for_commits () {\n+\tfor commit in \"$@\"; do\n+\t\tgit -c core.abbrev=12 log -1 --pretty=format:\"Fixes: %h ('%s')%n\" \"$commit\"\n+\tdone\n+}\n+\n+test_expect_success '--fixes' '\n+\n+\techo >>positive &&\n+\tgit add positive &&\n+\tgit commit -f HEAD -m \"fix bug\" &&\n+\tactual=$(git cat-file commit HEAD | sed -e \"1,/^\\$/d\") &&\n+\texpected=$(echo fix bug; echo; fixes_for_commits HEAD^) &&\n+\ttest \"z$actual\" = \"z$expected\"\n+\n+'\n+\n+test_expect_success 'multiple --fixes with signoff' '\n+\n+\techo >>positive &&\n+\tgit add positive &&\n+\tgit commit -f HEAD^ -f HEAD -s -m \"signed bugfix\" &&\n+\tactual=$(git cat-file commit HEAD | sed -e \"1,/^\\$/d\") &&\n+\texpected=$(\n+\t\techo signed bugfix\n+\t\techo\n+\t\techo \"Signed-off-by: $(signoff_ident)\"\n+\t\tfixes_for_commits HEAD^^ HEAD^\n+\t) &&\n \ttest \"z$actual\" = \"z$expected\"\n \n '\n-- \n1.8.4.rc3\n"},{"id":"229585","messageId":"526CA7D4.1070904@alum.mit.edu","threadId":"35213","inReplyTo":"20131027013402.GA7146@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2013-10-27T05:42:44Z","receivedAt":"2013-10-27T05:42:44Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/27/2013 02:34 AM, Josh Triplett wrote:\n> Linux Kernel Summit 2013 decided on a commit message convention to\n> identify commits containing bugs fixed by a commit: a \"Fixes:\" line,\n> included in the standard commit footer (along with \"Signed-off-by:\" if\n> present), containing an abbreviated commit hash (at least 12 characters\n> to keep it valid for a long time) and the subject of the commit (for\n> human readers).  This helps people (or automated tools) determine how\n> far to backport a commit.\n> \n> Add a command line option for git commit to automatically construct the\n> \"Fixes:\" line for a commit.  This avoids the need to manually construct\n> that line by copy-pasting the commit hash and subject.\n> \n> Also works with --amend to modify an existing commit's message.  To add\n> a Fixes line to an earlier commit in a series, use rebase -i and add the\n> following line after the existing commit:\n> x git commit --amend --no-edit -f $commit_containing_bug\n> \n> Generalize append_signoff to support appending arbitrary extra lines to\n> a commit in the signoff block; this avoids duplicating the logic to find\n> or construct that block.\n\nI have a few comments and questions about the design of this feature:\n\nFirst of all, let me show my ignorance.  How formalized is the use of\nmetadata lines at the end of a commit message?  I don't remember seeing\ndocumentation about such lines in general (as opposed to documentation\nabout particular types of lines).  Is the format defined well enough\nthat tools that don't know about a particular line could nonetheless\npreserve it correctly?  Is there/should there be a standard recommended\norder of metadata lines?  (For example, should \"Fixes:\" lines always\nappear before \"Signed-off-by\" lines, or vice versa?)  If so, is it\ndocumented somewhere and preserved by tools when such lines are\nadded/modified?  Should there be support for querying such lines?\n\nThere is another thread [1] proposing the addition of a \"Change-Id:\"\nmetadata line, so maybe now would be a good time to discuss such lines\nin general.\n\n\nToo bad your proposed new option sounds so similar to --fixup, which\ndoes something conceptually similar albeit very different in effect.\nThis will likely lead to confusion.  I wonder if the two features could\nbe combined in some way?\n\nThe main difference between the two features is how they are intended to\nbe used: --fixup is to fix a commit that hasn't been pushed yet (where\nthe user intends to squash the commits together), whereas --fixes is to\nmark a commit as a fix to a commit that has already been pushed (where\nthe commits will remain separate).  But there seems to be a common\nconcept here.\n\nFor example, what happens if a --fixes commit is \"rebase -i\"ed at the\nsame time as the commit that it fixes?  It might make sense to do the\nautosquash thing just like with a --fixup/--squash commit.  (Otherwise\nthe SHA-1 in the \"Fixes:\" line will become invalid anyway.)\n\nConversely, I suppose one could ask whether there should be some way to\nprevent \"fixup!\" or \"squash!\" commits from being pushed, at least\nwithout some kind of --force option.  This could of course be enforced\nby a hook but it might be nice to have some protection by default.\n\n\nI see that there a consistency check that the --fixes argument is a\nvalid commit.  But is there/should there be a check that it is an\nancestor of the commit being created?  Is there/should there be a check\nthat both of these facts remain true if the the commit containing it is\nrebased, cherry-picked, etc?\n\nIn workflows that make more use of cherry-picking, it could be that the\noriginal buggy commit was cherry-picked to a different branch.  In this\ncase the user would probably want to cherry-pick the fixing commit to\nthe other branch, too.  But then the commit that it would be fixing\nwould have a different SHA-1 than it did on the original branch.  A\ncheck that the \"Fixes:\" line refers to an ancestor of the current commit\ncould warn against such errors.  (In some cases it might be possible to\nuse cherry-pick's \"-x\" lines to figure out how to rewrite the \"Fixes:\"\nline, but I doubt that would work often enough to be worthwhile.)\n\n\n> Signed-off-by: Josh Triplett <josh@joshtriplett.org>\n> ---\n>  Documentation/git-commit.txt | 12 ++++++++++--\n>  builtin/commit.c             | 29 +++++++++++++++++++++++++++--\n>  sequencer.c                  | 31 +++++++++++++++++++++++--------\n>  sequencer.h                  |  3 +++\n>  t/t7502-commit.sh            | 39 ++++++++++++++++++++++++++++++++++++++-\n>  5 files changed, 101 insertions(+), 13 deletions(-)\n> \n> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\n> index 1a7616c..fcc6ed2 100644\n> --- a/Documentation/git-commit.txt\n> +++ b/Documentation/git-commit.txt\n> @@ -8,8 +8,8 @@ git-commit - Record changes to the repository\n>  SYNOPSIS\n>  --------\n>  [verse]\n> -'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n> -\t   [--dry-run] [(-c | -C | --fixup | --squash) <commit>]\n> +'git commit' [-a | --interactive | --patch] [-s] [-f <commit>] [-v] [-u<mode>]\n> +\t   [--amend] [--dry-run] [(-c | -C | --fixup | --squash) <commit>]\n\nYou mention only \"-f\", not \"--fixes\" here.\n\nBut I don't think that this feature should be given the \"-f\" short\noption, as (a) -f often means \"force\"; (b) it will increase the\nconfusion with --fixup; (c) it just doesn't strike me as being likely to\nbe such a frequently-used option (though if this changes over time the\n\"-f\" option could always be granted to it later).\n\n>  \t   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n>  \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n>  \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n> @@ -156,6 +156,14 @@ OPTIONS\n>  \tAdd Signed-off-by line by the committer at the end of the commit\n>  \tlog message.\n>  \n> +-f <commit>::\n> +--fixes=<commit>::\n> +\tAdd Fixes line for the specified commit at the end of the commit\n> +\tlog message.  This line includes an abbreviated commit hash for\n> +\tthe specified commit; the `core.abbrev` option determines the\n> +\tlength of the abbreviated commit hash used, with a minimum length\n> +\tof 12 hex digits.\n> +\n\nYou might also mention that the \"Fixes:\" line includes the old commit's\nsubject line.\n\n>  -n::\n>  --no-verify::\n>  \tThis option bypasses the pre-commit and commit-msg hooks.\n> diff --git a/builtin/commit.c b/builtin/commit.c\n> index 6ab4605..9bbcd8a 100644\n> --- a/builtin/commit.c\n> +++ b/builtin/commit.c\n> @@ -123,6 +123,7 @@ static int use_editor = 1, include_status = 1;\n>  static int show_ignored_in_status, have_option_m;\n>  static const char *only_include_assumed;\n>  static struct strbuf message = STRBUF_INIT;\n> +static struct strbuf fixes = STRBUF_INIT;\n>  \n>  static enum status_format {\n>  \tSTATUS_FORMAT_NONE = 0,\n> @@ -133,6 +134,28 @@ static enum status_format {\n>  \tSTATUS_FORMAT_UNSPECIFIED\n>  } status_format = STATUS_FORMAT_UNSPECIFIED;\n>  \n> +static int opt_parse_f(const struct option *opt, const char *arg, int unset)\n> +{\n> +\tstruct strbuf *sb = opt->value;\n> +\tif (unset) {\n> +\t\tstrbuf_setlen(sb, 0);\n> +\t} else {\n> +\t\tstruct pretty_print_context ctx = {0};\n> +\t\tstruct commit *commit;\n> +\n> +\t\tcommit = lookup_commit_reference_by_name(arg);\n> +\t\tif (!commit)\n> +\t\t\tdie(_(\"could not lookup commit %s\"), arg);\n> +\t\tctx.output_encoding = get_commit_output_encoding();\n> +\t\tctx.abbrev = DEFAULT_ABBREV;\n> +\t\tif (ctx.abbrev < 12)\n> +\t\t\tctx.abbrev = 12;\n> +\t\tformat_commit_message(commit, \"Fixes: %h ('%s')\\n\", sb, &ctx);\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n>  static int opt_parse_m(const struct option *opt, const char *arg, int unset)\n>  {\n>  \tstruct strbuf *buf = opt->value;\n> @@ -718,7 +741,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n>  \tif (clean_message_contents)\n>  \t\tstripspace(&sb, 0);\n>  \n> -\tif (signoff) {\n> +\tif (signoff || fixes.len) {\n>  \t\t/*\n>  \t\t * See if we have a Conflicts: block at the end. If yes, count\n>  \t\t * its size, so we can ignore it.\n> @@ -742,7 +765,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n>  \t\t\tprevious = eol;\n>  \t\t}\n>  \n> -\t\tappend_signoff(&sb, ignore_footer, 0);\n> +\t\tappend_signoff_extra(&sb, ignore_footer,\n> +\t\t\t\t     signoff ? 0 : APPEND_EXTRA_ONLY, &fixes);\n>  \t}\n>  \n>  \tif (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)\n> @@ -1463,6 +1487,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_STRING(0, \"squash\", &squash_message, N_(\"commit\"), N_(\"use autosquash formatted message to squash specified commit\")),\n>  \t\tOPT_BOOL(0, \"reset-author\", &renew_authorship, N_(\"the commit is authored by me now (used with -C/-c/--amend)\")),\n>  \t\tOPT_BOOL('s', \"signoff\", &signoff, N_(\"add Signed-off-by:\")),\n> +\t\tOPT_CALLBACK('f', \"fixes\", &fixes, N_(\"commit\"), N_(\"add Fixes: for the specified commit\"), opt_parse_f),\n>  \t\tOPT_FILENAME('t', \"template\", &template_file, N_(\"use specified template file\")),\n>  \t\tOPT_BOOL('e', \"edit\", &edit_flag, N_(\"force edit of commit\")),\n>  \t\tOPT_STRING(0, \"cleanup\", &cleanup_arg, N_(\"default\"), N_(\"how to strip spaces and #comments from message\")),\n> diff --git a/sequencer.c b/sequencer.c\n> index 06e52b4..f4cf0e1 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -1135,26 +1135,33 @@ int sequencer_pick_revisions(struct replay_opts *opts)\n>  \treturn pick_commits(todo_list, opts);\n>  }\n>  \n> -void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)\n> +void append_signoff_extra(struct strbuf *msgbuf, int ignore_footer,\n> +\t\t\t  unsigned flag, struct strbuf *extrabuf)\n>  {\n>  \tunsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;\n> +\tunsigned append_sob = !(flag & APPEND_EXTRA_ONLY);\n>  \tstruct strbuf sob = STRBUF_INIT;\n>  \tint has_footer;\n>  \n> -\tstrbuf_addstr(&sob, sign_off_header);\n> -\tstrbuf_addstr(&sob, fmt_name(getenv(\"GIT_COMMITTER_NAME\"),\n> -\t\t\t\tgetenv(\"GIT_COMMITTER_EMAIL\")));\n> -\tstrbuf_addch(&sob, '\\n');\n> +\tif (append_sob) {\n> +\t\tstrbuf_addstr(&sob, sign_off_header);\n> +\t\tstrbuf_addstr(&sob, fmt_name(getenv(\"GIT_COMMITTER_NAME\"),\n> +\t\t\t\t\tgetenv(\"GIT_COMMITTER_EMAIL\")));\n> +\t\tstrbuf_addch(&sob, '\\n');\n> +\t}\n>  \n>  \t/*\n>  \t * If the whole message buffer is equal to the sob, pretend that we\n>  \t * found a conforming footer with a matching sob\n>  \t */\n> -\tif (msgbuf->len - ignore_footer == sob.len &&\n> +\tif (append_sob &&\n> +\t    msgbuf->len - ignore_footer == sob.len &&\n>  \t    !strncmp(msgbuf->buf, sob.buf, sob.len))\n>  \t\thas_footer = 3;\n>  \telse\n> -\t\thas_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);\n> +\t\thas_footer = has_conforming_footer(msgbuf,\n> +\t\t\t\t\t\t   append_sob ? &sob : NULL,\n> +\t\t\t\t\t\t   ignore_footer);\n>  \n>  \tif (!has_footer) {\n>  \t\tconst char *append_newlines = NULL;\n> @@ -1193,9 +1200,17 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)\n>  \t\t\t\tappend_newlines, strlen(append_newlines));\n>  \t}\n>  \n> -\tif (has_footer != 3 && (!no_dup_sob || has_footer != 2))\n> +\tif (append_sob && has_footer != 3 && (!no_dup_sob || has_footer != 2))\n>  \t\tstrbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,\n>  \t\t\t\tsob.buf, sob.len);\n> +\tif (extrabuf)\n> +\t\tstrbuf_insert(msgbuf, msgbuf->len - ignore_footer,\n> +\t\t\t\textrabuf->buf, extrabuf->len);\n>  \n>  \tstrbuf_release(&sob);\n>  }\n> +\n> +void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)\n> +{\n> +\tappend_signoff_extra(msgbuf, ignore_footer, flag, NULL);\n> +}\n> diff --git a/sequencer.h b/sequencer.h\n> index 1fc22dc..8716ad0 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -7,6 +7,7 @@\n>  #define SEQ_OPTS_FILE\t\"sequencer/opts\"\n>  \n>  #define APPEND_SIGNOFF_DEDUP (1u << 0)\n> +#define APPEND_EXTRA_ONLY (1u << 1)\n>  \n>  enum replay_action {\n>  \tREPLAY_REVERT,\n> @@ -51,5 +52,7 @@ int sequencer_pick_revisions(struct replay_opts *opts);\n>  extern const char sign_off_header[];\n>  \n>  void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag);\n> +void append_signoff_extra(struct strbuf *msgbuf, int ignore_footer,\n> +\t\t\t  unsigned flag, struct strbuf *extrabuf);\n>  \n>  #endif\n> diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\n> index 6313da2..12b123a 100755\n> --- a/t/t7502-commit.sh\n> +++ b/t/t7502-commit.sh\n> @@ -137,13 +137,50 @@ test_expect_success 'partial removal' '\n>  \n>  '\n>  \n> +signoff_ident () {\n> +\tgit var GIT_COMMITTER_IDENT | sed -e \"s/>.*/>/\"\n> +}\n> +\n>  test_expect_success 'sign off' '\n>  \n>  \t>positive &&\n>  \tgit add positive &&\n>  \tgit commit -s -m \"thank you\" &&\n>  \tactual=$(git cat-file commit HEAD | sed -ne \"s/Signed-off-by: //p\") &&\n> -\texpected=$(git var GIT_COMMITTER_IDENT | sed -e \"s/>.*/>/\") &&\n> +\texpected=$(signoff_ident) &&\n> +\ttest \"z$actual\" = \"z$expected\"\n> +\n> +'\n> +\n> +fixes_for_commits () {\n> +\tfor commit in \"$@\"; do\n> +\t\tgit -c core.abbrev=12 log -1 --pretty=format:\"Fixes: %h ('%s')%n\" \"$commit\"\n> +\tdone\n> +}\n> +\n> +test_expect_success '--fixes' '\n> +\n> +\techo >>positive &&\n> +\tgit add positive &&\n> +\tgit commit -f HEAD -m \"fix bug\" &&\n> +\tactual=$(git cat-file commit HEAD | sed -e \"1,/^\\$/d\") &&\n> +\texpected=$(echo fix bug; echo; fixes_for_commits HEAD^) &&\n> +\ttest \"z$actual\" = \"z$expected\"\n> +\n> +'\n> +\n> +test_expect_success 'multiple --fixes with signoff' '\n> +\n> +\techo >>positive &&\n> +\tgit add positive &&\n> +\tgit commit -f HEAD^ -f HEAD -s -m \"signed bugfix\" &&\n> +\tactual=$(git cat-file commit HEAD | sed -e \"1,/^\\$/d\") &&\n> +\texpected=$(\n> +\t\techo signed bugfix\n> +\t\techo\n> +\t\techo \"Signed-off-by: $(signoff_ident)\"\n> +\t\tfixes_for_commits HEAD^^ HEAD^\n> +\t) &&\n>  \ttest \"z$actual\" = \"z$expected\"\n>  \n>  '\n> \n\nMichael\n\n[1]\nhttp://thread.gmane.org/gmane.comp.version-control.git/236429/focus=236582\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"229588","messageId":"20131027063708.GC12361@thunk.org","threadId":"35213","inReplyTo":"526CA7D4.1070904@alum.mit.edu","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Theodore Ts'o","fromEmail":"tytso@mit.edu","sentAt":"2013-10-27T06:37:08Z","receivedAt":"2013-10-27T06:37:08Z","isPatch":true,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"One of the uses of the Fixes commit line is so that when we fix a\nsecurity bug that has been in mainline for a while, it can be tricky\nto determine whether it should be backported in to the various stable\nbranches.  For example, let's suppose the security bug (or any bug,\nbut one of the contexts where this came up was for security fixes) was\nintroduced in 3.5, and backported into the 3.2.x kernel series, but\ncouldn't be applied into the 3.2.0 kernel series.  The security fix\nwas introduced in 3.12, and so it would be obvious that it should be\nbackported to the 3.10 kernel series, but it might not be so obvious\nthat it would also be required for the 3.2.x long-term stable series.\n\nSo the inclusion of the Fixes: line provides this critical bit of\ninformation.  It's also useful not just for the long-term stable tree\nmaintainers, but the maintainers of distro kernels would also find it\nto be very useful.\n\n> I see that there a consistency check that the --fixes argument is a\n> valid commit.  But is there/should there be a check that it is an\n> ancestor of the commit being created?  Is there/should there be a check\n> that both of these facts remain true if the the commit containing it is\n> rebased, cherry-picked, etc?\n> \n> In workflows that make more use of cherry-picking, it could be that the\n> original buggy commit was cherry-picked to a different branch.  In this\n> case the user would probably want to cherry-pick the fixing commit to\n> the other branch, too.  But then the commit that it would be fixing\n> would have a different SHA-1 than it did on the original branch.  A\n> check that the \"Fixes:\" line refers to an ancestor of the current commit\n> could warn against such errors.  (In some cases it might be possible to\n> use cherry-pick's \"-x\" lines to figure out how to rewrite the \"Fixes:\"\n> line, but I doubt that would work often enough to be worthwhile.)\n\nI believe that in the discussions we had, it was assumed that the\nFixes: line would reference the commit in the mainline kernel tree.\ni.e., it would always reference the commit which introduced the bug in\n3.5, even if the commit-id after the buggy commit was backported to\n3.2.x would obviously be different.  Presumably the distro kernel\nmaintainer would be able to find the commit in Linus's tree and then\ntry to find the corresponding commit in the distro kernel git tree,\nprobably by doing string searches over \"git log\".\n\nWe could actually do a much more elegant job if we did have the\nconcept of commit identity (i.e., ChangeID's) baked into git.  That\nway, there would be a constant ChangeID that would remain constant not\nonly across revisions of a patch under development, but also when the\ncommit is cherry picked into stable branches.  If we had that, then\ninstead of doing string searches on git log output, we could imagine a\nweb and/or command line interface where given a ChangeID, it would\ntell you which branches or which tags contained the same semantic\npatch.\n\nOf course, as soon as you do that, then if the multiple commits get\nsquashed together, you might need to have to support multiple\nChangeID's associated with one commit, at which point it becomes\nincompatible with Gerrit's use of this feature.\n\nSo we could add all sorts of complexity, but it's not obvious to me\nthat it's worth it.\n\n> First of all, let me show my ignorance.  How formalized is the use of\n> metadata lines at the end of a commit message?  I don't remember seeing\n> documentation about such lines in general (as opposed to documentation\n> about particular types of lines).  Is the format defined well enough\n> that tools that don't know about a particular line could nonetheless\n> preserve it correctly?  Is there/should there be a standard recommended\n> order of metadata lines?  (For example, should \"Fixes:\" lines always\n> appear before \"Signed-off-by\" lines, or vice versa?)  If so, is it\n> documented somewhere and preserved by tools when such lines are\n> added/modified?  Should there be support for querying such lines?\n\nInternally inside Google, we have tools that will assist in forward\nporting local changes from a 3.x based kernel to a 3.y kernel, to make\nsure that all local changes are properly accounted for and none are\naccidentally dropped during the rebase operation.  So we have various\nnew metadata lines that we add internally, for example:\n\nUpstream-3.x-SHA1: <commit-id>\n\tfor commits in newer kernels that have been backported\nOrigin-3.x-SHA1: <commit-id>\n\tto indicate the commit-id of a patch that was forward ported\n\tas part of a rebase operation from 3.x to 3.9\nUpstream-Dropped-3.x-SHA1: <commit-id>\n\tAs part of an empty commit to indicate that a patch that was\n\toriginally in our tree, has since been pushed upstream, so we\n\tcan drop it as part of the rebase to the 3.y kernel.\n\netc.\n\nOther projects have various metadata lines to reference a bug-tracker\nid number; folks may have seen commits with various metadata id's in\npublic git repositories such as:\n\n\tGoogle-Bug-Id: 12345\n\tBugLink: https://bugzilla.kernel.org/show_bug.cgi?id=62261\n\tAddresses-Debian-Bug: #698879\n\nThese are clearly much less standardized, and are probably used more\nfor human consumption than for any kind of automated tooling.  They\nare out there, though, so it indicates that there definitely is a need\nfor such things.\n\nI'm not entirely convinced that it's worth it to try to formalize this\nmore than what we already have, but perhaps there's some killer new\nfeature, such as better gitweb / Gerrit / Bugzilla integration, that\ncould be added if this stuff was more formalized.\n\nCheers,\n\n\t\t\t\t\t- Ted\n"},{"id":"229600","messageId":"20131027071407.GA11683@leaf","threadId":"35213","inReplyTo":"526CA7D4.1070904@alum.mit.edu","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Josh Triplett","fromEmail":"josh@joshtriplett.org","sentAt":"2013-10-27T07:14:07Z","receivedAt":"2013-10-27T07:14:07Z","isPatch":true,"sender":{"key":"josh@joshtriplett.org","avatar":"https://avatars.githubusercontent.com/u/162737?v=4"},"body":"On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n> On 10/27/2013 02:34 AM, Josh Triplett wrote:\n> > Linux Kernel Summit 2013 decided on a commit message convention to\n> > identify commits containing bugs fixed by a commit: a \"Fixes:\" line,\n> > included in the standard commit footer (along with \"Signed-off-by:\" if\n> > present), containing an abbreviated commit hash (at least 12 characters\n> > to keep it valid for a long time) and the subject of the commit (for\n> > human readers).  This helps people (or automated tools) determine how\n> > far to backport a commit.\n> > \n> > Add a command line option for git commit to automatically construct the\n> > \"Fixes:\" line for a commit.  This avoids the need to manually construct\n> > that line by copy-pasting the commit hash and subject.\n> > \n> > Also works with --amend to modify an existing commit's message.  To add\n> > a Fixes line to an earlier commit in a series, use rebase -i and add the\n> > following line after the existing commit:\n> > x git commit --amend --no-edit -f $commit_containing_bug\n> > \n> > Generalize append_signoff to support appending arbitrary extra lines to\n> > a commit in the signoff block; this avoids duplicating the logic to find\n> > or construct that block.\n> \n> I have a few comments and questions about the design of this feature:\n> \n> First of all, let me show my ignorance.  How formalized is the use of\n> metadata lines at the end of a commit message?  I don't remember seeing\n> documentation about such lines in general (as opposed to documentation\n> about particular types of lines).  Is the format defined well enough\n> that tools that don't know about a particular line could nonetheless\n> preserve it correctly?  Is there/should there be a standard recommended\n> order of metadata lines?  (For example, should \"Fixes:\" lines always\n> appear before \"Signed-off-by\" lines, or vice versa?)  If so, is it\n> documented somewhere and preserved by tools when such lines are\n> added/modified?  Should there be support for querying such lines?\n\nWhile it isn't very well documented in git itself, metadata lines are\nquite standardized.  See Documentation/SubmittingPatches and\nDocumentation/development-process/5.Posting in the Linux kernel, for an\nexplanation of \"Reported-by:\", \"Tested-by:\", \"Reviewed-by:\",\n\"Suggested-by:\", and \"Acked-by:\".  And git itself looks for a very\nspecific format; the has_conforming_footer function looks for a footer\nconsisting exclusively of rfc2822-style (email-style) header lines to\ndecide whether to append \"Signed-off-by:\" (and now \"Fixes:\") directly to\nthat block or to create a new block.\n\nI do think there should be additional support for such lines in git,\nsuch as a git commit option to add \"Cc:\" lines (via a --cc-cmd\nlike get_maintainer.pl run at commit time), or fast options in rebase -i\nto append arbitrary footer lines to a commit.\n\n> Too bad your proposed new option sounds so similar to --fixup, which\n> does something conceptually similar albeit very different in effect.\n> This will likely lead to confusion.\n\nGiven that the line is named \"Fixes:\", I don't think the name of the\noption will extend the confusion any further. :)\n\n> I wonder if the two features could\n> be combined in some way?\n> \n> The main difference between the two features is how they are intended to\n> be used: --fixup is to fix a commit that hasn't been pushed yet (where\n> the user intends to squash the commits together), whereas --fixes is to\n> mark a commit as a fix to a commit that has already been pushed (where\n> the commits will remain separate).  But there seems to be a common\n> concept here.\n> \n> For example, what happens if a --fixes commit is \"rebase -i\"ed at the\n> same time as the commit that it fixes?  It might make sense to do the\n> autosquash thing just like with a --fixup/--squash commit.  (Otherwise\n> the SHA-1 in the \"Fixes:\" line will become invalid anyway.)\n\nMost definitely not, no, at least not without an explicit option to\nenable that.  Consider the case of backporting a series of patches and\npreserving the relative history of those patches, to make it easier to\nmatch up a set of patches.  At most, it might be a good idea for\ncherry-pick or similar to provide an updated Fixes tag for the new hash\nof the older commit.  Personally, I'd argue against doing this even with\n--autosquash.  I could see the argument for an --autosquash-fixes, but I\ncan't think of a real-world scenario where what would come up.\n\nGenerally, if history is still editable, you should just squash in the\nfix to the original commit, and if history is no longer editable (which\nis the use case for \"Fixes:\" lines), the squash case simply won't come\nup, offering little point to adding special support for that case.\n\n> Conversely, I suppose one could ask whether there should be some way to\n> prevent \"fixup!\" or \"squash!\" commits from being pushed, at least\n> without some kind of --force option.  This could of course be enforced\n> by a hook but it might be nice to have some protection by default.\n\nThat's a good idea, but unrelated to this patch.  And yes, a hook seems\nlike the right answer there.\n\n> I see that there a consistency check that the --fixes argument is a\n> valid commit.  But is there/should there be a check that it is an\n> ancestor of the commit being created?  Is there/should there be a check\n> that both of these facts remain true if the the commit containing it is\n> rebased, cherry-picked, etc?\n\nThat sounds like a nice future enhancement, sure.  I don't have any plans to\nadd such a check myself, though.  Also note that --fixup and --squash\ndon't have such a check either; if you want to add one, you should add\nit for all three options at once.\n\n> In workflows that make more use of cherry-picking, it could be that the\n> original buggy commit was cherry-picked to a different branch.  In this\n> case the user would probably want to cherry-pick the fixing commit to\n> the other branch, too.  But then the commit that it would be fixing\n> would have a different SHA-1 than it did on the original branch.  A\n> check that the \"Fixes:\" line refers to an ancestor of the current commit\n> could warn against such errors.  (In some cases it might be possible to\n> use cherry-pick's \"-x\" lines to figure out how to rewrite the \"Fixes:\"\n> line, but I doubt that would work often enough to be worthwhile.)\n\nThat also sounds like a plausible future enhancement. :)  I do like the\nidea of warning when a cherry-pick grabs a subsequently-fixed commit and\nnot the fix; that seems quite useful.\n\n> > Signed-off-by: Josh Triplett <josh@joshtriplett.org>\n> > ---\n> >  Documentation/git-commit.txt | 12 ++++++++++--\n> >  builtin/commit.c             | 29 +++++++++++++++++++++++++++--\n> >  sequencer.c                  | 31 +++++++++++++++++++++++--------\n> >  sequencer.h                  |  3 +++\n> >  t/t7502-commit.sh            | 39 ++++++++++++++++++++++++++++++++++++++-\n> >  5 files changed, 101 insertions(+), 13 deletions(-)\n> > \n> > diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\n> > index 1a7616c..fcc6ed2 100644\n> > --- a/Documentation/git-commit.txt\n> > +++ b/Documentation/git-commit.txt\n> > @@ -8,8 +8,8 @@ git-commit - Record changes to the repository\n> >  SYNOPSIS\n> >  --------\n> >  [verse]\n> > -'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n> > -\t   [--dry-run] [(-c | -C | --fixup | --squash) <commit>]\n> > +'git commit' [-a | --interactive | --patch] [-s] [-f <commit>] [-v] [-u<mode>]\n> > +\t   [--amend] [--dry-run] [(-c | -C | --fixup | --squash) <commit>]\n> \n> You mention only \"-f\", not \"--fixes\" here.\n\n-u also has --untracked-files, and -e has --edit; synopsis lines like\nthese normally show the shortest version of each option.\n\n> But I don't think that this feature should be given the \"-f\" short\n> option, as (a) -f often means \"force\"; (b) it will increase the\n> confusion with --fixup; (c) it just doesn't strike me as being likely to\n> be such a frequently-used option (though if this changes over time the\n> \"-f\" option could always be granted to it later).\n\n(a) -n often means --dry-run, but for commit it means --no-verify.\nDifferent commands have different options, and commit doesn't have a\n--force to abbreviate as -f.\n\n(b) If anything, I think the existence of a short option will make the\ndistinction more obvious, since -f and --fixup are much less similar\nthan --fixes and --fixup.  Most users will never type --fixes, making\nconfusion unlikely.\n\n(c) Short option letters tend to be first-come first-serve unless\nthere's a strong reason to do otherwise.  Why reserve 'f' for some\nhypothetical future option that doesn't exist yet?\n\n> >  \t   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n> >  \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n> >  \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n> > @@ -156,6 +156,14 @@ OPTIONS\n> >  \tAdd Signed-off-by line by the committer at the end of the commit\n> >  \tlog message.\n> >  \n> > +-f <commit>::\n> > +--fixes=<commit>::\n> > +\tAdd Fixes line for the specified commit at the end of the commit\n> > +\tlog message.  This line includes an abbreviated commit hash for\n> > +\tthe specified commit; the `core.abbrev` option determines the\n> > +\tlength of the abbreviated commit hash used, with a minimum length\n> > +\tof 12 hex digits.\n> > +\n> \n> You might also mention that the \"Fixes:\" line includes the old commit's\n> subject line.\n\nI only mentioned the abbreviated commit hash because it was necessary to\nexplain the factors affecting hash length.  -s, above, doesn't mention\nthat the Signed-off-by line includes the name and email address of the\ncommitter.\n\n- Josh Triplett\n"},{"id":"229601","messageId":"CANN689HctBYZfU+OQ7movFFWNm6rwUdU7G-ExxhPcBPg1KF8Jw@mail.gmail.com","threadId":"35213","inReplyTo":"20131027071407.GA11683@leaf","subject":"Re: [Ksummit-2013-discuss] [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Michel Lespinasse","fromEmail":"walken@google.com","sentAt":"2013-10-27T08:03:47Z","receivedAt":"2013-10-27T08:03:47Z","isPatch":true,"sender":{"key":"walken@google.com","avatar":null},"body":"On Sun, Oct 27, 2013 at 12:14 AM, Josh Triplett <josh@joshtriplett.org> wrote:\n>> > +-f <commit>::\n>> > +--fixes=<commit>::\n>> > +   Add Fixes line for the specified commit at the end of the commit\n>> > +   log message.  This line includes an abbreviated commit hash for\n>> > +   the specified commit; the `core.abbrev` option determines the\n>> > +   length of the abbreviated commit hash used, with a minimum length\n>> > +   of 12 hex digits.\n>>\n>> You might also mention that the \"Fixes:\" line includes the old commit's\n>> subject line.\n>\n> I only mentioned the abbreviated commit hash because it was necessary to\n> explain the factors affecting hash length.  -s, above, doesn't mention\n> that the Signed-off-by line includes the name and email address of the\n> committer.\n\nI do wonder, if we're going to bake into git the idea that too-short\nabbreviated sha1s don't make sense, why don't we just change the\ncore.abbrev default to 12 everywhere rather than just in this one\ncommand ?\n\n-- \nMichel \"Walken\" Lespinasse\nA program is never fully debugged until the last user dies.\n"},{"id":"229602","messageId":"874n83m8xv.fsf@linux-k42r.v.cablecom.net","threadId":"35213","inReplyTo":"20131027071407.GA11683@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Thomas Rast","fromEmail":"tr@thomasrast.ch","sentAt":"2013-10-27T08:09:32Z","receivedAt":"2013-10-27T08:09:32Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Josh Triplett <josh@joshtriplett.org> writes:\n\n> On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n>> But I don't think that this feature should be given the \"-f\" short\n>> option, as (a) -f often means \"force\"; (b) it will increase the\n>> confusion with --fixup; (c) it just doesn't strike me as being likely to\n>> be such a frequently-used option (though if this changes over time the\n>> \"-f\" option could always be granted to it later).\n>\n> (a) -n often means --dry-run, but for commit it means --no-verify.\n> Different commands have different options, and commit doesn't have a\n> --force to abbreviate as -f.\n>\n> (b) If anything, I think the existence of a short option will make the\n> distinction more obvious, since -f and --fixup are much less similar\n> than --fixes and --fixup.  Most users will never type --fixes, making\n> confusion unlikely.\n>\n> (c) Short option letters tend to be first-come first-serve unless\n> there's a strong reason to do otherwise.  Why reserve 'f' for some\n> hypothetical future option that doesn't exist yet?\n\nNo, lately the direction in Git has been to avoid giving options a\none-letter shorthand until they have proven so useful that people using\nit in the wild start to suggest that it should have one.\n\nSee e.g.\n\n  http://article.gmane.org/gmane.comp.version-control.git/233998\n  http://article.gmane.org/gmane.comp.version-control.git/168748\n\nA much better argument would be if it was already clear from the specs\nlaid out for Fixes that n% of the kernel commits will end up having this\nfooter, and thus kernel hackers will spend x amount of time spelling out\n--fixes and/or confusing it with --fixup to much headache.\n\n-- \nThomas Rast\ntr@thomasrast.ch\n"},{"id":"229603","messageId":"CACsJy8CKUygqbMKK_mkOY2C5whqHN=d+6ME_jkXpPebxeSd3Tw@mail.gmail.com","threadId":"35213","inReplyTo":"20131027013402.GA7146@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-27T08:33:19Z","receivedAt":"2013-10-27T08:33:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sun, Oct 27, 2013 at 8:34 AM, Josh Triplett <josh@joshtriplett.org> wrote:\n> Add a command line option for git commit to automatically construct the\n> \"Fixes:\" line for a commit.  This avoids the need to manually construct\n> that line by copy-pasting the commit hash and subject.\n\nBut you still have to copy/paste the hash in command line. I wonder if\nwe should approach it differently: the user writes \"Fixes: <hash>\" in\nthe commit message, then git detects these lines and expands them\nusing a user-configured format. For the kernel circle, the format\nwould be \"%h ('%s')\" (I'll need to think how to let the user say\n\"minimum 12 chars\").\n\nOther projects need to refer to old commits sometimes in commit\nmessages too and this could be extended further to expand inline\nabbrev sha-1s, but to not break the text alignment badly, maybe\nfootnotes will be created to store subjects and stuff, rather than do\ninline expansion. For example,\n\n  commit 1232343 breaks something.....\n\nbecomes\n\n  comit 1232343 [1] breaks something....\n\n  [1] 123234332131 (do something wrong - at this date)\n-- \nDuy\n"},{"id":"229604","messageId":"20131027091318.GA13149@leaf","threadId":"35213","inReplyTo":"CACsJy8CKUygqbMKK_mkOY2C5whqHN=d+6ME_jkXpPebxeSd3Tw@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Josh Triplett","fromEmail":"josh@joshtriplett.org","sentAt":"2013-10-27T09:13:19Z","receivedAt":"2013-10-27T09:13:19Z","isPatch":true,"sender":{"key":"josh@joshtriplett.org","avatar":"https://avatars.githubusercontent.com/u/162737?v=4"},"body":"On Sun, Oct 27, 2013 at 03:33:19PM +0700, Duy Nguyen wrote:\n> On Sun, Oct 27, 2013 at 8:34 AM, Josh Triplett <josh@joshtriplett.org> wrote:\n> > Add a command line option for git commit to automatically construct the\n> > \"Fixes:\" line for a commit.  This avoids the need to manually construct\n> > that line by copy-pasting the commit hash and subject.\n> \n> But you still have to copy/paste the hash in command line. I wonder if\n> we should approach it differently: the user writes \"Fixes: <hash>\" in\n> the commit message, then git detects these lines and expands them\n\nThen you have to copy/paste the hash into the commit message; either way\nyou're not getting around that.  However, note that you can pass a ref\ninstead of a commit hash, if you happen to have saved a tag pointing to\nthe broken ref.  (Or, for instance, if you have it from a bisection.)\n\nI could imagine supporting that approach in addition (via a commit-msg\nhook, for instance), but I'd still like to have the command-line option\nto git commit.\n\n> using a user-configured format. For the kernel circle, the format\n> would be \"%h ('%s')\" (I'll need to think how to let the user say\n> \"minimum 12 chars\").\n\nI considered making the format configurable, and that's easy enough to\ndo, but I wanted to start out with the simplest patch that achieved the\ngoal, on the theory that it's easy to add configurability later if\nanyone actually needs it.\n\n> Other projects need to refer to old commits sometimes in commit\n> messages too and this could be extended further to expand inline\n> abbrev sha-1s, but to not break the text alignment badly, maybe\n> footnotes will be created to store subjects and stuff, rather than do\n> inline expansion. For example,\n> \n>   commit 1232343 breaks something.....\n> \n> becomes\n> \n>   comit 1232343 [1] breaks something....\n> \n>   [1] 123234332131 (do something wrong - at this date)\n\nEasily done via a commit-msg hook, if you want that.\n\n- Josh Triplett\n"},{"id":"229605","messageId":"20131027092019.GB13149@leaf","threadId":"35213","inReplyTo":"874n83m8xv.fsf@linux-k42r.v.cablecom.net","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Josh Triplett","fromEmail":"josh@joshtriplett.org","sentAt":"2013-10-27T09:20:20Z","receivedAt":"2013-10-27T09:20:20Z","isPatch":true,"sender":{"key":"josh@joshtriplett.org","avatar":"https://avatars.githubusercontent.com/u/162737?v=4"},"body":"On Sun, Oct 27, 2013 at 09:09:32AM +0100, Thomas Rast wrote:\n> Josh Triplett <josh@joshtriplett.org> writes:\n> \n> > On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n> >> But I don't think that this feature should be given the \"-f\" short\n> >> option, as (a) -f often means \"force\"; (b) it will increase the\n> >> confusion with --fixup; (c) it just doesn't strike me as being likely to\n> >> be such a frequently-used option (though if this changes over time the\n> >> \"-f\" option could always be granted to it later).\n> >\n> > (a) -n often means --dry-run, but for commit it means --no-verify.\n> > Different commands have different options, and commit doesn't have a\n> > --force to abbreviate as -f.\n> >\n> > (b) If anything, I think the existence of a short option will make the\n> > distinction more obvious, since -f and --fixup are much less similar\n> > than --fixes and --fixup.  Most users will never type --fixes, making\n> > confusion unlikely.\n> >\n> > (c) Short option letters tend to be first-come first-serve unless\n> > there's a strong reason to do otherwise.  Why reserve 'f' for some\n> > hypothetical future option that doesn't exist yet?\n> \n> No, lately the direction in Git has been to avoid giving options a\n> one-letter shorthand until they have proven so useful that people using\n> it in the wild start to suggest that it should have one.\n> \n> See e.g.\n> \n>   http://article.gmane.org/gmane.comp.version-control.git/233998\n>   http://article.gmane.org/gmane.comp.version-control.git/168748\n\nFair enough; easy enough to drop -f if that's the consensus.  However...\n\n> A much better argument would be if it was already clear from the specs\n> laid out for Fixes that n% of the kernel commits will end up having this\n> footer, and thus kernel hackers will spend x amount of time spelling out\n> --fixes and/or confusing it with --fixup to much headache.\n\n...good suggestion:\n\n~/src/linux$ git log --grep='stable@' --oneline --since='1 year ago' | wc -l\n2769\n~/src/linux$ git log --grep='stable@' --oneline --since='1 year ago' --pretty=format:%an | sort -u | wc -l\n839\n\nSeveral thousand commits per year by hundreds of unique people seems\nlike enough to justify a short option.\n\n- Josh Triplett\n"},{"id":"229606","messageId":"20131027092313.GC13149@leaf","threadId":"35213","inReplyTo":"CANN689HctBYZfU+OQ7movFFWNm6rwUdU7G-ExxhPcBPg1KF8Jw@mail.gmail.com","subject":"Re: [Ksummit-2013-discuss] [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Josh Triplett","fromEmail":"josh@joshtriplett.org","sentAt":"2013-10-27T09:23:13Z","receivedAt":"2013-10-27T09:23:13Z","isPatch":true,"sender":{"key":"josh@joshtriplett.org","avatar":"https://avatars.githubusercontent.com/u/162737?v=4"},"body":"On Sun, Oct 27, 2013 at 01:03:47AM -0700, Michel Lespinasse wrote:\n> On Sun, Oct 27, 2013 at 12:14 AM, Josh Triplett <josh@joshtriplett.org> wrote:\n> >> > +-f <commit>::\n> >> > +--fixes=<commit>::\n> >> > +   Add Fixes line for the specified commit at the end of the commit\n> >> > +   log message.  This line includes an abbreviated commit hash for\n> >> > +   the specified commit; the `core.abbrev` option determines the\n> >> > +   length of the abbreviated commit hash used, with a minimum length\n> >> > +   of 12 hex digits.\n> >>\n> >> You might also mention that the \"Fixes:\" line includes the old commit's\n> >> subject line.\n> >\n> > I only mentioned the abbreviated commit hash because it was necessary to\n> > explain the factors affecting hash length.  -s, above, doesn't mention\n> > that the Signed-off-by line includes the name and email address of the\n> > committer.\n> \n> I do wonder, if we're going to bake into git the idea that too-short\n> abbreviated sha1s don't make sense, why don't we just change the\n> core.abbrev default to 12 everywhere rather than just in this one\n> command ?\n\nYou won't get any argument from me on that one.  I personally would have\nargued for making the hashes 40 characters always, but in any case\nbumping up the default (and minimum) for core.abbrev seems entirely\nsensible.\n\n- Josh Triplett\n"},{"id":"229607","messageId":"526CDC5C.40208@googlemail.com","threadId":"35213","inReplyTo":"874n83m8xv.fsf@linux-k42r.v.cablecom.net","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-10-27T09:26:52Z","receivedAt":"2013-10-27T09:26:52Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On 10/27/2013 09:09 AM, Thomas Rast wrote:\n> Josh Triplett <josh@joshtriplett.org> writes:\n> \n>> On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n>>> But I don't think that this feature should be given the \"-f\" short\n>>> option, as (a) -f often means \"force\"; (b) it will increase the\n>>> confusion with --fixup; (c) it just doesn't strike me as being likely to\n>>> be such a frequently-used option (though if this changes over time the\n>>> \"-f\" option could always be granted to it later).\n>>\n>> (a) -n often means --dry-run, but for commit it means --no-verify.\n>> Different commands have different options, and commit doesn't have a\n>> --force to abbreviate as -f.\n>>\n>> (b) If anything, I think the existence of a short option will make the\n>> distinction more obvious, since -f and --fixup are much less similar\n>> than --fixes and --fixup.  Most users will never type --fixes, making\n>> confusion unlikely.\n>>\n>> (c) Short option letters tend to be first-come first-serve unless\n>> there's a strong reason to do otherwise.  Why reserve 'f' for some\n>> hypothetical future option that doesn't exist yet?\n> \n> No, lately the direction in Git has been to avoid giving options a\n> one-letter shorthand until they have proven so useful that people using\n> it in the wild start to suggest that it should have one.\n> \n> See e.g.\n> \n>   http://article.gmane.org/gmane.comp.version-control.git/233998\n>   http://article.gmane.org/gmane.comp.version-control.git/168748\n> \n> A much better argument would be if it was already clear from the specs\n> laid out for Fixes that n% of the kernel commits will end up having this\n> footer, and thus kernel hackers will spend x amount of time spelling out\n> --fixes and/or confusing it with --fixup to much headache.\n> \n\nI assembled an overview table, which plots the long options of \ngit commands by the short letters.\nHere it is:\n(Best viewed with a *large* screen and monospace font)\n\n         Name\\short |              C |               B |              A |             G |              F |                E |               H |                    O |              N |                    L |         S |        R |            P |                 W |                X |               c |       b |         a |       g |      f |        e |            d |             k |            i |                 o |             n |         m |                   l |          s |        r |      q |              p |            w |             v |                u |         t |     z |        x |       3 |     2\n             status |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |  branch |           |         |        |          |              |               |              |                   |               |           |                     |      short |          |        |                |              |       verbose |  untracked-files |           |  null |          |         |          status\n               help |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |       all |  guides |        |          |              |               |         info |                   |               |       man |                     |            |          |        |                |          web |               |                  |           |       |          |         |          help\n               show |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          show\n             revert |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |  strategy-option |                 |         |           |         |        |     edit |              |               |              |                   |     no-commit |  mainline |                     |    signoff |          |        |                |              |               |                  |           |       |          |         |          revert\n       pack-objects |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          pack-objects\n       prune-packed |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |       dry-run |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          prune-packed\n            replace |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |          |       delete |               |              |                   |               |           |                list |            |          |        |                |              |               |                  |           |       |          |         |          replace\n           show-ref |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |  dereference |               |              |                   |               |           |                     |       hash |          |  quiet |                |              |               |                  |           |       |          |         |          show-ref\n                tag |                |                 |                |               |           file |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |  annotate |         |  force |          |       delete |               |              |                   |               |   message |                list |       sign |          |        |                |              |        verify |       local-user |           |       |          |         |          tag\n                 gc |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          gc\n              apply |                |                 |                |               |                |                  |                 |                      |                |                      |           |  reverse |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |    3way |          apply\n       fsck-objects |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          fsck-objects\n            archive |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |            output |               |           |                     |            |          |        |                |              |               |                  |           |       |          |         |          archive\n         merge-file |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |         stdout |              |               |                  |           |       |          |         |          merge-file\n                log |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          log\n             cherry |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          cherry\n     checkout-index |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |       all |         |  force |          |              |               |              |                   |     no-create |           |                     |            |          |  quiet |                |              |               |            index |           |       |          |         |          checkout-index\n         check-attr |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |       all |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |               |                  |           |       |          |         |          check-attr\n             reflog |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          reflog\n             branch |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |       all |         |  force |          |       delete |               |              |                   |               |      move |       create-reflog |            |  remotes |  quiet |                |              |       verbose |  set-upstream-to |     track |       |          |         |          branch\n            ls-tree |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                long |            |          |        |                |              |               |                  |           |       |          |         |          ls-tree\n                 rm |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |          |              |               |              |                   |       dry-run |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          rm\n             config |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |   file |     edit |              |               |              |                   |               |           |                list |            |          |        |                |              |               |                  |           |  null |          |         |          config\n             remote |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          remote\n            init-db |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          init-db\n         merge-base |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |       all |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |               |                  |           |       |          |         |          merge-base\n       for-each-ref |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |      shell |          |        |           perl |              |               |                  |           |       |          |         |          for-each-ref\n              clone |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |          config |  branch |           |         |        |          |              |               |              |            origin |   no-checkout |           |               local |     shared |          |  quiet |                |              |       verbose |      upload-pack |           |       |          |         |          clone\n      count-objects |                |                 |                |               |                |                  |  human-readable |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          count-objects\n               fsck |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          fsck\n        verify-pack |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |  stat-only |          |        |                |              |       verbose |                  |           |       |          |         |          verify-pack\n update-server-info |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |          |              |               |              |                   |               |           |                     |            |          |        |                |              |               |                  |           |       |          |         |          update-server-info\n                add |                |                 |            all |               |                |                  |                 |                      |  intent-to-add |                      |           |          |              |                   |                  |                 |         |           |         |  force |     edit |              |               |  interactive |                   |       dry-run |           |                     |            |          |        |          patch |              |       verbose |           update |           |       |          |         |          add\n        whatchanged |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          whatchanged\n        cherry-pick |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |  strategy-option |                 |         |           |         |        |     edit |              |               |              |                   |     no-commit |  mainline |                     |    signoff |          |        |                |              |               |                  |           |       |          |         |          cherry-pick\n          read-tree |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |       dry-run |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          read-tree\n       format-patch |                |                 |                |               |                |                  |                 |                      |    no-numbered |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |  keep-subject |              |  output-directory |      numbered |           |                     |    signoff |          |  quiet |        no-stat |              |  reroll-count |                  |           |       |          |         |          format-patch\n              stage |                |                 |            all |               |                |                  |                 |                      |  intent-to-add |                      |           |          |              |                   |                  |                 |         |           |         |  force |     edit |              |               |  interactive |                   |       dry-run |           |                     |            |          |        |          patch |              |       verbose |           update |           |       |          |         |          stage\n              reset |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |          patch |              |               |                  |           |       |          |         |          reset\n       check-ignore |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |  non-matching |           |                     |            |          |  quiet |                |              |       verbose |                  |           |       |          |         |          check-ignore\n               grep |        context |  before-context |  after-context |  basic-regexp |  fixed-strings |  extended-regexp |                 |  open-files-in-pager |                |  files-without-match |           |          |  perl-regexp |  function-context |                  |           count |         |      text |         |        |          |              |               |  ignore-case |                   |   line-number |           |  files-with-matches |            |          |  quiet |  show-function |  word-regexp |  invert-match |                  |           |  null |          |         |          grep\n              prune |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |       dry-run |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          prune\n       symbolic-ref |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |       delete |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          symbolic-ref\n           checkout |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |          |              |               |              |                   |               |     merge |                     |            |          |  quiet |          patch |              |               |                  |     track |       |          |  theirs |  ours    checkout\n             repack |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |               local |            |          |  quiet |                |              |               |                  |           |       |          |         |          repack\n               init |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          init\n              merge |                |                 |                |               |                |                  |                 |                      |                |                      |  gpg-sign |          |              |                   |  strategy-option |                 |         |           |         |        |     edit |              |               |              |                   |               |   message |                     |   strategy |          |  quiet |                |              |       verbose |                  |           |       |          |         |          merge\n                 mv |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |          |              |               |              |                   |       dry-run |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          mv\n           ls-files |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |     exclude-from |          cached |         |           |         |        |          |      deleted |        killed |      ignored |            others |               |  modified |                     |      stage |          |        |                |              |               |         unmerged |           |       |  exclude |         |          ls-files\n              clean |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |  exclude |              |               |  interactive |                   |       dry-run |           |                     |            |          |  quiet |                |              |               |                  |           |       |          |         |          clean\n        show-branch |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |       all |  reflog |        |          |              |               |              |                   |               |           |                     |            |  remotes |        |                |              |               |                  |           |       |          |         |          show-branch\n               push |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |  force |          |              |               |              |                   |       dry-run |           |                     |            |          |  quiet |                |              |       verbose |     set-upstream |           |       |          |         |          push\n             commit |  reuse-message |                 |                |               |           file |                  |                 |                      |                |                      |  gpg-sign |          |              |                   |                  |  reedit-message |         |       all |         |        |     edit |              |               |      include |              only |     no-verify |   message |                     |    signoff |          |  quiet |          patch |              |       verbose |  untracked-files |  template |  null |          |         |          commit\n         verify-tag |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |           |                     |            |          |        |                |              |       verbose |                  |           |       |          |         |          verify-tag\n      fmt-merge-msg |                |                 |                |               |           file |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |           |         |        |          |              |               |              |                   |               |   message |                     |            |          |        |                |              |               |                  |           |       |          |         |          fmt-merge-msg\n              fetch |                |                 |                |               |                |                  |                 |                      |                |                      |           |          |              |                   |                  |                 |         |    append |         |  force |          |              |          keep |              |                   |               |  multiple |                     |            |          |  quiet |          prune |              |       verbose |   update-head-ok |      tags |       |          |         |          fetch\n\n\n(In case thunderbird messes it up, here it is again http://pastebin.com/raw.php?i=JBci2Krx)\n\nAs you can see, f is always --force except for git-config, where it is --file\n"},{"id":"229610","messageId":"CALKQrgc7a+p5eebJErcGdA3QDyvdHEaef36RhZocQp9LjDUeeg@mail.gmail.com","threadId":"35213","inReplyTo":"20131027092019.GB13149@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-10-27T10:59:53Z","receivedAt":"2013-10-27T10:59:53Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Sun, Oct 27, 2013 at 10:20 AM, Josh Triplett <josh@joshtriplett.org> wrote:\n> On Sun, Oct 27, 2013 at 09:09:32AM +0100, Thomas Rast wrote:\n>> Josh Triplett <josh@joshtriplett.org> writes:\n>> > On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n>> >> But I don't think that this feature should be given the \"-f\" short\n>> >> option, as (a) -f often means \"force\"; (b) it will increase the\n>> >> confusion with --fixup; (c) it just doesn't strike me as being likely to\n>> >> be such a frequently-used option (though if this changes over time the\n>> >> \"-f\" option could always be granted to it later).\n>> >\n>> > (a) -n often means --dry-run, but for commit it means --no-verify.\n>> > Different commands have different options, and commit doesn't have a\n>> > --force to abbreviate as -f.\n>> >\n>> > (b) If anything, I think the existence of a short option will make the\n>> > distinction more obvious, since -f and --fixup are much less similar\n>> > than --fixes and --fixup.  Most users will never type --fixes, making\n>> > confusion unlikely.\n>> >\n>> > (c) Short option letters tend to be first-come first-serve unless\n>> > there's a strong reason to do otherwise.  Why reserve 'f' for some\n>> > hypothetical future option that doesn't exist yet?\n>>\n>> No, lately the direction in Git has been to avoid giving options a\n>> one-letter shorthand until they have proven so useful that people using\n>> it in the wild start to suggest that it should have one.\n>>\n>> See e.g.\n>>\n>>   http://article.gmane.org/gmane.comp.version-control.git/233998\n>>   http://article.gmane.org/gmane.comp.version-control.git/168748\n>\n> Fair enough; easy enough to drop -f if that's the consensus.  However...\n>\n>> A much better argument would be if it was already clear from the specs\n>> laid out for Fixes that n% of the kernel commits will end up having this\n>> footer, and thus kernel hackers will spend x amount of time spelling out\n>> --fixes and/or confusing it with --fixup to much headache.\n>\n> ...good suggestion:\n>\n> ~/src/linux$ git log --grep='stable@' --oneline --since='1 year ago' | wc -l\n> 2769\n> ~/src/linux$ git log --grep='stable@' --oneline --since='1 year ago' --pretty=format:%an | sort -u | wc -l\n> 839\n>\n> Several thousand commits per year by hundreds of unique people seems\n> like enough to justify a short option.\n\nI think this can be solved just as well (if not better) using a\ncombination of a commit message template (or a prepare-commit-msg\nhook) and a commit-msg hook.\n\nThe former appends a section of commonly-used RFC822-style headers\n(with empty values) to the bottom of the commit message, e.g. some\nvariation on this:\n\n  Fixes:\n  Reported-by:\n  Suggested-by:\n  Improved-by:\n  Acked-by:\n  Reviewed-by:\n  Tested-by:\n  Signed-off-by:\n\nThen the user (in addition to writing the commit message above this\nblock) may choose to fill in one or more values in this \"form\", e.g.\nlike this:\n\n  My commit subject\n\n  This is the commit message body.\n\n  Fixes: 1234beef\n  Reported-by: Joe User <j.user@example.com>\n  Suggested-by:\n  Improved-by: Joe Hacker <j.hacker@example.com>\n  Acked-by:\n  Reviewed-by:\n  Tested-by: Joe Tester <j.tester@example.com>\n  Signed-off-by: Myself <myself@example.com>\n\nThen, the commit-msg hook can clean up and transform this into the\nfinal commit message:\n\n  My commit subject\n\n  This is the commit message body.\n\n  Fixes: 1234beef56 (Commit message summmary)\n  Reported-by: Joe User <j.user@example.com>\n  Improved-by: Joe Hacker <j.hacker@example.com>\n  Tested-by: Joe Tester <j.tester@example.com>\n  Signed-off-by: Myself <myself@example.com>\n\nHere, the commit-msg hook removes the fields that were not filled in,\nand performs additional filtering on the \"Fixes\" line (Adding commit\nmessage summary). The filtering could also resolve ref names, so that\nif you had refs/tags/security-bug pointing at the buggy commit, then:\n\n  Fixes: security-bug\n\nwould be expanded/DWIMed into:\n\n  Fixes: 1234beef56 (Commit message summmary)\n\nObviously, any other fancy processing you want to do into in the\ncommit-msg hook can be done as well, adding footnotes, checking that\ncommits are present in the ancestry, etc, etc.\n\nThree good reasons to go this way:\n\n 1. If the user forgets to supply command-line options like -s,\n--fixes, etc, there is a nice reminder in the supplied form.\n\n 2. No need to add any command-line options to Git.\n\n 3. The whole mechanism is controlled by the project. The kernel folks\ncan do whatever they want in their templates/hooks without needing\nchanges to the Git project.\n\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"229614","messageId":"87zjpuznf1.fsf@thomasrast.ch","threadId":"35213","inReplyTo":"526CDC5C.40208@googlemail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Thomas Rast","fromEmail":"tr@thomasrast.ch","sentAt":"2013-10-27T16:30:42Z","receivedAt":"2013-10-27T16:30:42Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Stefan Beller <stefanbeller@googlemail.com> writes:\n\n> I assembled an overview table, which plots the long options of \n> git commands by the short letters.\n[...]\n> (In case thunderbird messes it up, here it is again http://pastebin.com/raw.php?i=JBci2Krx)\n>\n> As you can see, f is always --force except for git-config, where it is --file\n\nWoah!  Impressive work.  Did you autogenerate this?  If so, can we have\nit as a small make target somewhere?  If not, can you send a patch to\nput your table in Documentation somewhere?\n\n-- \nThomas Rast\ntr@thomasrast.ch\n"},{"id":"229615","messageId":"526D4750.7040804@googlemail.com","threadId":"35213","inReplyTo":"87zjpuznf1.fsf@thomasrast.ch","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-10-27T17:03:12Z","receivedAt":"2013-10-27T17:03:12Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On 10/27/2013 05:30 PM, Thomas Rast wrote:\n> Stefan Beller <stefanbeller@googlemail.com> writes:\n> \n>> I assembled an overview table, which plots the long options of \n>> git commands by the short letters.\n> [...]\n>> (In case thunderbird messes it up, here it is again http://pastebin.com/raw.php?i=JBci2Krx)\n>>\n>> As you can see, f is always --force except for git-config, where it is --file\n> \n> Woah!  Impressive work.  Did you autogenerate this?  If so, can we have\n> it as a small make target somewhere?  If not, can you send a patch to\n> put your table in Documentation somewhere?\n> \n\nI thought about generating it by parsing the man pages, \nbut I felt it would not be reliable enough and quite time consuming \nto come up with a parser. Parsing the C sources however also seemed time consuming,\nso I decided to come up with this patch:\n--8<--\nSubject: [PATCH] parse-options: print all options having short and long form and exit\n\nThis patch basically only prints all options which have a long and a short form\nand then aborts the program. A typical output looks like this:\n./git-add\nadd,  n, dry-run\nadd,  v, verbose\nadd,  i, interactive\nadd,  p, patch\nadd,  e, edit\nadd,  f, force\nadd,  u, update\nadd,  N, intent-to-add\nadd,  A, all\n---\n parse-options.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 62e9b1c..b356ca9 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -500,6 +500,12 @@ int parse_options(int argc, const char **argv, const char *prefix,\n {\n \tstruct parse_opt_ctx_t ctx;\n \n+\tfor (; options->type != OPTION_END; options++) {\n+\t\tif (options->long_name && options->short_name)\n+\t\t\tprintf(\"%s,  %c, %s\\n\", argv[0], options->short_name, options->long_name);\n+\t}\n+\texit(1);\n+\n \tparse_options_start(&ctx, argc, argv, prefix, options, flags);\n \tswitch (parse_options_step(&ctx, options, usagestr)) {\n \tcase PARSE_OPT_HELP:\n-- \n1.8.4.1.605.g23c6912\n\n\nUnfortunately we can only check git commands, which are written in C. \nYou'll notice all the perl/shell written commands are missing (rebase, etc).\nAlso a few commands written in C cannot easily be picked up, as they do stuff\nbefore calling parse_options. [typically something like \"if (argc != 4) print_usage();\"]\nThese commands are also not contained.\n\nThe generation of the table however was just a little python:\n\n--8<--\n#!/usr/bin/python\n\ncmds=\"\"\"git-add\ngit-apply\ngit-archive\ngit-branch\ngit-check-attr\ngit-check-ignore\ngit-check-mailmap\ngit-checkout\ngit-checkout-index\ngit-cherry\ngit-cherry-pick\ngit-clean\ngit-clone\ngit-column\ngit-commit\ngit-config\ngit-count-objects\ngit-credential-cache\ngit-credential-store\ngit-describe\ngit-fetch\ngit-fmt-merge-msg\ngit-for-each-ref\ngit-format-patch\ngit-fsck\ngit-fsck-objects\ngit-gc\ngit-grep\ngit-hash-object\ngit-help\ngit-init\ngit-init-db\ngit-log\ngit-ls-files\ngit-ls-tree\ngit-merge\ngit-merge-base\ngit-merge-file\ngit-merge-ours\ngit-mktree\ngit-mv\ngit-name-rev\ngit-notes\ngit-pack-objects\ngit-pack-refs\ngit-prune\ngit-prune-packed\ngit-push\ngit-read-tree\ngit-reflog\ngit-remote\ngit-repack\ngit-replace\ngit-rerere\ngit-reset\ngit-revert\ngit-rev-parse\ngit-rm\ngit-show\ngit-show-branch\ngit-show-ref\ngit-stage\ngit-status\ngit-symbolic-ref\ngit-tag\ngit-update-index\ngit-update-ref\ngit-update-server-info\ngit-verify-pack\ngit-verify-tag\ngit-whatchanged\ngit-write-tree\"\"\"\n\nimport subprocess\n\nshorts={}\ncmdoptions={}\n\nfor cmd in cmds.split(\"\\n\"):\n\tp = subprocess.Popen(\"./\"+cmd, stdout=subprocess.PIPE)\n\tp.wait()\n\tlines = p.stdout.read()\n\tfor line in lines.split(\"\\n\"):\n\t\tif not len(line):\n\t\t\tcontinue\n\n\t\tname, short, long = line.split(\",\")\n\t\tif not short in shorts:\n\t\t\tshorts[short] = len(long)\n\t\telse:\n\t\t\tshorts[short] = max(shorts[short], len(long))\n\n\t\tif not name in cmdoptions:\n\t\t\tcmdoptions[name] = {}\n\t\tcmdoptions[name][short] = long\n\nlongest_cmd = 0\nfor cmd in cmdoptions:\n\tlongest_cmd = max(longest_cmd, len(cmd))\n\nprint \" \"*(longest_cmd-len(\"Name\\\\short\")), \"Name\\\\short\",\n\nfor short in shorts:\n\tprint \"|\" + \" \"*(1+shorts[short]-len(short)) + short,\nprint\n\nfor cmd in cmdoptions:\n\tprint \" \"*(longest_cmd-len(cmd)), cmd,\n\tfor short in shorts:\n\t\ts = \"\"\n\t\tif short in cmdoptions[cmd]:\n\t\t\ts = cmdoptions[cmd][short]\n\t\tprint \"|\" + \" \"*(1+shorts[short]-len(s)) + s,\n\tprint \"  \", cmd\n\n--8<--\n\nI am not sure if we should add such code to the git code base, as it would need some cleanup. \nThe existing table however would become outdated fast?\nSo I do not have a good idea, how such a table could be easily incorporated and kept up to date.\n\nThanks,\nStefan\n"},{"id":"229617","messageId":"CAP8UFD3MZJKWUbdZqrSwoatpnx73MTpiwSkxPHYDagGjMSqJNw@mail.gmail.com","threadId":"35213","inReplyTo":"CALKQrgc7a+p5eebJErcGdA3QDyvdHEaef36RhZocQp9LjDUeeg@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2013-10-27T19:10:36Z","receivedAt":"2013-10-27T19:10:36Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"[Sorry I already sent the reply below to Johan only instead of everyone.]\n\nHi Johan,\n\nOn Sun, Oct 27, 2013 at 11:59 AM, Johan Herland <johan@herland.net> wrote:\n> On Sun, Oct 27, 2013 at 10:20 AM, Josh Triplett <josh@joshtriplett.org> wrote:\n>>\n>> ...good suggestion:\n>>\n>> ~/src/linux$ git log --grep='stable@' --oneline --since='1 year ago' | wc -l\n>> 2769\n>> ~/src/linux$ git log --grep='stable@' --oneline --since='1 year ago' --pretty=format:%an | sort -u | wc -l\n>> 839\n>>\n>> Several thousand commits per year by hundreds of unique people seems\n>> like enough to justify a short option.\n>\n> I think this can be solved just as well (if not better) using a\n> combination of a commit message template (or a prepare-commit-msg\n> hook) and a commit-msg hook.\n\nYour suggestion is very good, and it is not incompatible with command\nline options.\nSo both could be implemented and even work together.\n\nFor example if \"-f ack:Peff\" was passed to the command line, \"git commit\" could\nlookup in the commit message template and see if there is one\nRFC822-style header\nthat starts with or contains \"ack\" (discarding case) and it could look\nin some previous commits if\nthere is an author whose name contains \"Peff\" (discarding case) and if\nit is the case\nit could append the following to the bottom of the commit message:\n\nFixes:\nReported-by:\nSuggested-by:\nImproved-by:\nAcked-by: Jeff King <peff@peff.net>\nReviewed-by:\nTested-by:\nSigned-off-by: Myself <myself@example.com>\n\n(I suppose that the sob is automatically added.)\n\nIt would work also with \"-f fix:security-bug\" and would put something\nlike what you suggested:\n\nFixes: 1234beef56 (Commit message summmary)\n\n> Then, the commit-msg hook can clean up and transform this into the\n> final commit message:\n>\n>   My commit subject\n>\n>   This is the commit message body.\n>\n>   Fixes: 1234beef56 (Commit message summmary)\n>   Reported-by: Joe User <j.user@example.com>\n>   Improved-by: Joe Hacker <j.hacker@example.com>\n>   Tested-by: Joe Tester <j.tester@example.com>\n>   Signed-off-by: Myself <myself@example.com>\n>\n> Here, the commit-msg hook removes the fields that were not filled in,\n> and performs additional filtering on the \"Fixes\" line (Adding commit\n> message summary). The filtering could also resolve ref names, so that\n> if you had refs/tags/security-bug pointing at the buggy commit, then:\n>\n>   Fixes: security-bug\n>\n> would be expanded/DWIMed into:\n>\n>   Fixes: 1234beef56 (Commit message summmary)\n>\n> Obviously, any other fancy processing you want to do into in the\n> commit-msg hook can be done as well, adding footnotes, checking that\n> commits are present in the ancestry, etc, etc.\n\nYeah, the commit message hook could do some more processing if the\nuser adds or changes stuff.\n\n> Three good reasons to go this way:\n>\n>  1. If the user forgets to supply command-line options like -s,\n> --fixes, etc, there is a nice reminder in the supplied form.\n\nGreat!\n\n>  2. No need to add any command-line options to Git.\n\nThis is not a good reason. If many users prefer a command line option,\nwhy not let them use that?\n\n>  3. The whole mechanism is controlled by the project. The kernel folks\n> can do whatever they want in their templates/hooks without needing\n> changes to the Git project.\n\nThe Git project already manages sob lines. It would be a good thing if\nit could manage\nmore of this stuff to help users in a generic way while taking care of\nuser preferences.\n\nBest regards,\nChristian.\n"},{"id":"229624","messageId":"526DB494.8000703@gmail.com","threadId":"35213","inReplyTo":"20131027013402.GA7146@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Jim Hill","fromEmail":"gjthill@gmail.com","sentAt":"2013-10-28T00:49:24Z","receivedAt":"2013-10-28T00:49:24Z","isPatch":true,"sender":{"key":"gjthill@gmail.com","avatar":"https://avatars.githubusercontent.com/u/80352?v=4"},"body":"On 10/26/13 18:34, Josh Triplett wrote:\n> Linux Kernel ... \"Fixes:\" line ... containing an abbreviated commit hash\n\n<!-- -->\n> This helps people (or automated tools) determine how far to backport\n\nI beg pardon if I'm rehearsing an old debate, but it seems to me it \nwould be better and worthwhile to bring more of git to bear by adding \n`reference` links as follows from considering this proposed sequence:\n\n     #  ...G---B---...    history-with-bug-at-B\n\n     Gprime=`git commit-tree --reference G`\n     Bprime=`git commit-tree --reference B -p $Gprime`\n\n     #   ...G---B---...   history-with-bug-at-B\n     #      :   :         # <-- `:`'s are `reference` links\n     #      G'--B'        $Bprime is a mergeable cherry-pick for B\n\n`reference` links have no enforced semantics. Teach all current logic to \nignore them (fetch doesn't fetch through them, fsck doesn't care, etc.). \n  Elaborating some of the good parts:\n\n* If the author and committer data are left untouched when \n`commit-tree`'s tree and message arguments are defaulted, as above, to \nthe referenced commit's tree and message, the resulting commit is unique.\n\n* Bullet-proof cherry-pick creation becomes easy and idempotent:\n\n         git-make-cherry-pick() {\n             local picked=$1\n             set -- `git rev-list --parents $picked^!`\n             shift\n             local parents\n             local parent\n             local p2\n             for parent; do\n                     p2=\"$p2 -p `git commit-tree --reference $parent`\"\n             done\n             git commit-tree --reference $picked $parents`\n         }\n\n* Which makes the created commit id a fully-implemented _change-id_ for \nthe referenced commit:\n\n         git merge $(git-make-cherry-pick $B)\n\n     can be done from anywhere, merge won't have to rely on patch-id's \nto detect cherry-picks done this way.\n\n* A bugged commit gets fixed by fixing its reference commit and merging \nnormally, worry-free:\n\n         ...G---B ... -F   Merge fix X for a bug in B\n            :   :     /\n            G'--B'---X     X's commit message is the `Fixes:` equivalent\n\n    Bugfix commit X can be safely merged anywhere.  Worst case, `git \nmerge -s ours --no-commit X` and do whatever you would have done otherwise.\n\n`merge` might usefully be updated to warn about merging from a commit \nwith only a reference parent, I think merging from `G'` would probably \nbe a mistake.\n\n---\nSo, this is as far as I've gotten with this, is there reason to think it \nshould or shouldn't be pursued?\n"},{"id":"229625","messageId":"xmqqa9hui2lp.fsf@gitster.dls.corp.google.com","threadId":"35213","inReplyTo":"20131027013402.GA7146@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-10-28T01:52:18Z","receivedAt":"2013-10-28T01:52:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"There are unbound number of kinds of trailers people would want to\nadd, depending on their projects' needs.  We should not have to add\na specific support for a tailer like this one, before thinking\nthrough to see if we can add generic support for adding arbitrary\ntrailers to avoid code and interface bloat.\n\nThink of the existing --signoff as a historical mistake.  Such a\ngeneric \"adding arbitrary trailers\" support, when done properly,\nshould be able to express what \"--signoff\" does, and we should be\nable to redo \"--signoff\" as a special case of that generic \"adding\narbitrary trailers\" support, and at that point, \"Fixes:\" trailer the\nkernel project wants to use should fall out as a natural consequence.\n"},{"id":"229626","messageId":"CALKQrgcgfimZRJL7WyS-brqEZnHJkJjK_0cqe6-7HWkuCW6Dzw@mail.gmail.com","threadId":"35213","inReplyTo":"CAP8UFD3MZJKWUbdZqrSwoatpnx73MTpiwSkxPHYDagGjMSqJNw@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-10-28T02:46:15Z","receivedAt":"2013-10-28T02:46:15Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Sun, Oct 27, 2013 at 8:04 PM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Sun, Oct 27, 2013 at 2:30 PM, Johan Herland <johan@herland.net> wrote:\n>> On Sun, Oct 27, 2013 at 1:30 PM, Christian Couder <christian.couder@gmail.com> wrote:\n>>>\n>>> Your suggestion is very good, and it is not incompatible with command\n>>> line options.\n>>> So both could be implemented and even work together.\n>>>\n>>> For example if \"-f ack:Peff\" was passed to the command line, \"git commit\" could\n>>> lookup in the commit message template and see if there is one\n>>> RFC822-style header\n>>> that starts with or contains \"ack\" (discarding case) and it could look\n>>> in some previous commits if\n>>> there is an author whose name contains \"Peff\" (discarding case)\n>>\n>> ...may be cheaper to (first) look at the .mailmap?\n>\n> Ok. I haven't really had a look at how it could best be done.\n>\n>>> and if it is the case\n>>> it could append the following to the bottom of the commit message:\n>>>\n>>> Fixes:\n>>> Reported-by:\n>>> Suggested-by:\n>>> Improved-by:\n>>> Acked-by: Jeff King <peff@peff.net>\n>>> Reviewed-by:\n>>> Tested-by:\n>>> Signed-off-by: Myself <myself@example.com>\n>>>\n>>> (I suppose that the sob is automatically added.)\n>>>\n>>> It would work also with \"-f fix:security-bug\" and would put something\n>>> like what you suggested:\n>>>\n>>> Fixes: 1234beef56 (Commit message summmary)\n>>\n>> Even better: Imagine \"-f\" (or whatever is decided) as a general\n>> mechanism for forwarding parameters to the prepare-commit-msg hook.\n>> When you run \"git commit -f ack:Peff -f fix:security-bug\", the -f\n>> arguments will be forwarded to prepare-commit-msg (as additional\n>> command-line args, or on stdin), and then the prepare-commit-msg hook\n>> can do whatever it wants with them (e.g. the things you describe\n>> above).\n>\n> If \"git commit\" processes these arguments and puts the result in the\n> commit message file that is passed to the\n> prepare-commit-msg hook, then this hook can still get them from the\n> file and process them however it wants.\n>\n> And in most cases the processing could be the same as what is done by\n> the commit-msg hook when the user changes the \"Fixes: xxx\" and\n> \"Stuffed-by: yyy\" lines in the editor.\n>\n> So it would probably be easier for people customizing the\n> prepare-commit-msg and commit-msg if \"git commit\" processes the\n> arguments instead of just passing them to the prepare-commit-msg hook.\n>\n> And it will be better for people who don't set up any *commit-msg hook.\n> Even if there is no commit template, \"-f Acked-by:Peff\" and \"-f\n> Fixes:security-bug\" could still work.\n> I suspect most users don't setup any hook or commit template.\n\nHmm. I'm not sure what you argue about which part of the system should\nperform which function. Let's examine the above options in more\ndetail. Roughly, the flow of events look like this\n\n  git commit -f ack:Peff -f fix:security-bug\n    |\n    v\n  builtin/commit.c (i.e. inside \"git commit\")\n    |\n    v\n  prepare-commit-msg hook\n    |\n    v\n  commit message template:\n    Fixes: security-bug\n    Acked-by: Peff\n    |\n    v\n  user edits commit message (may or may not change Fixes/Acked-by lines)\n    |\n    v\n  commit-msg hook\n    |\n    v\n  commit message:\n    Fixes: 1234beef56 (Commit message summmary)\n    Acked-by: Jeff King <peff@peff.net>\n\n(The above is even a bit simplified, but I believe it's sufficient for\nthe current discussion.) So, there are several expansions happening\nbetween the initial \"git commit\" and the final commit message. They\nare:\n\n 1. \"fix\" -> \"Fixes: \"\n 2. \"security-bug\" -> \"1234beef56 (Commit message summmary)\"\n 3. \"ack\" -> \"Acked-by: \"\n 4. \"Peff\" -> \"Jeff King <peff@peff.net>\"\n\nFirst, I think we both agree that expansions #2 and #4 MUST be done by\nthe commit-msg hook. The reason for this is two-fold: (a) the\nexpansion must be done (at least) after the user has edited the commit\nmessage (since the values entered by the user might require the same\nexpansion), and (b) how (and whether) to perform the expansion is a\nproject-specific policy question, and not something that Git can\ndictate. Obviously, common functionality can be made available in the\ndefault hook shipped by Git, but it's up to each project to enable\nand/or customize this.\n\nSecond, there is #1 and #3, the expansion of \"ack\" -> \"Acked-by:\" and\n\"fix\" -> \"Fixes:\". Is this expansion performed by the\nprepare-commit-msg hook, or directly inside builtin/commit.c?\n\nIf you are arguing for the latter (and I'm not sure that you are), we\nwould need to add a dictionary to \"git commit\" that maps shorthand\nfield names (\"ack\") to the RFC822 -style equivalent (\"Acked-by: \").\n\nI would instead argue for the former, i.e. simply forwarding \"ack\" and\n\"fix\" as-is to the prepare-commit-msg hook, and let it deal with the\nappropriate expansion. The main reason for this is that if a project\nwants to add another shorthand expansion (e.g. \"bug\" ->\n\"Related-Bugzilla-Id: \"), they can do so without hacking\nbuiltin/commit.c.\n\nCertainly, we could ship a default prepare-commit-msg hook that knows\nhow to expand the usual suspects (like \"ack\" and \"fix\"), but\nhardcoding this inside \"git commit\" is not optimal, IMHO.\n\n>> The reason I like this, is that we can now support project-specific\n>> conventions/rules without having to encode those directly in \"git\n>> commit\" itself. The only thing \"git commit\" needs to know, is how to\n>> forward the appropriate information to the project-specific hook.\n>\n> Supporting project specific conventions/rules would still be possible\n> by processing lines in the commit message file without changing \"git\n> commit\".\n>\n> If \"git commit\" is already able to do some processing, it only adds\n> power to what can be done by people writing hooks.\n>\n> We could even have git plumbing commands used by git commit to process\n> the -f (or whatever option) arguments and they could be reused by the\n> *commit-msg hooks if they find them useful.\n\nCan you walk through an example of such reusable functionality? ISTM\nthat you want to add quite a lot of infrastructure to git for very\nsmall gains (preparing and cleaning up commit messages), when that\ninfrastructure could instead be added by those (few?) projects that\nneed it without complicating Git itself (it is e.g. trivially easy to\nshare code between the prepare-commit-msg and commit-msg hooks...)\n\n>> One such project-specific convention/rule is the Signed-off-by line\n>> (although it has certainly spread to quite a lot of projects). I am\n>> not 100% comfortable with encoding this convention directly into \"git\n>> commit\", because it serves as a \"slippery slope\" to encode even more\n>> project-specific conventions/rules directly into \"git commit\" (the\n>> proposals to add command-line options for the \"Change-Id\" and \"Fixes\"\n>> headers are the two most recent examples), and the more we add, the\n>> more we bloat the \"git commit\" command-line interface.\n>\n> I don't think we would bloat the \"git commit\" command line interface.\n> We just add one option that could help a lot of people, even those who\n> want something very special.\n>\n>>>>  2. No need to add any command-line options to Git.\n>>>\n>>> This is not a good reason. If many users prefer a command line option,\n>>> why not let them use that?\n>>\n>> True. As explained above, what I don't want is to add another\n>> command-line option _every_time_ there is a useful project-specific\n>> convention. Adding _one_ option to rule them all is much more\n>> acceptable to me. :)\n>\n> Great!\n>\n>>>>  3. The whole mechanism is controlled by the project. The kernel folks\n>>>> can do whatever they want in their templates/hooks without needing\n>>>> changes to the Git project.\n>>>\n>>> The Git project already manages sob lines. It would be a good thing if\n>>> it could manage\n>>> more of this stuff to help users in a generic way while taking care of\n>>> user preferences.\n>>\n>> Yes, but the key word here is _generic_. It's impossible to make \"git\n>> commit\" able to solve all problems for all projects, but we can make a\n>> generic mechanism that helps projects solve their own problems more\n>> easily.\n>\n> Yeah, but as you said in your initial message, the generic mechanism\n> already exists with commit templates and *commit-msg hooks. The only\n> question left is how an additional command line option can best help.\n> And if this option does nearly nothing, it will not help much.\n\nBut I still don't see exactly what this option should do (inside \"git\ncommit\") that would end up being useful across most/all projects, and\nnot just something that could more easily be implemented in the\n*commit-msg hooks for relevant projects.\n\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"229628","messageId":"20131028071606.GA16878@leaf","threadId":"35213","inReplyTo":"xmqqa9hui2lp.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Josh Triplett","fromEmail":"josh@joshtriplett.org","sentAt":"2013-10-28T07:16:06Z","receivedAt":"2013-10-28T07:16:06Z","isPatch":true,"sender":{"key":"josh@joshtriplett.org","avatar":"https://avatars.githubusercontent.com/u/162737?v=4"},"body":"On Sun, Oct 27, 2013 at 06:52:18PM -0700, Junio C Hamano wrote:\n> There are unbound number of kinds of trailers people would want to\n> add, depending on their projects' needs.  We should not have to add\n> a specific support for a tailer like this one, before thinking\n> through to see if we can add generic support for adding arbitrary\n> trailers to avoid code and interface bloat.\n> \n> Think of the existing --signoff as a historical mistake.  Such a\n> generic \"adding arbitrary trailers\" support, when done properly,\n> should be able to express what \"--signoff\" does, and we should be\n> able to redo \"--signoff\" as a special case of that generic \"adding\n> arbitrary trailers\" support, and at that point, \"Fixes:\" trailer the\n> kernel project wants to use should fall out as a natural consequence.\n\nWell, the add_signoff_extra function I added makes it easy to add any\nkind of trailing data you want to a commit; the question just becomes\nwhat the UI looks like to drive that.\n\nWould you be OK with a solution that pushes the specific supported\nfooter lines into git's configuration, and then supplies default\nconfiguration for common cases such as Fixes?  The option could become\n-f/--footer, and the configuration would specify how to parse various\narguments of -f and turn them into something.  For example:\n\n[footer \"Fixes\"]\n    abbrev = f\n    arg = commit\n    format = %h ('%s')\n\ngit commit -f Cc:stable@vger.kernel.org -f f:bad-commit ...\n\nThe Cc line there would go unparsed since there's no specific support\nfor it, while the 'f:bad-commit' would get expanded by the configuration\nabove to parse bad-commit as a committish and format it using the\nspecified pretty format.\n\nLook reasonable?  I could start out by adding support for footer lines\nthat take commits as arguments and format them using arbitrary pretty\nstrings, and leave room for future expansion to support footers that\nreference idents (given some way to expand idents from some shorter\nform, otherwise there's no point).\n\n- Josh Triplett\n"},{"id":"229629","messageId":"526E1FD6.7040404@alum.mit.edu","threadId":"35213","inReplyTo":"20131028071606.GA16878@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2013-10-28T08:27:02Z","receivedAt":"2013-10-28T08:27:02Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/28/2013 08:16 AM, Josh Triplett wrote:\n> On Sun, Oct 27, 2013 at 06:52:18PM -0700, Junio C Hamano wrote:\n>> There are unbound number of kinds of trailers people would want to\n>> add, depending on their projects' needs.  We should not have to add\n>> a specific support for a tailer like this one, before thinking\n>> through to see if we can add generic support for adding arbitrary\n>> trailers to avoid code and interface bloat.\n>>\n>> Think of the existing --signoff as a historical mistake.  Such a\n>> generic \"adding arbitrary trailers\" support, when done properly,\n>> should be able to express what \"--signoff\" does, and we should be\n>> able to redo \"--signoff\" as a special case of that generic \"adding\n>> arbitrary trailers\" support, and at that point, \"Fixes:\" trailer the\n>> kernel project wants to use should fall out as a natural consequence.\n> \n> Well, the add_signoff_extra function I added makes it easy to add any\n> kind of trailing data you want to a commit; the question just becomes\n> what the UI looks like to drive that.\n> \n> Would you be OK with a solution that pushes the specific supported\n> footer lines into git's configuration, and then supplies default\n> configuration for common cases such as Fixes?  The option could become\n> -f/--footer, and the configuration would specify how to parse various\n> arguments of -f and turn them into something.  For example:\n> \n> [footer \"Fixes\"]\n>     abbrev = f\n>     arg = commit\n>     format = %h ('%s')\n\nIt could be even more decoupled, for example like this:\n\n[footer \"Fixes\"]\n    type = pipe\n    cmd = awk '{ print $1 }' | git log --stdin --no-walk --abbrev=12\n--pretty=format:\\\"Fixes: %h ('%s')\\\"\n\nNote that the command is written to be idempotent; that way git could\nre-pipe the old value(s) of the footer though the command if necessary.\n And it can handle multiple lines, since some callback scripts might\nwant to see all of them at once.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"229630","messageId":"20131028085911.GA9411@lst.de","threadId":"35213","inReplyTo":"20131028071606.GA16878@leaf","subject":"Re: [ksummit-attendees] [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Christoph Hellwig","fromEmail":"hch@lst.de","sentAt":"2013-10-28T08:59:11Z","receivedAt":"2013-10-28T08:59:11Z","isPatch":true,"sender":{"key":"hch@lst.de","avatar":null},"body":"Btw, can we please take away this discussion from ksummit-attendees?  It's got\nabsolutely nothing to do with kernel summit and is getting fairly annoying.\n\nThanks!\n"},{"id":"229633","messageId":"526E283A.1070801@alum.mit.edu","threadId":"35213","inReplyTo":"20131027071407.GA11683@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2013-10-28T09:02:50Z","receivedAt":"2013-10-28T09:02:50Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/27/2013 08:14 AM, Josh Triplett wrote:\n> On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n>> On 10/27/2013 02:34 AM, Josh Triplett wrote:\n>> [...]\n>> First of all, let me show my ignorance.  How formalized is the use of\n>> metadata lines at the end of a commit message?  I don't remember seeing\n>> documentation about such lines in general (as opposed to documentation\n>> about particular types of lines).  Is the format defined well enough\n>> that tools that don't know about a particular line could nonetheless\n>> preserve it correctly?  Is there/should there be a standard recommended\n>> order of metadata lines?  (For example, should \"Fixes:\" lines always\n>> appear before \"Signed-off-by\" lines, or vice versa?)  If so, is it\n>> documented somewhere and preserved by tools when such lines are\n>> added/modified?  Should there be support for querying such lines?\n> \n> While it isn't very well documented in git itself, metadata lines are\n> quite standardized.  See Documentation/SubmittingPatches and\n> Documentation/development-process/5.Posting in the Linux kernel, for an\n> explanation of \"Reported-by:\", \"Tested-by:\", \"Reviewed-by:\",\n> \"Suggested-by:\", and \"Acked-by:\".  And git itself looks for a very\n> specific format; the has_conforming_footer function looks for a footer\n> consisting exclusively of rfc2822-style (email-style) header lines to\n> decide whether to append \"Signed-off-by:\" (and now \"Fixes:\") directly to\n> that block or to create a new block.\n\nIt would be nice to document exactly what \"rfc2822-style\" means in this\ncontext (e.g., are line breaks supported?  Encoding changes?  etc.) so\nthat (1) new inventors of trailer lines can make sure that they conform\nto what Git expects and (2) Git could someday add some generic\nfacilities for handling these fields (e.g., adding/removing/tidying them\nin a commit-msg hook; grepping through them by name) and be relatively\nsure that it is not breaking somebody's metadata.\n\nI'm not saying that it's your job; only that it would be helpful for\nideas like yours.\n\n> [...]\n>> I wonder if the two features could\n>> be combined in some way?\n>>\n>> The main difference between the two features is how they are intended to\n>> be used: --fixup is to fix a commit that hasn't been pushed yet (where\n>> the user intends to squash the commits together), whereas --fixes is to\n>> mark a commit as a fix to a commit that has already been pushed (where\n>> the commits will remain separate).  But there seems to be a common\n>> concept here.\n>>\n>> For example, what happens if a --fixes commit is \"rebase -i\"ed at the\n>> same time as the commit that it fixes?  It might make sense to do the\n>> autosquash thing just like with a --fixup/--squash commit.  (Otherwise\n>> the SHA-1 in the \"Fixes:\" line will become invalid anyway.)\n> \n> Most definitely not, no, at least not without an explicit option to\n> enable that.  Consider the case of backporting a series of patches and\n> preserving the relative history of those patches, to make it easier to\n> match up a set of patches.  At most, it might be a good idea for\n> cherry-pick or similar to provide an updated Fixes tag for the new hash\n> of the older commit.  Personally, I'd argue against doing this even with\n> --autosquash.  I could see the argument for an --autosquash-fixes, but I\n> can't think of a real-world scenario where what would come up.\n> \n> Generally, if history is still editable, you should just squash in the\n> fix to the original commit, and if history is no longer editable (which\n> is the use case for \"Fixes:\" lines), the squash case simply won't come\n> up, offering little point to adding special support for that case.\n\nIn your last paragraph you explain exactly why these two features are\nsimilar and why it is thinkable to make the way that they are handled\ndepend on the context.  Exactly because one would never rebase a\n\"Fixes:\" commit and the commit it is fixing at the same time, they would\nnever be squashed together.  And ISTM that in most cases whenever they\n*are* being rebased at the same time, then one would want to squash them\ntogether.  So it might be possible to mark both types of commits the\nsame way and then squash/not squash them depending on the context and\nthe --autosquash option.\n\n> [...]\n>> I see that there a consistency check that the --fixes argument is a\n>> valid commit.  But is there/should there be a check that it is an\n>> ancestor of the commit being created?  Is there/should there be a check\n>> that both of these facts remain true if the the commit containing it is\n>> rebased, cherry-picked, etc?\n> \n> That sounds like a nice future enhancement, sure.  I don't have any plans to\n> add such a check myself, though.  Also note that --fixup and --squash\n> don't have such a check either; if you want to add one, you should add\n> it for all three options at once.\n\nA hook-based solution could do this.  But a built-in \"all-purpose\"\nhandler like \"footer.Fixes.arg=commit\", which was intended to be\nreusable, wouldn't be able to do such footer-specific extra work without\nhaving to create new special cases in git each time.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"229632","messageId":"xmqq1u35iwyl.fsf@gitster.dls.corp.google.com","threadId":"35213","inReplyTo":"xmqqa9hui2lp.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-10-28T09:08:50Z","receivedAt":"2013-10-28T09:08:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> There are unbound number of kinds of trailers people would want to\n> add, depending on their projects' needs.  We should not have to add\n> a specific support for a tailer like this one, before thinking\n> through to see if we can add generic support for adding arbitrary\n> trailers to avoid code and interface bloat.\n>\n> Think of the existing --signoff as a historical mistake.  Such a\n> generic \"adding arbitrary trailers\" support, when done properly,\n> should be able to express what \"--signoff\" does, and we should be\n> able to redo \"--signoff\" as a special case of that generic \"adding\n> arbitrary trailers\" support, and at that point, \"Fixes:\" trailer the\n> kernel project wants to use should fall out as a natural consequence.\n\nThinking aloud further, what I had in mind was along the lines of\nthe following.\n\n * The most generic external interface would be spelled as\n\n    --trailer <token>[=<param>]\n\n   where <token> can be things like \"signoff\", \"closes\", \"acked-by\",\n   \"change-id\", \"fixes\", etc.; they can be taken from an unbounded\n   set.  The historical \"--signoff\" can become a short-hand for\n   \"--trailer signoff\".  More than one \"--trailer\" option can be\n   given on a single command line.\n\n * The token is used to look into the configuration, e.g.,\n\n   [commitTrailer \"signoff\"]\n\tstyle = append-norepeat\n\ttrailer = Signed-off-by\n        command = echo \"$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"'\n\n   [commitTrailer \"change-id\"]\n\tstyle = append-only-if-missing\n\ttrailer = Change-Id\n        command = 'git hash-object -t commit --stdin <$GIT_PROTO_COMMIT'\n\n   [commitTrailer \"fixes\"]\n\tstyle = overwrite\n        trailer = Fixes\n        command = 'git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit=14 $ARG'\n\n   where\n\n   - \"commitTrailer.<token>.style\" defines the interaction with\n     existing trailer of the same kind (e.g. S-o-b: accumulates by\n     appending, but we try not to repeat the same sign-off twice\n     which would show you forwarding your own message you are the\n     last person in the Sign-off chain; Fixes: if there is already\n     one will remove the old one and replaces; etc.);\n\n   - \"commitTrailer.<token>.trailer\" defines the trailer label at\n     the beginning of the trailer line;\n\n   - \"commitTrailer.<token>.command\" gives the command to run to\n     obtain the payload after the \"trailer\" label.  A handful\n     obvious and useful variables are exported for the command to\n     use, and <param> is exported as $ARG, if present.\n\nWith the most generic syntax, with the above commitTrailer.fixes.*\nconfiguration, I would imagine that you can say something like:\n\n    git commit --trailer fixes=\"v2.6.12^{/^i386: tweak frobnitz}\"\n\nto say that the first commit you find traversing the history of\nv2.6.12 whose title is \"i386: tweak frobnitz\" was faulty, and you\nare creating a commit that corrects its mistake.\n\nGiving some default configuration to often used trailer types\n(e.g. configuration for \"--trailer signoff\") and promoting some\ncommonly used ones into a separate built-in option (e.g. an option\n\"--signoff\" that does not have to say \"--trailer signoff\") are\nentirely separate issues, and only time can nudge us into evaluating\nindividual types of trailers.\n"},{"id":"229637","messageId":"CALKQrgfsk3fjyF77XL9+CPyJ_s-AfzkNAj4Eaj1LT-G0Ph=bfg@mail.gmail.com","threadId":"35213","inReplyTo":"526E283A.1070801@alum.mit.edu","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-10-28T11:29:32Z","receivedAt":"2013-10-28T11:29:32Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Mon, Oct 28, 2013 at 10:02 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n> On 10/27/2013 08:14 AM, Josh Triplett wrote:\n>> On Sun, Oct 27, 2013 at 06:42:44AM +0100, Michael Haggerty wrote:\n>>> On 10/27/2013 02:34 AM, Josh Triplett wrote:\n>>> I wonder if the two features could\n>>> be combined in some way?\n>>>\n>>> The main difference between the two features is how they are intended to\n>>> be used: --fixup is to fix a commit that hasn't been pushed yet (where\n>>> the user intends to squash the commits together), whereas --fixes is to\n>>> mark a commit as a fix to a commit that has already been pushed (where\n>>> the commits will remain separate).  But there seems to be a common\n>>> concept here.\n>>>\n>>> For example, what happens if a --fixes commit is \"rebase -i\"ed at the\n>>> same time as the commit that it fixes?  It might make sense to do the\n>>> autosquash thing just like with a --fixup/--squash commit.  (Otherwise\n>>> the SHA-1 in the \"Fixes:\" line will become invalid anyway.)\n>>\n>> Most definitely not, no, at least not without an explicit option to\n>> enable that.  Consider the case of backporting a series of patches and\n>> preserving the relative history of those patches, to make it easier to\n>> match up a set of patches.  At most, it might be a good idea for\n>> cherry-pick or similar to provide an updated Fixes tag for the new hash\n>> of the older commit.  Personally, I'd argue against doing this even with\n>> --autosquash.  I could see the argument for an --autosquash-fixes, but I\n>> can't think of a real-world scenario where what would come up.\n>>\n>> Generally, if history is still editable, you should just squash in the\n>> fix to the original commit, and if history is no longer editable (which\n>> is the use case for \"Fixes:\" lines), the squash case simply won't come\n>> up, offering little point to adding special support for that case.\n>\n> In your last paragraph you explain exactly why these two features are\n> similar and why it is thinkable to make the way that they are handled\n> depend on the context.  Exactly because one would never rebase a\n> \"Fixes:\" commit and the commit it is fixing at the same time, they would\n> never be squashed together.  And ISTM that in most cases whenever they\n> *are* being rebased at the same time, then one would want to squash them\n> together.  So it might be possible to mark both types of commits the\n> same way and then squash/not squash them depending on the context and\n> the --autosquash option.\n\nIn general, we should be careful with introducing features that\nexhibit different consequences based on the context in which they are\nused, but in this case, I believe I agree with you. The existence of\n\"Fixes:\" in a commit should be a just as valid hint to --autosquash as\na commit message starting with \"fixup!\" or \"squash!\" (obviously, the\n\"Fixes:\" commit should be handled like a \"squash!\" and not like a\n\"fixup!\", so that we don't haphazardly discard the commit message\naccompanying \"Fixes:\").\n\n>>> I see that there a consistency check that the --fixes argument is a\n>>> valid commit.  But is there/should there be a check that it is an\n>>> ancestor of the commit being created?  Is there/should there be a check\n>>> that both of these facts remain true if the the commit containing it is\n>>> rebased, cherry-picked, etc?\n>>\n>> That sounds like a nice future enhancement, sure.  I don't have any plans to\n>> add such a check myself, though.  Also note that --fixup and --squash\n>> don't have such a check either; if you want to add one, you should add\n>> it for all three options at once.\n>\n> A hook-based solution could do this.  But a built-in \"all-purpose\"\n> handler like \"footer.Fixes.arg=commit\", which was intended to be\n> reusable, wouldn't be able to do such footer-specific extra work without\n> having to create new special cases in git each time.\n\nWhich begs the question (posed to all, not specifically to you): Why\nwould we want solve this issue in config instead of in hooks? The\nhooks will always be more flexible and less dependent on making\nchanges in git.git. (...a suitably flexible hook could even use the\nconfig options discussed above as input...) In both cases, we need the\nuser to actively enable the functionality (either installing hooks, or\nsetting up config), and in both cases we could bundle Git with\ndefaults that solve the common cases, so that is not a useful\ndifferentiator between the two approaches. I would even venture to\nask: If we end up solving this problem in config and not in hooks,\nthen why do we bother having hooks in the first place?\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"229680","messageId":"87txg1hwsa.fsf@linux-k42r.v.cablecom.net","threadId":"35213","inReplyTo":"CALKQrgcgfimZRJL7WyS-brqEZnHJkJjK_0cqe6-7HWkuCW6Dzw@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Thomas Rast","fromEmail":"tr@thomasrast.ch","sentAt":"2013-10-28T22:10:13Z","receivedAt":"2013-10-28T22:10:13Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> But I still don't see exactly what this option should do (inside \"git\n> commit\") that would end up being useful across most/all projects, and\n> not just something that could more easily be implemented in the\n> *commit-msg hooks for relevant projects.\n\n[Ok, admittedly I don't really know what to quote from your message,\nsince I'm mostly responding to the overall concept.]\n\nI like the idea of putting all that in hooks, but I have two\nobservations:\n\n* Signed-off-by: is already such a case (and was probably also added for\n  the kernel?) that _could_ have been dealt with using {prepare-,}commit-msg, \n  but has its own support in various git tools.\n\n* In your list\n\n>   Fixes:\n>   Reported-by:\n>   Suggested-by:\n>   Improved-by:\n>   Acked-by:\n>   Reviewed-by:\n>   Tested-by:\n>   Signed-off-by:\n\n  and I might add\n\n    Cherry-picked-from:\n    Reverts:\n\n  if one were to phrase that as a footer/pseudoheader, observe that\n  there are only two kinds of these: footers that contain identities,\n  and footers that contain references to commits.\n\nSo why not support these use-cases?  We could have something like\nfooter.foo.* configuration, e.g.\n\n[footer \"fixes\"]\n        type = commit\n        suggest = true\n[footer \"acked-by\"]\n        type = identity\n\nwhere 'suggest' (please suggest a better name) means that git-commit\nwill put a blank one in the commit message template for you to fill in.\n'commit' and 'identity' can have some elementary expansion and\nvalidation tied to them.  Some easy extensiblity (hooks?) might not\nhurt, but then as you point out, the existing hooks already cover that.\n\nPerhaps we could also have, for Gerrit (cf. [1]):\n\n[footer \"change-id\"]\n        type = uuid\n\nthough admittedly I haven't investigated if it's okay to just put a\nrandom string there, or it needs to have a specific value.\n\n\n[1]  http://thread.gmane.org/gmane.comp.version-control.git/236429\n\n-- \nThomas Rast\ntr@thomasrast.ch\n"},{"id":"229682","messageId":"1383001793.5117.14.camel@pasglop","threadId":"35213","inReplyTo":"20131028085911.GA9411@lst.de","subject":"Re: [ksummit-attendees] [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Benjamin Herrenschmidt","fromEmail":"benh@kernel.crashing.org","sentAt":"2013-10-28T23:09:53Z","receivedAt":"2013-10-28T23:09:53Z","isPatch":true,"sender":{"key":"benh@kernel.crashing.org","avatar":null},"body":"On Mon, 2013-10-28 at 09:59 +0100, Christoph Hellwig wrote:\n> Btw, can we please take away this discussion from ksummit-attendees?  It's got\n> absolutely nothing to do with kernel summit and is getting fairly annoying.\n\nAck. Additionally, iirc, we had decided that\n\n - We don't cross post multiple lists\n\n - We drop the annoying subject tags\n\nAs is, all I see is some attempt at doing an lkml dup, which is\npointless\n\nBen.\n"},{"id":"229684","messageId":"20131028233805.GL16735@n2100.arm.linux.org.uk","threadId":"35213","inReplyTo":"1383001793.5117.14.camel@pasglop","subject":"Re: [ksummit-attendees] [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Russell King - ARM Linux","fromEmail":"linux@arm.linux.org.uk","sentAt":"2013-10-28T23:38:05Z","receivedAt":"2013-10-28T23:38:05Z","isPatch":true,"sender":{"key":"linux@arm.linux.org.uk","avatar":null},"body":"On Tue, Oct 29, 2013 at 10:09:53AM +1100, Benjamin Herrenschmidt wrote:\n> On Mon, 2013-10-28 at 09:59 +0100, Christoph Hellwig wrote:\n> > Btw, can we please take away this discussion from ksummit-attendees?  It's got\n> > absolutely nothing to do with kernel summit and is getting fairly annoying.\n> \n> Ack. Additionally, iirc, we had decided that\n> \n>  - We don't cross post multiple lists\n> \n>  - We drop the annoying subject tags\n> \n> As is, all I see is some attempt at doing an lkml dup, which is\n> pointless\n\nI agree too.  This whole thread seems to be about noise, and I too\nthought there was something about not cross-posting between this list\nand any other list.\n"},{"id":"229685","messageId":"20131028234117.GM16735@n2100.arm.linux.org.uk","threadId":"35213","inReplyTo":"1383001793.5117.14.camel@pasglop","subject":"Re: [ksummit-attendees] [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Russell King - ARM Linux","fromEmail":"rmk+kernel@arm.linux.org.uk","sentAt":"2013-10-28T23:41:17Z","receivedAt":"2013-10-28T23:41:17Z","isPatch":true,"sender":{"key":"rmk+kernel@arm.linux.org.uk","avatar":null},"body":"On Tue, Oct 29, 2013 at 10:09:53AM +1100, Benjamin Herrenschmidt wrote:\n> On Mon, 2013-10-28 at 09:59 +0100, Christoph Hellwig wrote:\n> > Btw, can we please take away this discussion from ksummit-attendees?  It's got\n> > absolutely nothing to do with kernel summit and is getting fairly annoying.\n> \n> Ack. Additionally, iirc, we had decided that\n> \n>  - We don't cross post multiple lists\n> \n>  - We drop the annoying subject tags\n> \n> As is, all I see is some attempt at doing an lkml dup, which is\n> pointless\n\nI agree too.  This whole thread seems to be about noise, and I too\nthought there was something about not cross-posting between this list\nand any other list.\n"},{"id":"229694","messageId":"20131029020227.GD11861@sigill.intra.peff.net","threadId":"35213","inReplyTo":"87txg1hwsa.fsf@linux-k42r.v.cablecom.net","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-10-29T02:02:28Z","receivedAt":"2013-10-29T02:02:28Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Oct 28, 2013 at 11:10:13PM +0100, Thomas Rast wrote:\n\n> * In your list\n> \n> >   Fixes:\n> >   Reported-by:\n> >   Suggested-by:\n> >   Improved-by:\n> >   Acked-by:\n> >   Reviewed-by:\n> >   Tested-by:\n> >   Signed-off-by:\n> \n>   and I might add\n> \n>     Cherry-picked-from:\n>     Reverts:\n> \n>   if one were to phrase that as a footer/pseudoheader, observe that\n>   there are only two kinds of these: footers that contain identities,\n>   and footers that contain references to commits.\n\nI think people put other things in, too. For example, cross-referencing\nbug-tracker ids.\n\nIn fact, if I saw \"fixes: XXX\", I would expect the latter to be a\ntracker id.  People do this a lot with GitHub issues, because GitHub\nwill auto-close issue 123 if a commit with \"fixes #123\" is pushed to\nmaster. Because of the \"#\", no pseudo-header is needed, but I have also\nseen people use the footer style (I don't have any examples on-hand,\nthough).\n\nThat being said, in your examples:\n\n> So why not support these use-cases?  We could have something like\n> footer.foo.* configuration, e.g.\n> \n> [footer \"fixes\"]\n>         type = commit\n>         suggest = true\n> [footer \"acked-by\"]\n>         type = identity\n\nyou could easily have \"type=text\" to handle arbitrary text.\n\n-Peff\n"},{"id":"229695","messageId":"20131029020824.GE11861@sigill.intra.peff.net","threadId":"35213","inReplyTo":"CALKQrgfsk3fjyF77XL9+CPyJ_s-AfzkNAj4Eaj1LT-G0Ph=bfg@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-10-29T02:08:24Z","receivedAt":"2013-10-29T02:08:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Oct 28, 2013 at 12:29:32PM +0100, Johan Herland wrote:\n\n> > A hook-based solution could do this.  But a built-in \"all-purpose\"\n> > handler like \"footer.Fixes.arg=commit\", which was intended to be\n> > reusable, wouldn't be able to do such footer-specific extra work without\n> > having to create new special cases in git each time.\n> \n> Which begs the question (posed to all, not specifically to you): Why\n> would we want solve this issue in config instead of in hooks? The\n> hooks will always be more flexible and less dependent on making\n> changes in git.git. (...a suitably flexible hook could even use the\n> config options discussed above as input...) In both cases, we need the\n> user to actively enable the functionality (either installing hooks, or\n> setting up config), and in both cases we could bundle Git with\n> defaults that solve the common cases, so that is not a useful\n> differentiator between the two approaches. I would even venture to\n> ask: If we end up solving this problem in config and not in hooks,\n> then why do we bother having hooks in the first place?\n\nOne thing that is much nicer with config vs hooks is that you can manage\nconfig for all of your repositories by tweaking ~/.gitconfig (and that\nis where I would expect this type of config to go).\n\nManaging hooks globally means having each repo symlink to a central hook\narea, and having the forethought to set up the symlink farm and use\ninit.templatedir before cloning any repos.  We could probably make this\nfriendlier by reading from ~/.githooks and defining some semantics for\nmultiple hooks. E.g., fall back to ~/.githooks if the repo hook is not\nexecutable, or possibly run them both (or even allow multiple instances\nof a hook in ~/.githooks, which can help organization), and consider the\nhook a failure if any of them fail.\n\n-Peff\n"},{"id":"229698","messageId":"CAP8UFD0R7JAkQSiX=1nqg_fmo-o7B-ekkxvsjHFgwspk5V0PHA@mail.gmail.com","threadId":"35213","inReplyTo":"xmqq1u35iwyl.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2013-10-29T04:45:00Z","receivedAt":"2013-10-29T04:45:00Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Mon, Oct 28, 2013 at 10:08 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Thinking aloud further, what I had in mind was along the lines of\n> the following.\n>\n>  * The most generic external interface would be spelled as\n>\n>     --trailer <token>[=<param>]\n>\n>    where <token> can be things like \"signoff\", \"closes\", \"acked-by\",\n>    \"change-id\", \"fixes\", etc.; they can be taken from an unbounded\n>    set.  The historical \"--signoff\" can become a short-hand for\n>    \"--trailer signoff\".  More than one \"--trailer\" option can be\n>    given on a single command line.\n\nOk, and maybe the <token> could also be the full trailer like \"Signed-off-by\".\n\n>  * The token is used to look into the configuration, e.g.,\n>\n>    [commitTrailer \"signoff\"]\n>         style = append-norepeat\n>         trailer = Signed-off-by\n>         command = echo \"$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"'\n>\n>    [commitTrailer \"change-id\"]\n>         style = append-only-if-missing\n>         trailer = Change-Id\n>         command = 'git hash-object -t commit --stdin <$GIT_PROTO_COMMIT'\n>\n>    [commitTrailer \"fixes\"]\n>         style = overwrite\n>         trailer = Fixes\n>         command = 'git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit=14 $ARG'\n>\n>    where\n>\n>    - \"commitTrailer.<token>.style\" defines the interaction with\n>      existing trailer of the same kind (e.g. S-o-b: accumulates by\n>      appending, but we try not to repeat the same sign-off twice\n>      which would show you forwarding your own message you are the\n>      last person in the Sign-off chain; Fixes: if there is already\n>      one will remove the old one and replaces; etc.);\n>\n>    - \"commitTrailer.<token>.trailer\" defines the trailer label at\n>      the beginning of the trailer line;\n>\n>    - \"commitTrailer.<token>.command\" gives the command to run to\n>      obtain the payload after the \"trailer\" label.  A handful\n>      obvious and useful variables are exported for the command to\n>      use, and <param> is exported as $ARG, if present.\n>\n> With the most generic syntax, with the above commitTrailer.fixes.*\n> configuration, I would imagine that you can say something like:\n>\n>     git commit --trailer fixes=\"v2.6.12^{/^i386: tweak frobnitz}\"\n>\n> to say that the first commit you find traversing the history of\n> v2.6.12 whose title is \"i386: tweak frobnitz\" was faulty, and you\n> are creating a commit that corrects its mistake.\n>\n> Giving some default configuration to often used trailer types\n> (e.g. configuration for \"--trailer signoff\") and promoting some\n> commonly used ones into a separate built-in option (e.g. an option\n> \"--signoff\" that does not have to say \"--trailer signoff\") are\n> entirely separate issues, and only time can nudge us into evaluating\n> individual types of trailers.\n\nOk, and maybe, if there is no configuration for a trailer token, we\ncould look at the commit template.\n\nThanks,\nChristian.\n"},{"id":"229700","messageId":"CAP8UFD1eTmUGt7dWAP-Ws17op=z98hOvBa_g8_y=xS8WQ1dRMg@mail.gmail.com","threadId":"35213","inReplyTo":"CALKQrgcgfimZRJL7WyS-brqEZnHJkJjK_0cqe6-7HWkuCW6Dzw@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2013-10-29T06:23:40Z","receivedAt":"2013-10-29T06:23:40Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Mon, Oct 28, 2013 at 3:46 AM, Johan Herland <johan@herland.net> wrote:\n> On Sun, Oct 27, 2013 at 8:04 PM, Christian Couder <christian.couder@gmail.com> wrote:\n>>\n>> If \"git commit\" processes these arguments and puts the result in the\n>> commit message file that is passed to the\n>> prepare-commit-msg hook, then this hook can still get them from the\n>> file and process them however it wants.\n>>\n>> And in most cases the processing could be the same as what is done by\n>> the commit-msg hook when the user changes the \"Fixes: xxx\" and\n>> \"Stuffed-by: yyy\" lines in the editor.\n>>\n>> So it would probably be easier for people customizing the\n>> prepare-commit-msg and commit-msg if \"git commit\" processes the\n>> arguments instead of just passing them to the prepare-commit-msg hook.\n>>\n>> And it will be better for people who don't set up any *commit-msg hook.\n>> Even if there is no commit template, \"-f Acked-by:Peff\" and \"-f\n>> Fixes:security-bug\" could still work.\n>> I suspect most users don't setup any hook or commit template.\n>\n> Hmm. I'm not sure what you argue about which part of the system should\n> perform which function. Let's examine the above options in more\n> detail. Roughly, the flow of events look like this\n>\n>   git commit -f ack:Peff -f fix:security-bug\n>     |\n>     v\n>   builtin/commit.c (i.e. inside \"git commit\")\n>     |\n>     v\n>   prepare-commit-msg hook\n>     |\n>     v\n>   commit message template:\n>     Fixes: security-bug\n>     Acked-by: Peff\n\nHere it could already be:\n\n     Fixes: 1234beef56 (Commit message summmary)\n     Acked-by: Jeff King <peff@peff.net>\n\nBecause builtin/commit.c hook could already have expanded everything.\n\n>     |\n>     v\n>   user edits commit message (may or may not change Fixes/Acked-by lines)\n>     |\n>     v\n>   commit-msg hook\n>     |\n>     v\n>   commit message:\n>     Fixes: 1234beef56 (Commit message summmary)\n>     Acked-by: Jeff King <peff@peff.net>\n>\n> (The above is even a bit simplified, but I believe it's sufficient for\n> the current discussion.) So, there are several expansions happening\n> between the initial \"git commit\" and the final commit message. They\n> are:\n>\n>  1. \"fix\" -> \"Fixes: \"\n>  2. \"security-bug\" -> \"1234beef56 (Commit message summmary)\"\n>  3. \"ack\" -> \"Acked-by: \"\n>  4. \"Peff\" -> \"Jeff King <peff@peff.net>\"\n>\n> First, I think we both agree that expansions #2 and #4 MUST be done by\n> the commit-msg hook. The reason for this is two-fold: (a) the\n> expansion must be done (at least) after the user has edited the commit\n> message (since the values entered by the user might require the same\n> expansion), and (b) how (and whether) to perform the expansion is a\n> project-specific policy question, and not something that Git can\n> dictate.\n\nI don't agree. Git doesn't need to dictate anything to be able to do\nthese expansions.\nGit only needs some hints to do these expansions properly and it could\njust look at the commit template, or the config, to get those hints.\n\nFor example, if there is a \"Acked-by:\" line in the commit template,\nthen Git might decide that \"ack\" means \"Acked-by\", and then that \"-by\"\nmeans that \"Peff\" should be related to an author, and then that it is\nprobably \"Jeff King <peff@peff.net>\".\n\n> Obviously, common functionality can be made available in the\n> default hook shipped by Git, but it's up to each project to enable\n> and/or customize this.\n>\n> Second, there is #1 and #3, the expansion of \"ack\" -> \"Acked-by:\" and\n> \"fix\" -> \"Fixes:\". Is this expansion performed by the\n> prepare-commit-msg hook, or directly inside builtin/commit.c?\n>\n> If you are arguing for the latter (and I'm not sure that you are), we\n> would need to add a dictionary to \"git commit\" that maps shorthand\n> field names (\"ack\") to the RFC822 -style equivalent (\"Acked-by: \").\n\nYes, I am arguing that builtin/commit.c, or better a plumbing command\nlaunched by builtin/commit.c, should do it.\n\nAnd I don't think there is an absolute need for a dictionary.\nThere could be such a dictionary in the config (as Junio proposed).\nBut if there isn't, the plumbing command launched by builtin/commit.c\ncould look at the commit template to decide that \"ack\" means\n\"Acked-by:\".\n\n> I would instead argue for the former, i.e. simply forwarding \"ack\" and\n> \"fix\" as-is to the prepare-commit-msg hook, and let it deal with the\n> appropriate expansion. The main reason for this is that if a project\n> wants to add another shorthand expansion (e.g. \"bug\" ->\n> \"Related-Bugzilla-Id: \"), they can do so without hacking\n> builtin/commit.c.\n\nI agree that there should be no need to hack builtin/commit.c.\nFor example if \"Bugzilla-Id:\" is in the commit template, the plumbing\ncommand launched by builtin/commit.c would decide that \"bug\" means\n\"Bugzilla-Id:\" without any hack.\n\nOf course this suppose that there is no other \"Bugtracker:\" or \"Bug:\"\nin the commit template.\nBut even in this case it would mean that users have to use \"-f\nbugz:XXX\" (or \"--trailer bugz=XXX\") instead of just \"-f bug:XXX\".\n\n>> Supporting project specific conventions/rules would still be possible\n>> by processing lines in the commit message file without changing \"git\n>> commit\".\n>>\n>> If \"git commit\" is already able to do some processing, it only adds\n>> power to what can be done by people writing hooks.\n>>\n>> We could even have git plumbing commands used by git commit to process\n>> the -f (or whatever option) arguments and they could be reused by the\n>> *commit-msg hooks if they find them useful.\n>\n> Can you walk through an example of such reusable functionality?\n\nOk, let's call the new plumbing command \"git interpret-trailers\".\nAnd let's suppose that \"git commit\" is passed \"-f ack:Peff -f\nfix:security-bug\" (or \"--trailer ack=Peff --trailer\nfix=security-bug\").\n\n\"git commit\" would then call something like:\n\ngit interpret-trailers --file commit_message_template.txt 'ack:Peff'\n'fix:security-bug'\n\nAnd this command would output:\n\n------------------\n<<<upper part of commit_message_template.txt>>>\n\nFixes: 1234beef56 (Commit message summmary)\nReported-by:\nSuggested-by:\nImproved-by:\nAcked-by: Jeff King <peff@peff.net>\nReviewed-by:\nTested-by:\nSigned-off-by: Myself <myself@example.com>\n------------------\n\nBecause it would have looked at the commit template it is passed and\nfilled in the blanks it could fill using the arguments it is also\npassed.\n\n\"git commit\" would then put the above lines in the file that it passes\nto the prepare-commit-msg hook.\n\nThen the prepare-commit-msg could just do nothing.\n\nAfter the user has edited the commit message, the commit-msg hook\ncould just call:\n\ngit interpret-trailers --trim-empty --file commit_message.txt\n\nso that what the user changed is interpreted again.\n\nFor example if the user changed the \"Reviewed-by:\" line to\n\"Reviewed-by: Johan\", then the output would be:\n\n------------------\n<<<upper part of commit_message.txt>>>\n\nFixes: 1234beef56 (Commit message summmary)\nAcked-by: Jeff King <peff@peff.net>\nReviewed-by: Johan Herland <johan@herland.net>\nSigned-off-by: Myself <myself@example.com>\n------------------\n\nAnd that would be the final commit message in most cases.\n\nThanks,\nChristian.\n"},{"id":"229712","messageId":"vpqfvrkeb4p.fsf@anie.imag.fr","threadId":"35213","inReplyTo":"20131029020824.GE11861@sigill.intra.peff.net","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2013-10-29T08:26:14Z","receivedAt":"2013-10-29T08:26:14Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jeff King <peff@peff.net> writes:\n\n>  We could probably make this friendlier by reading from ~/.githooks\n> and defining some semantics for multiple hooks.\n\nI'd be all for it, except I'd call this ~/.config/git/hooks/* (or\n$XDG_CONFIG_HOME if set).\n\n> E.g., fall back to ~/.githooks if the repo hook is not\n> executable, or possibly run them both\n\nI think running them both would be the best option. Otherwise, adding a\n(possibly trivial) hook to a repo would disable the user-wide one,\nthat'd feel weird.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"229743","messageId":"xmqqa9hretuf.fsf@gitster.dls.corp.google.com","threadId":"35213","inReplyTo":"CAP8UFD0R7JAkQSiX=1nqg_fmo-o7B-ekkxvsjHFgwspk5V0PHA@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-10-29T19:54:16Z","receivedAt":"2013-10-29T19:54:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n> On Mon, Oct 28, 2013 at 10:08 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>> Thinking aloud further, what I had in mind was along the lines of\n>> the following.\n>>\n>>  * The most generic external interface would be spelled as\n>>\n>>     --trailer <token>[=<param>]\n>>\n>>    where <token> can be things like \"signoff\", \"closes\", \"acked-by\",\n>>    \"change-id\", \"fixes\", etc.; they can be taken from an unbounded\n>>    set.  The historical \"--signoff\" can become a short-hand for\n>>    \"--trailer signoff\".  More than one \"--trailer\" option can be\n>>    given on a single command line.\n>\n> Ok, and maybe the <token> could also be the full trailer like \"Signed-off-by\".\n\nYeah, between these two:\n\n    [commitTrailer \"Signed-off-by\"]\n        style = append-norepeat\n        shorthand = signoff\n        command = echo \"$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"'\n\n   [commitTrailer \"signoff\"]\n        style = append-norepeat\n        trailer = Signed-off-by\n        command = echo \"$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"'\n\nI do not have strong preference either way.  One of these two sets\nof configuration will have to become a built-in default (i.e. still\nallowing people from other development community conventions to\nredefine how S-o-b: works), so there will be no user-visible\ndifference either way at the highest-level Porcelain anyway.\n\nOh, also, it seems people prefer to call them \"footers\", judging by\nthe messages in this thread. I do not have a problem with that word,\neither; I suspect we may have to update existing documentation that\ncalls them \"trailers\", if we go that way, though.\n"},{"id":"229835","messageId":"CA+8MBbK3dicmwOJb0mhTwr59O1tqzZgEGmMfSQV61Z=aK_64oA@mail.gmail.com","threadId":"35213","inReplyTo":"20131027013402.GA7146@leaf","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Tony Luck","fromEmail":"tony.luck@gmail.com","sentAt":"2013-10-30T17:28:06Z","receivedAt":"2013-10-30T17:28:06Z","isPatch":true,"sender":{"key":"tony.luck@gmail.com","avatar":null},"body":"On Sat, Oct 26, 2013 at 6:34 PM, Josh Triplett <josh@joshtriplett.org> wrote:\n\n> +               format_commit_message(commit, \"Fixes: %h ('%s')\\n\", sb, &ctx);\n\nWhat is the value of double wrapping the commit message inside '...'\nand then ('...')?\n\n-Tony\n"},{"id":"229844","messageId":"CALKQrgc297dqaxBNDT-N831a94gF7TyDrjt2y4DpOdT_tkyayA@mail.gmail.com","threadId":"35213","inReplyTo":"87txg1hwsa.fsf@linux-k42r.v.cablecom.net","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-10-30T17:53:52Z","receivedAt":"2013-10-30T17:53:52Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Mon, Oct 28, 2013 at 11:10 PM, Thomas Rast <tr@thomasrast.ch> wrote:\n> Johan Herland <johan@herland.net> writes:\n>> But I still don't see exactly what this option should do (inside \"git\n>> commit\") that would end up being useful across most/all projects, and\n>> not just something that could more easily be implemented in the\n>> *commit-msg hooks for relevant projects.\n>\n> [Ok, admittedly I don't really know what to quote from your message,\n> since I'm mostly responding to the overall concept.]\n>\n> I like the idea of putting all that in hooks, but I have two\n> observations:\n>\n> * Signed-off-by: is already such a case (and was probably also added for\n>   the kernel?) that _could_ have been dealt with using {prepare-,}commit-msg,\n>   but has its own support in various git tools.\n\nYes, and I don't like using the precedent of \"Signed-off-by\" as an\nargument to push support for more (IMHO project-specific) footers into\ncore Git. Hence, I'd rather see the \"Signed-off-by\" reimplemented as a\nhook (obviously, the -s option for \"git commit\" would have to remain\nfor backward-compatibility).\n\n> * In your list\n>\n>>   Fixes:\n>>   Reported-by:\n>>   Suggested-by:\n>>   Improved-by:\n>>   Acked-by:\n>>   Reviewed-by:\n>>   Tested-by:\n>>   Signed-off-by:\n>\n>   and I might add\n>\n>     Cherry-picked-from:\n>     Reverts:\n>\n>   if one were to phrase that as a footer/pseudoheader, observe that\n>   there are only two kinds of these: footers that contain identities,\n>   and footers that contain references to commits.\n\nI'm not so sure we can make those assumptions. One might conceivably\nimagine a \"Fixes:\" footer that refers to a bug ID, and not a commit.\nAlso, projects might want to apply different rules on what may appear\nin which footer. E.g. one could e.g. want to enforce that the ident\nlisted in \"Reviewed-by:\" or \"Signed-off-by:\" must always appear in a\nproject-specific REVIEWERS.txt or AUTHORS.txt file. Since we don't\nreally know what projects might want, we shouldn't make too many\nassumptions on how these footers will be used... That said, I am not\n(or at least no longer) opposed to generic support in core Git for\nprocessing these footers, as long as that support is flexible/generic\nin nature, and equally available to be reused from within hooks as\nfrom within core Git.\n\n> So why not support these use-cases?  We could have something like\n> footer.foo.* configuration, e.g.\n>\n> [footer \"fixes\"]\n>         type = commit\n>         suggest = true\n> [footer \"acked-by\"]\n>         type = identity\n>\n> where 'suggest' (please suggest a better name) means that git-commit\n> will put a blank one in the commit message template for you to fill in.\n> 'commit' and 'identity' can have some elementary expansion and\n> validation tied to them.  Some easy extensiblity (hooks?) might not\n> hurt, but then as you point out, the existing hooks already cover that.\n>\n> Perhaps we could also have, for Gerrit (cf. [1]):\n>\n> [footer \"change-id\"]\n>         type = uuid\n>\n> though admittedly I haven't investigated if it's okay to just put a\n> random string there, or it needs to have a specific value.\n>\n> [1]  http://thread.gmane.org/gmane.comp.version-control.git/236429\n\nHow the config ends up looking is not actually that interesting to me\n(not at this stage, at least). My objection is to adding support for\nspecific footers with specific interpretations tailored specifically\nfor one (or a few) projects. Such things only open the door to more\nbloat. Instead, we already have the hooks for implementing such\nproject-specific rules and conventions. This is the core of my\nargument. Since then, the discussion has moved towards generic and\nflexible support for commonly-used footers, and I don't really have a\nproblem with that, as long as it is easily reusable (and extensible)\nby a project's own hooks.\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"229846","messageId":"CALKQrge8T8R7roUUYyLcu_QnL1afeqTATOp+0n_OOsZZoJXF4Q@mail.gmail.com","threadId":"35213","inReplyTo":"20131029020824.GE11861@sigill.intra.peff.net","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-10-30T18:12:16Z","receivedAt":"2013-10-30T18:12:16Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Tue, Oct 29, 2013 at 3:08 AM, Jeff King <peff@peff.net> wrote:\n> On Mon, Oct 28, 2013 at 12:29:32PM +0100, Johan Herland wrote:\n>> > A hook-based solution could do this.  But a built-in \"all-purpose\"\n>> > handler like \"footer.Fixes.arg=commit\", which was intended to be\n>> > reusable, wouldn't be able to do such footer-specific extra work without\n>> > having to create new special cases in git each time.\n>>\n>> Which begs the question (posed to all, not specifically to you): Why\n>> would we want solve this issue in config instead of in hooks? The\n>> hooks will always be more flexible and less dependent on making\n>> changes in git.git. (...a suitably flexible hook could even use the\n>> config options discussed above as input...) In both cases, we need the\n>> user to actively enable the functionality (either installing hooks, or\n>> setting up config), and in both cases we could bundle Git with\n>> defaults that solve the common cases, so that is not a useful\n>> differentiator between the two approaches. I would even venture to\n>> ask: If we end up solving this problem in config and not in hooks,\n>> then why do we bother having hooks in the first place?\n>\n> One thing that is much nicer with config vs hooks is that you can manage\n> config for all of your repositories by tweaking ~/.gitconfig (and that\n> is where I would expect this type of config to go).\n\nActually, I believe the use of footers are more often guided by\nproject conventions/rules, so I wouldn't expect such config to go into\n~/.gitconfig. I would rather expect to find it in an in-project config\nthat was included from the repo config...\n\n> Managing hooks globally means having each repo symlink to a central hook\n> area, and having the forethought to set up the symlink farm and use\n> init.templatedir before cloning any repos.  We could probably make this\n> friendlier by reading from ~/.githooks and defining some semantics for\n> multiple hooks. E.g., fall back to ~/.githooks if the repo hook is not\n> executable, or possibly run them both (or even allow multiple instances\n> of a hook in ~/.githooks, which can help organization), and consider the\n> hook a failure if any of them fail.\n\nYes, we do lack a good infrastructure for managing Git hooks from\nmultiple sources. It makes people afraid to use them, because they\nmight conflict with hooks from another source. There are (off the top\nof my head):\n\n - \"personal\" hooks (\"I want this behaviour in my repo(s)\")\n - \"project\" hooks (\"In this project we follow these conventions\")\n - \"system\" hooks (\"This host runs gitolite (or whatever) which needs\nthese hooks...\")\n - \"default\" hooks (Some of the core Git code could have be\nimplemented as hooks (e.g. \"--signoff\"), but is instead put into core\nGit)\n\nMaybe if we solved that problem, we could actually make use of hooks\ninstead of adding \"code\" to our git configs (by which I mean config\ndirectives that are flexible enough to encode all kinds of semantics\nand behaviors that are probably better expressed in real code...).\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"229847","messageId":"xmqqsivibobv.fsf@gitster.dls.corp.google.com","threadId":"35213","inReplyTo":"CA+8MBbK3dicmwOJb0mhTwr59O1tqzZgEGmMfSQV61Z=aK_64oA@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-10-30T18:33:56Z","receivedAt":"2013-10-30T18:33:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tony Luck <tony.luck@gmail.com> writes:\n\n> On Sat, Oct 26, 2013 at 6:34 PM, Josh Triplett <josh@joshtriplett.org> wrote:\n>\n>> +               format_commit_message(commit, \"Fixes: %h ('%s')\\n\", sb, &ctx);\n>\n> What is the value of double wrapping the commit message inside '...'\n> and then ('...')?\n\nGood point ;-)\n"},{"id":"229852","messageId":"CALKQrgdo=RP6vgCUML_L_NPsvSbg8Lyjy4HqmWYXk+NmWOjCvw@mail.gmail.com","threadId":"35213","inReplyTo":"CAP8UFD1eTmUGt7dWAP-Ws17op=z98hOvBa_g8_y=xS8WQ1dRMg@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-10-30T19:07:01Z","receivedAt":"2013-10-30T19:07:01Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Tue, Oct 29, 2013 at 7:23 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> On Mon, Oct 28, 2013 at 3:46 AM, Johan Herland <johan@herland.net> wrote:\n>> On Sun, Oct 27, 2013 at 8:04 PM, Christian Couder <christian.couder@gmail.com> wrote:\n>>> If \"git commit\" processes these arguments and puts the result in the\n>>> commit message file that is passed to the\n>>> prepare-commit-msg hook, then this hook can still get them from the\n>>> file and process them however it wants.\n>>>\n>>> And in most cases the processing could be the same as what is done by\n>>> the commit-msg hook when the user changes the \"Fixes: xxx\" and\n>>> \"Stuffed-by: yyy\" lines in the editor.\n>>>\n>>> So it would probably be easier for people customizing the\n>>> prepare-commit-msg and commit-msg if \"git commit\" processes the\n>>> arguments instead of just passing them to the prepare-commit-msg hook.\n>>>\n>>> And it will be better for people who don't set up any *commit-msg hook.\n>>> Even if there is no commit template, \"-f Acked-by:Peff\" and \"-f\n>>> Fixes:security-bug\" could still work.\n>>> I suspect most users don't setup any hook or commit template.\n>>\n>> Hmm. I'm not sure what you argue about which part of the system should\n>> perform which function. Let's examine the above options in more\n>> detail. Roughly, the flow of events look like this\n>>\n>>   git commit -f ack:Peff -f fix:security-bug\n>>     |\n>>     v\n>>   builtin/commit.c (i.e. inside \"git commit\")\n>>     |\n>>     v\n>>   prepare-commit-msg hook\n>>     |\n>>     v\n>>   commit message template:\n>>     Fixes: security-bug\n>>     Acked-by: Peff\n>\n> Here it could already be:\n>\n>      Fixes: 1234beef56 (Commit message summmary)\n>      Acked-by: Jeff King <peff@peff.net>\n>\n> Because builtin/commit.c hook could already have expanded everything.\n>\n>>     |\n>>     v\n>>   user edits commit message (may or may not change Fixes/Acked-by lines)\n>>     |\n>>     v\n>>   commit-msg hook\n>>     |\n>>     v\n>>   commit message:\n>>     Fixes: 1234beef56 (Commit message summmary)\n>>     Acked-by: Jeff King <peff@peff.net>\n>>\n>> (The above is even a bit simplified, but I believe it's sufficient for\n>> the current discussion.) So, there are several expansions happening\n>> between the initial \"git commit\" and the final commit message. They\n>> are:\n>>\n>>  1. \"fix\" -> \"Fixes: \"\n>>  2. \"security-bug\" -> \"1234beef56 (Commit message summmary)\"\n>>  3. \"ack\" -> \"Acked-by: \"\n>>  4. \"Peff\" -> \"Jeff King <peff@peff.net>\"\n>>\n>> First, I think we both agree that expansions #2 and #4 MUST be done by\n>> the commit-msg hook. The reason for this is two-fold: (a) the\n>> expansion must be done (at least) after the user has edited the commit\n>> message (since the values entered by the user might require the same\n>> expansion), and (b) how (and whether) to perform the expansion is a\n>> project-specific policy question, and not something that Git can\n>> dictate.\n>\n> I don't agree. Git doesn't need to dictate anything to be able to do\n> these expansions.\n> Git only needs some hints to do these expansions properly and it could\n> just look at the commit template, or the config, to get those hints.\n>\n> For example, if there is a \"Acked-by:\" line in the commit template,\n> then Git might decide that \"ack\" means \"Acked-by\", and then that \"-by\"\n> means that \"Peff\" should be related to an author, and then that it is\n> probably \"Jeff King <peff@peff.net>\".\n\nI don't like putting that much Magic into core Git... Especially not\ninto builtin/commit.c. However, if we - as you suggest further below -\nput it into a separate helper, and we make that helper available (and\nusable) from elsewhere (most importantly from hooks where\npeople/projects can add their own more specific functionality), then I\ndon't have a problem with it.\n\n[...]\n\n>>> Supporting project specific conventions/rules would still be possible\n>>> by processing lines in the commit message file without changing \"git\n>>> commit\".\n>>>\n>>> If \"git commit\" is already able to do some processing, it only adds\n>>> power to what can be done by people writing hooks.\n>>>\n>>> We could even have git plumbing commands used by git commit to process\n>>> the -f (or whatever option) arguments and they could be reused by the\n>>> *commit-msg hooks if they find them useful.\n>>\n>> Can you walk through an example of such reusable functionality?\n>\n> Ok, let's call the new plumbing command \"git interpret-trailers\".\n> And let's suppose that \"git commit\" is passed \"-f ack:Peff -f\n> fix:security-bug\" (or \"--trailer ack=Peff --trailer\n> fix=security-bug\").\n>\n> \"git commit\" would then call something like:\n>\n> git interpret-trailers --file commit_message_template.txt 'ack:Peff'\n> 'fix:security-bug'\n>\n> And this command would output:\n>\n> ------------------\n> <<<upper part of commit_message_template.txt>>>\n>\n> Fixes: 1234beef56 (Commit message summmary)\n> Reported-by:\n> Suggested-by:\n> Improved-by:\n> Acked-by: Jeff King <peff@peff.net>\n> Reviewed-by:\n> Tested-by:\n> Signed-off-by: Myself <myself@example.com>\n> ------------------\n>\n> Because it would have looked at the commit template it is passed and\n> filled in the blanks it could fill using the arguments it is also\n> passed.\n>\n> \"git commit\" would then put the above lines in the file that it passes\n> to the prepare-commit-msg hook.\n>\n> Then the prepare-commit-msg could just do nothing.\n>\n> After the user has edited the commit message, the commit-msg hook\n> could just call:\n>\n> git interpret-trailers --trim-empty --file commit_message.txt\n>\n> so that what the user changed is interpreted again.\n>\n> For example if the user changed the \"Reviewed-by:\" line to\n> \"Reviewed-by: Johan\", then the output would be:\n>\n> ------------------\n> <<<upper part of commit_message.txt>>>\n>\n> Fixes: 1234beef56 (Commit message summmary)\n> Acked-by: Jeff King <peff@peff.net>\n> Reviewed-by: Johan Herland <johan@herland.net>\n> Signed-off-by: Myself <myself@example.com>\n> ------------------\n>\n> And that would be the final commit message in most cases.\n\nThis approach looks OK to me, as long as we make sure that this\nfunctionality is (a) optional, (b) flexible/reusable from hooks, and\n(c) not bound tightly to core Git (and AFAICS, your proposal is just\nthat). As I said above, this stuff certainly does not belong in\nbuiltin/commit.c...\n\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"229872","messageId":"CACsJy8DVSpmmDw-jGJoJK171u5UeJR7GKPuX7QAK4=7yYn6n8Q@mail.gmail.com","threadId":"35213","inReplyTo":"CALKQrge8T8R7roUUYyLcu_QnL1afeqTATOp+0n_OOsZZoJXF4Q@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-31T06:28:44Z","receivedAt":"2013-10-31T06:28:44Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Oct 31, 2013 at 1:12 AM, Johan Herland <johan@herland.net> wrote:\n> Yes, we do lack a good infrastructure for managing Git hooks from\n> multiple sources. It makes people afraid to use them, because they\n> might conflict with hooks from another source. There are (off the top\n> of my head):\n>\n>  - \"personal\" hooks (\"I want this behaviour in my repo(s)\")\n>  - \"project\" hooks (\"In this project we follow these conventions\")\n>  - \"system\" hooks (\"This host runs gitolite (or whatever) which needs\n> these hooks...\")\n>  - \"default\" hooks (Some of the core Git code could have be\n> implemented as hooks (e.g. \"--signoff\"), but is instead put into core\n> Git)\n>\n> Maybe if we solved that problem, we could actually make use of hooks\n> instead of adding \"code\" to our git configs (by which I mean config\n> directives that are flexible enough to encode all kinds of semantics\n> and behaviors that are probably better expressed in real code...).\n\nOK how about, if $GIT_DIR/hooks/something is a directory, then the\ndirectory must contain a file named \"index\", listing all the hooks of\ntype \"something\". All the hooks in \"index\" will be executed in the\nlisting order. There could be directories inside .git/hooks/something\nto help categorize the scripts, so project hooks stay in \"project\"\nsubdirectory and so on.\n\nWith this we could provide \"git hook\" command to manipulate hooks and\ntest out the new combination of hooks. We could even select what\nscripts not to run for a particular run, say you don't want the s-o-b\nhook active when you commit this thing, you could run\n\n  git commit --exclude-hooks=pre-commit-msg/s-o-b\n\nYou could exclude hooks by pattern as well\n\n  git commit --exclude-hooks=\"pre-commit-msg/projects/*\"\n\nOr run an unsinstalled hook just one time\n\n  git commit --include-hooks=/path/to/my/hook\n\nHooks like \"Fixes\" may need input from the user. The hook could bail\nout if the required input is not given. But it maybe a good idea for\ngit to check and reject before running hooks, if the input is not\nspecified (e.g. from command line). I guess those extra info has to be\nin .git/config and be added to .git/config by \"git hook\" command,\nunless we have some convention to express those without running the hook.\n\nFor old Git versions that does not support this scheme, as directories\nusually have u+x, the hook directory should be mistaken as an\nexecutable and rejected when executed (permission denied in my test),\nwhich gives user a good warning that this repo should not be used with\nthis git version.\n-- \nDuy\n"},{"id":"229924","messageId":"xmqqa9hp9x2e.fsf@gitster.dls.corp.google.com","threadId":"35213","inReplyTo":"CACsJy8DVSpmmDw-jGJoJK171u5UeJR7GKPuX7QAK4=7yYn6n8Q@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-10-31T17:20:25Z","receivedAt":"2013-10-31T17:20:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> OK how about, if $GIT_DIR/hooks/something is a directory, then the\n> directory must contain a file named \"index\", listing all the hooks of\n> type \"something\". All the hooks in \"index\" will be executed in the\n> listing order.\n\nHooks that take arbitrary amount of information from the body read\ntheir standard input. How are your multiple hooks supposed to\ninteract?\n\nHooks that prevent you from doing something stupid signal allow/deny\nwith their exit code. Do you fail a commit if any of your pre-commit\nhook fails, or is it OK to commit as long as one of them says so?\nIf the former, do all the hooks described in the index still run, or\ndoes the first failure short-cut the remainder?\n"},{"id":"229984","messageId":"5272E1B9.6000705@googlemail.com","threadId":"35213","inReplyTo":"87zjpuznf1.fsf@thomasrast.ch","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-10-31T23:03:21Z","receivedAt":"2013-10-31T23:03:21Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On 10/27/2013 05:30 PM, Thomas Rast wrote:\n> Stefan Beller <stefanbeller@googlemail.com> writes:\n> \n>> I assembled an overview table, which plots the long options of \n>> git commands by the short letters.\n> [...]\n>> (In case thunderbird messes it up, here it is again http://pastebin.com/raw.php?i=JBci2Krx)\n>>\n>> As you can see, f is always --force except for git-config, where it is --file\n> \n> Woah!  Impressive work.  Did you autogenerate this?  If so, can we have\n> it as a small make target somewhere?  If not, can you send a patch to\n> put your table in Documentation somewhere?\n> \n\n[ Removing the linux related mailing lists and participants ]\n\nWould you mind to define \n> in Documentation somewhere\na little more precise?\nI cannot really find a suitable place for such a table as in the main\nDocumentation direcotry there are basically the man page informations \nand some git development related things, such as SubmittingPatches.\nThe sub directories are even less fitting, so maybe \n\tDocumentation/ShortOptions \nwould be fine?\n\nAnyway, as I couldn't really come up with a reliable way for the shell\ncommands, I just went manually through all the missing commands \n(be it written in shell or missing compiled commands), \nand added it to the script. The script itself was reworked a little,\nto better be able to add manual information.\n\nAny suggestions how to improve the script or the table itself is \nwelcome.\n\nThanks,\nStefan\n"},{"id":"229985","messageId":"1383260682-12364-1-git-send-email-stefanbeller@googlemail.com","threadId":"35213","inReplyTo":"5272E1B9.6000705@googlemail.com","subject":"[PATCH] Documentation: add a script to generate a (long/short) options overview","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-10-31T23:04:42Z","receivedAt":"2013-10-31T23:04:42Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Recently a discussion started on the mailing list, which short option\nshall be best for a long option. (-f being always --force and therefore\nshould not be reassigned another meaning in one particular command)\nSee http://www.mail-archive.com/git@vger.kernel.org/msg38456.html\n\nFor discussions as these we need a script to easily generate an\noverview of all available one letter options, and their long option\nequivalents.\n\nAs the list of options was not retrieved fully automated,\nthere might be minor errors or missing items.\n\nSigned-off-by: Stefan Beller <stefanbeller@googlemail.com>\n---\n Documentation/generateShortOptions.py | 460 ++++++++++++++++++++++++++++++++++\n 1 file changed, 460 insertions(+)\n create mode 100644 Documentation/generateShortOptions.py\n\ndiff --git a/Documentation/generateShortOptions.py b/Documentation/generateShortOptions.py\nnew file mode 100644\nindex 0000000..1d326f9\n--- /dev/null\n+++ b/Documentation/generateShortOptions.py\n@@ -0,0 +1,460 @@\n+#!/usr/bin/python\n+# This script generates a table, which should help you getting a\n+# better overview of the existing long and short options of the\n+# various git commands. This script actually is only suited for\n+# generating the table itself, as the collection of the options of\n+# the git commands needs to be done manually.\n+# For the majority of commands, which are written in C, a small patch\n+# such as the following helps to extract the relevant cases for this\n+# script. However you still need to go through the shell commands\n+# manually.\n+# diff --git a/parse-options.c b/parse-options.c\n+# index 62e9b1c..b356ca9 100644\n+# --- a/parse-options.c\n+# +++ b/parse-options.c\n+# @@ -500,6 +500,12 @@ int parse_options(int argc, const char **argv, const char *prefix,\n+#  {\n+#  \tstruct parse_opt_ctx_t ctx;\n+#\n+# +\tfor (; options->type != OPTION_END; options++) {\n+# +\t\tif (options->long_name && options->short_name)\n+# +\t\t\tprintf(\"%s,  %c, %s\\n\", argv[0], options->short_name, options->long_name);\n+# +\t}\n+# +\texit(1);\n+# +\n+#  \tparse_options_start(&ctx, argc, argv, prefix, options, flags);\n+#  \tswitch (parse_options_step(&ctx, options, usagestr)) {\n+#  \tcase PARSE_OPT_HELP:\n+# --\n+\n+\n+# Command, short option, long option\n+cmd_results=\"\"\"add,  n, dry-run\n+add,  v, verbose\n+add,  i, interactive\n+add,  p, patch\n+add,  e, edit\n+add,  f, force\n+add,  u, update\n+add,  N, intent-to-add\n+add,  A, all\n+\n+am, i, interactive\n+am, 3, 3way\n+am, q, quiet\n+am, s, signoff\n+am, u, utf8\n+am, k, keep\n+\n+annotate, p, porcelain\n+\n+apply,  3, 3way\n+apply,  R, reverse\n+apply,  v, verbose\n+\n+archive,  o, output\n+\n+blame, p, porcelain\n+blame, f, show-name\n+blame, n, show-number\n+blame, e, show-email\n+\n+branch,  v, verbose\n+branch,  q, quiet\n+branch,  t, track\n+branch,  u, set-upstream-to\n+branch,  r, remotes\n+branch,  a, all\n+branch,  d, delete\n+branch,  m, move\n+branch,  l, create-reflog\n+branch,  f, force\n+\n+check-attr,  a, all\n+\n+check-ignore,  q, quiet\n+check-ignore,  v, verbose\n+check-ignore,  n, non-matching\n+\n+checkout,  q, quiet\n+checkout,  t, track\n+checkout,  2, ours\n+checkout,  3, theirs\n+checkout,  f, force\n+checkout,  m, merge\n+checkout,  p, patch\n+\n+checkout-index,  a, all\n+checkout-index,  f, force\n+checkout-index,  q, quiet\n+checkout-index,  n, no-create\n+checkout-index,  u, index\n+\n+cherry,  v, verbose\n+\n+cherry-pick,  n, no-commit\n+cherry-pick,  e, edit\n+cherry-pick,  s, signoff\n+cherry-pick,  m, mainline\n+cherry-pick,  X, strategy-option\n+\n+clean,  q, quiet\n+clean,  n, dry-run\n+clean,  f, force\n+clean,  i, interactive\n+clean,  e, exclude\n+\n+clone,  v, verbose\n+clone,  q, quiet\n+clone,  n, no-checkout\n+clone,  l, local\n+clone,  s, shared\n+clone,  o, origin\n+clone,  b, branch\n+clone,  u, upload-pack\n+clone,  c, config\n+\n+commit,  q, quiet\n+commit,  v, verbose\n+commit,  F, file\n+commit,  m, message\n+commit,  c, reedit-message\n+commit,  C, reuse-message\n+commit,  s, signoff\n+commit,  t, template\n+commit,  e, edit\n+commit,  S, gpg-sign\n+commit,  a, all\n+commit,  i, include\n+commit,  p, patch\n+commit,  o, only\n+commit,  n, no-verify\n+commit,  z, null\n+commit,  u, untracked-files\n+\n+config,  f, file\n+config,  l, list\n+config,  e, edit\n+config,  z, null\n+\n+count-objects,  v, verbose\n+count-objects,  H, human-readable\n+\n+diff, u, patch\n+diff, p, patch\n+diff, U, unified\n+diff, B, break-rewrites\n+diff, M, find-renames\n+diff, C, find-copies\n+diff, D, irreversible-delete\n+diff, a, text\n+diff, b, ignore-space-change\n+diff, w, ignore-all-space\n+diff, W, function-context\n+\n+diff-files, u, patch\n+diff-files, p, patch\n+diff-files, U, unified\n+diff-files, B, break-rewrites\n+diff-files, M, find-renames\n+diff-files, C, find-copies\n+diff-files, D, irreversible-delete\n+diff-files, a, text\n+diff-files, b, ignore-space-change\n+diff-files, w, ignore-all-space\n+diff-files, W, function-context\n+diff-files, c, cc\n+# diff-index and diff-tree similar, to be done\n+\n+fetch,  v, verbose\n+fetch,  q, quiet\n+fetch,  a, append\n+fetch,  f, force\n+fetch,  m, multiple\n+fetch,  t, tags\n+fetch,  p, prune\n+fetch,  k, keep\n+fetch,  u, update-head-ok\n+\n+filter-branch, f, force\n+\n+fmt-merge-msg,  m, message\n+fmt-merge-msg,  F, file\n+\n+for-each-ref,  s, shell\n+for-each-ref,  p, perl\n+\n+format-patch,  n, numbered\n+format-patch,  N, no-numbered\n+format-patch,  s, signoff\n+format-patch,  v, reroll-count\n+format-patch,  o, output-directory\n+format-patch,  k, keep-subject\n+format-patch,  p, no-stat\n+format-patch,  q, quiet\n+\n+fsck,  v, verbose\n+\n+fsck-objects,  v, verbose\n+\n+gc,  q, quiet\n+\n+grep,  v, invert-match\n+grep,  i, ignore-case\n+grep,  w, word-regexp\n+grep,  a, text\n+grep,  E, extended-regexp\n+grep,  G, basic-regexp\n+grep,  F, fixed-strings\n+grep,  P, perl-regexp\n+grep,  n, line-number\n+grep,  l, files-with-matches\n+grep,  L, files-without-match\n+grep,  z, null\n+grep,  c, count\n+grep,  C, context\n+grep,  B, before-context\n+grep,  A, after-context\n+grep,  p, show-function\n+grep,  W, function-context\n+grep,  q, quiet\n+grep,  O, open-files-in-pager\n+\n+help,  a, all\n+help,  g, guides\n+help,  m, man\n+help,  w, web\n+help,  i, info\n+\n+init,  q, quiet\n+\n+init-db,  q, quiet\n+\n+insta-web, l, local\n+insta-web, d, httpd\n+insta-web, m, module-path\n+insta-web, p, port\n+insta-web, b, browser\n+\n+log,  q, quiet\n+\n+ls-files,  c, cached\n+ls-files,  d, deleted\n+ls-files,  m, modified\n+ls-files,  o, others\n+ls-files,  i, ignored\n+ls-files,  s, stage\n+ls-files,  k, killed\n+ls-files,  u, unmerged\n+ls-files,  x, exclude\n+ls-files,  X, exclude-from\n+\n+ls-tree,  l, long\n+\n+ls-remotes, h, heads\n+ls-remotes, t, tags\n+ls-remotes, u, upload-pack\n+\n+merge,  e, edit\n+merge,  s, strategy\n+merge,  X, strategy-option\n+merge,  m, message\n+merge,  n, no-stat\n+merge,  v, verbose\n+merge,  q, quiet\n+merge,  S, gpg-sign\n+merge,  s, strategy\n+merge,  X, strategy-option\n+\n+merge-base,  a, all\n+\n+merge-file,  p, stdout\n+merge-file,  q, quiet\n+\n+mv,  v, verbose\n+mv,  n, dry-run\n+mv,  f, force\n+\n+pack-objects,  q, quiet\n+\n+prune,  n, dry-run\n+prune,  v, verbose\n+\n+prune-packed,  n, dry-run\n+prune-packed,  q, quiet\n+\n+pull, a, append\n+pull, f, force\n+pull, k, keep\n+pull, u, update-head-ok\n+pull, n, no-stat\n+pull, q, quiet\n+pull, v, verbose\n+pull, r, rebase\n+pull,  s, strategy\n+pull,  X, strategy-option\n+\n+push,  v, verbose\n+push,  q, quiet\n+push,  n, dry-run\n+push,  f, force\n+push,  u, set-upstream\n+\n+quilt-import, n, dry-run\n+\n+rebase, f, force-rebase\n+rebase, i, interactive\n+rebase, p, preserve-merges\n+rebase, m, merge\n+rebase, n, no-stat\n+rebase, v, verbose\n+rebase, r, rebase\n+rebase,  s, strategy\n+rebase,  X, strategy-option\n+rebase, x, exec\n+\n+read-tree,  v, verbose\n+read-tree,  n, dry-run\n+\n+reflog,  q, quiet\n+\n+rev-list, n, max-count\n+rev-list, i, regexp-ignore-case\n+rev-list, E, extended-regexp\n+rev-list, F, fixed-strings\n+rev-list, g, walk-reflogs\n+\n+remote,  v, verbose\n+\n+repack,  q, quiet\n+repack,  l, local\n+\n+replace,  l, list\n+replace,  d, delete\n+replace,  f, force\n+\n+reset,  q, quiet\n+reset,  p, patch\n+\n+revert,  n, no-commit\n+revert,  e, edit\n+revert,  s, signoff\n+revert,  m, mainline\n+revert,  X, strategy-option\n+\n+rm,  n, dry-run\n+rm,  q, quiet\n+rm,  f, force\n+\n+show,  q, quiet\n+\n+show-branch,  a, all\n+show-branch,  r, remotes\n+show-branch,  g, reflog\n+\n+show-ref,  d, dereference\n+show-ref,  s, hash\n+show-ref,  q, quiet\n+\n+shortlog, n, numbered\n+shortlog, s, summary\n+shortlog, e, email\n+\n+stash, p, patch\n+stash, u, include-untracked\n+stash, a, all\n+stash, q, quiet\n+\n+stage,  n, dry-run\n+stage,  v, verbose\n+stage,  i, interactive\n+stage,  p, patch\n+stage,  e, edit\n+stage,  f, force\n+stage,  u, update\n+stage,  N, intent-to-add\n+stage,  A, all\n+\n+status,  v, verbose\n+status,  s, short\n+status,  b, branch\n+status,  z, null\n+status,  u, untracked-files\n+\n+stripspace, s, strip-comments\n+stripspace, c, comment-lines\n+\n+submodule, q, quiet\n+submodule, b, branch\n+submodule, f, force\n+submodule, n, summary-limit\n+submodule, N, no-fetch\n+\n+symbolic-ref,  q, quiet\n+symbolic-ref,  d, delete\n+\n+tag,  l, list\n+tag,  d, delete\n+tag,  v, verify\n+tag,  a, annotate\n+tag,  m, message\n+tag,  F, file\n+tag,  s, sign\n+tag,  u, local-user\n+tag,  f, force\n+\n+update-server-info,  f, force\n+\n+verify-pack,  v, verbose\n+verify-pack,  s, stat-only\n+\n+verify-tag,  v, verbose\n+\n+whatchanged,  q, quiet\"\"\"\n+\n+import subprocess\n+\n+column_len = {}\n+column_count = {}\n+cmdoptions={}\n+\n+for line in cmd_results.split(\"\\n\"):\n+\tif not len(line) or line.startswith('#'):\n+\t\tcontinue\n+\tname, short, long = line.split(\",\")\n+\n+\tif not short in column_len:\n+\t\tcolumn_len[short] = len(long)\n+\t\tcolumn_count[short] = 0\n+\tcolumn_len[short] = max(column_len[short], len(long))\n+\tcolumn_count[short] += 1\n+\n+\tif not name in cmdoptions:\n+\t\tcmdoptions[name] = {}\n+\tcmdoptions[name][short] = long\n+\n+longest_cmd = 0\n+for cmd in cmdoptions:\n+\tlongest_cmd = max(longest_cmd, len(cmd))\n+\n+print \" \"*(longest_cmd-len(\"Name\\\\short\")), \"Name\\\\short\",\n+\n+# let's sort the columns in a way, we can see most of the options on the left hand side\n+columns = []\n+for key, value in sorted(column_count.iteritems(), key=lambda (k,v): (-v,k)):\n+\tcolumns += [key]\n+\n+# print head line\n+for short in columns:\n+\tprint \"|\" + \" \"*(1+column_len[short]-len(short)) + short,\n+print\n+\n+# print line for each command\n+for cmd in sorted(cmdoptions):\n+\tprint \" \"*(longest_cmd-len(cmd)), cmd,\n+\tfor short in columns:\n+\t\ts = \"\"\n+\t\tif short in cmdoptions[cmd]:\n+\t\t\ts = cmdoptions[cmd][short]\n+\t\tprint \"|\" + \" \"*(1+column_len[short]-len(s)) + s,\n+\tprint \"  \", cmd\n-- \n1.8.4.1.605.g23c6912\n"},{"id":"229986","messageId":"5272E316.5090108@googlemail.com","threadId":"35213","inReplyTo":"1383260682-12364-1-git-send-email-stefanbeller@googlemail.com","subject":"Re: [PATCH] Documentation: add a script to generate a (long/short) options overview","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-10-31T23:09:10Z","receivedAt":"2013-10-31T23:09:10Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On 11/01/2013 12:04 AM, Stefan Beller wrote:\n> Recently a discussion started on the mailing list, which short option\n> shall be best for a long option. (-f being always --force and therefore\n> should not be reassigned another meaning in one particular command)\n> See http://www.mail-archive.com/git@vger.kernel.org/msg38456.html\n> \n> For discussions as these we need a script to easily generate an\n> overview of all available one letter options, and their long option\n> equivalents.\n> \n> As the list of options was not retrieved fully automated,\n> there might be minor errors or missing items.\n> \n> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>\n> ---\n>  Documentation/generateShortOptions.py | 460 ++++++++++++++++++++++++++++++++++\n>  1 file changed, 460 insertions(+)\n>  create mode 100644 Documentation/generateShortOptions.py\n> \n\nWhen trying to send a follow-up patch with the table itself, I got:\nfatal: /tmp/wHpJlnf1r5/0002-Documentation-add-table-viewing-short-long-options-f.patch: 19: patch contains a line longer than 998 characters\nwarning: no patches were sent\n\nIs this an artifical limitation or something that actually makes sense?\n\nAnyway here is the table, updated to carry more commands and sorted:\n\n>From 7d2ba0af3500f1629783dfc80aafe218dee8618c Mon Sep 17 00:00:00 2001\nFrom: Stefan Beller <stefanbeller@googlemail.com>\nDate: Fri, 1 Nov 2013 00:01:21 +0100\nSubject: [PATCH 2/2] Documentation: add table viewing (short/long) options for\n all commands\n\nSigned-off-by: Stefan Beller <stefanbeller@googlemail.com>\n---\n Documentation/ShortOptions.txt | 73 ++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 73 insertions(+)\n create mode 100644 Documentation/ShortOptions.txt\n\ndiff --git a/Documentation/ShortOptions.txt b/Documentation/ShortOptions.txt\nnew file mode 100644\nindex 0000000..dd76512\n--- /dev/null\n+++ b/Documentation/ShortOptions.txt\n@@ -0,0 +1,73 @@\n+         Name\\short |      q |             v |             n |          s |      f |         m |                u |         a |              p |        e |                   l |                X |            i |              n |                p |            d |                  u |                 o |             f |              F |               c |         t |     z |       a |                    b |      q |              A |              N |             k |                   i |               s |       3 |              C |         S |       b |       g |        r |            w |               B |            C |                    D |             M |        U |                 W |              c |           e |     k |            m |       r |        v |                 w |     2 |  \n              B |                E |             G |               H |                    L |                    O |            P |        R |                 W |        x |     3 |                E |\n              F |         N |      d |             g |      h |      l |     t |     x\n+                add |        |       verbose |       dry-run |            |  force |           |           update |           |          patch |     edit |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |            all |  intent-to-add |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          add\n+                 am |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |               utf8 |                   |               |                |                 |           |       |         |                      |  quiet |                |                |               |         interactive |         signoff |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |  keep |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |  3way |                  |\n                |           |        |               |        |        |       |          am\n+           annotate |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |        porcelain |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          annotate\n+              apply |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |    3way |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |  reverse |                   |          |       |                  |\n                |           |        |               |        |        |       |          apply\n+            archive |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |            output |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          archive\n+              blame |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |    show-number |        porcelain |              |                    |                   |     show-name |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |  show-email |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          blame\n+             branch |  quiet |       verbose |               |            |  force |      move |  set-upstream-to |       all |                |          |       create-reflog |                  |              |                |                  |       delete |                    |                   |               |                |                 |     track |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |  remotes |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          branch\n+         check-attr |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          check-attr\n+       check-ignore |  quiet |       verbose |  non-matching |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          check-ignore\n+           checkout |  quiet |               |               |            |  force |     merge |                  |           |          patch |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |     track |       |         |                      |        |                |                |               |                     |                 |  theirs |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |  ours |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          checkout\n+     checkout-index |  quiet |               |     no-create |            |  force |           |            index |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          checkout-index\n+             cherry |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          cherry\n+        cherry-pick |        |               |     no-commit |    signoff |        |  mainline |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          cherry-pick\n+              clean |  quiet |               |       dry-run |            |  force |           |                  |           |                |  exclude |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          clean\n+              clone |  quiet |       verbose |   no-checkout |     shared |        |           |      upload-pack |           |                |          |               local |                  |              |                |                  |              |                    |            origin |               |                |          config |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |  branch |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          clone\n+             commit |  quiet |       verbose |     no-verify |    signoff |        |   message |  untracked-files |       all |          patch |     edit |                     |                  |      include |                |                  |              |                    |              only |               |           file |  reedit-message |  template |  null |         |                      |        |                |                |               |                     |                 |         |  reuse-message |  gpg-sign |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          commit\n+             config |        |               |               |            |   file |           |                  |           |                |     edit |                list |                  |              |                |                  |              |                    |                   |               |                |                 |           |  null |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          config\n+      count-objects |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |  human-readable |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          count-objects\n+               diff |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |              patch |                   |               |                |                 |           |       |    text |  ignore-space-change |        |                |                |               |                     |                 |         |                |           |         |         |          |              |  break-rewrites |  find-copies |  irreversible-delete |  find-renames |  unified |  function-context |                |             |       |              |         |          |  ignore-all-space |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          diff\n+         diff-files |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |              patch |                   |               |                |                 |           |       |    text |  ignore-space-change |        |                |                |               |                     |                 |         |                |           |         |         |          |              |  break-rewrites |  find-copies |  irreversible-delete |  find-renames |  unified |  function-context |             cc |             |       |              |         |          |  ignore-all-space |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          diff-files\n+              fetch |  quiet |       verbose |               |            |  force |  multiple |   update-head-ok |    append |          prune |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |      tags |       |         |                      |        |                |                |          keep |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          fetch\n+      filter-branch |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |         force |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          filter-branch\n+      fmt-merge-msg |        |               |               |            |        |   message |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |           file |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          fmt-merge-msg\n+       for-each-ref |        |               |               |      shell |        |           |                  |           |           perl |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          for-each-ref\n+       format-patch |  quiet |  reroll-count |      numbered |    signoff |        |           |                  |           |        no-stat |          |                     |                  |              |                |                  |              |                    |  output-directory |               |                |                 |           |       |         |                      |        |                |    no-numbered |  keep-subject |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          format-patch\n+               fsck |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          fsck\n+       fsck-objects |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          fsck-objects\n+                 gc |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          gc\n+               grep |  quiet |  invert-match |   line-number |            |        |           |                  |      text |  show-function |          |  files-with-matches |                  |  ignore-case |                |                  |              |                    |                   |               |  fixed-strings |           count |           |  null |         |                      |        |  after-context |                |               |                     |                 |         |        context |           |         |         |          |  word-regexp |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n before-context |  extended-regexp |  basic-regexp |                 |  files-without-match |  open-files-in-pager |  perl-regexp |          |  function-context |          |       |                  |\n                |           |        |               |        |        |       |          grep\n+               help |        |               |               |            |        |       man |                  |       all |                |          |                     |                  |         info |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |  guides |          |          web |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          help\n+               init |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          init\n+            init-db |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          init-db\n+          insta-web |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |             port |              |                    |                   |               |                |                 |           |       |         |              browser |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |  module-path |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |  httpd |               |        |  local |       |          insta-web\n+                log |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          log\n+           ls-files |        |               |               |      stage |        |  modified |         unmerged |           |                |          |                     |     exclude-from |      ignored |                |                  |      deleted |                    |            others |               |                |          cached |           |       |         |                      |        |                |                |        killed |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |  exclude |       |                  |\n                |           |        |               |        |        |       |          ls-files\n+         ls-remotes |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |        upload-pack |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |  heads |        |  tags |          ls-remotes\n+            ls-tree |        |               |               |            |        |           |                  |           |                |          |                long |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          ls-tree\n+              merge |  quiet |       verbose |       no-stat |   strategy |        |   message |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |  gpg-sign |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          merge\n+         merge-base |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          merge-base\n+         merge-file |  quiet |               |               |            |        |           |                  |           |         stdout |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          merge-file\n+                 mv |        |       verbose |       dry-run |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          mv\n+       pack-objects |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          pack-objects\n+              prune |        |       verbose |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          prune\n+       prune-packed |  quiet |               |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          prune-packed\n+               pull |        |               |               |   strategy |        |           |                  |           |                |          |                     |  strategy-option |              |        no-stat |                  |              |     update-head-ok |                   |         force |                |                 |           |       |  append |                      |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |  keep |              |  rebase |  verbose |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          pull\n+               push |  quiet |       verbose |       dry-run |            |  force |           |     set-upstream |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          push\n+       quilt-import |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |        dry-run |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          quilt-import\n+          read-tree |        |       verbose |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          read-tree\n+             rebase |        |               |               |   strategy |        |           |                  |           |                |          |                     |  strategy-option |              |        no-stat |  preserve-merges |              |                    |                   |  force-rebase |                |                 |           |       |         |                      |        |                |                |               |         interactive |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |        merge |  rebase |  verbose |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |  exec    rebase\n+             reflog |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          reflog\n+             remote |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          remote\n+             repack |  quiet |               |               |            |        |           |                  |           |                |          |               local |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          repack\n+            replace |        |               |               |            |  force |           |                  |           |                |          |                list |                  |              |                |                  |       delete |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          replace\n+              reset |  quiet |               |               |            |        |           |                  |           |          patch |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          reset\n+           rev-list |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |      max-count |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |  regexp-ignore-case |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |  extended-regexp |\n  fixed-strings |           |        |  walk-reflogs |        |        |       |          rev-list\n+             revert |        |               |     no-commit |    signoff |        |  mainline |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          revert\n+                 rm |  quiet |               |       dry-run |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          rm\n+           shortlog |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |       numbered |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |         summary |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |       email |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          shortlog\n+               show |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          show\n+        show-branch |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |  reflog |  remotes |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          show-branch\n+           show-ref |  quiet |               |               |       hash |        |           |                  |           |                |          |                     |                  |              |                |                  |  dereference |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          show-ref\n+              stage |        |       verbose |       dry-run |            |  force |           |           update |           |          patch |     edit |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |            all |  intent-to-add |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          stage\n+              stash |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |  include-untracked |                   |               |                |                 |           |       |     all |                      |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          stash\n+             status |        |       verbose |               |      short |        |           |  untracked-files |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |  null |         |                      |        |                |                |               |                     |                 |         |                |           |  branch |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          status\n+         stripspace |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |  strip-comments |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |  comment-lines |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          stripspace\n+          submodule |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |  summary-limit |                  |              |                    |                   |         force |                |                 |           |       |         |               branch |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |  no-fetch |        |               |        |        |       |          submodule\n+       symbolic-ref |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |       delete |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          symbolic-ref\n+                tag |        |        verify |               |       sign |  force |   message |       local-user |  annotate |                |          |                list |                  |              |                |                  |       delete |                    |                   |               |           file |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          tag\n+ update-server-info |        |               |               |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          update-server-info\n+        verify-pack |        |       verbose |               |  stat-only |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          verify-pack\n+         verify-tag |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          verify-tag\n+        whatchanged |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  \n                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |\n                |           |        |               |        |        |       |          whatchanged\n-- \n1.8.4.1.605.g23c6912\n"},{"id":"229988","messageId":"20131031234514.GC41460@vauxhall.crustytoothpaste.net","threadId":"35213","inReplyTo":"5272E316.5090108@googlemail.com","subject":"Re: [PATCH] Documentation: add a script to generate a (long/short) options overview","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2013-10-31T23:45:14Z","receivedAt":"2013-10-31T23:45:14Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Fri, Nov 01, 2013 at 12:09:10AM +0100, Stefan Beller wrote:\n> On 11/01/2013 12:04 AM, Stefan Beller wrote:\n> > Recently a discussion started on the mailing list, which short option\n> > shall be best for a long option. (-f being always --force and therefore\n> > should not be reassigned another meaning in one particular command)\n> > See http://www.mail-archive.com/git@vger.kernel.org/msg38456.html\n> > \n> > For discussions as these we need a script to easily generate an\n> > overview of all available one letter options, and their long option\n> > equivalents.\n> > \n> > As the list of options was not retrieved fully automated,\n> > there might be minor errors or missing items.\n> > \n> > Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>\n> > ---\n> >  Documentation/generateShortOptions.py | 460 ++++++++++++++++++++++++++++++++++\n> >  1 file changed, 460 insertions(+)\n> >  create mode 100644 Documentation/generateShortOptions.py\n> > \n> \n> When trying to send a follow-up patch with the table itself, I got:\n> fatal: /tmp/wHpJlnf1r5/0002-Documentation-add-table-viewing-short-long-options-f.patch: 19: patch contains a line longer than 998 characters\n> warning: no patches were sent\n> \n> Is this an artifical limitation or something that actually makes sense?\n\nRFC 5321 forbids lines exceeding 1000 octets (including CRLF).  RFC 5322\nforbids lines exceeding 998 characters (excluding CRLF).  If you want to\nget around that, you need to base64-encode the content, which is\ngenerally discouraged when sending patches, I believe.\n\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187\n"},{"id":"229989","messageId":"CACsJy8CEnKxmhRYQqWoMVyLpfDUp7tqdnLxiV47XqaOFFCcUMw@mail.gmail.com","threadId":"35213","inReplyTo":"xmqqa9hp9x2e.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-31T23:52:35Z","receivedAt":"2013-10-31T23:52:35Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Nov 1, 2013 at 12:20 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> OK how about, if $GIT_DIR/hooks/something is a directory, then the\n>> directory must contain a file named \"index\", listing all the hooks of\n>> type \"something\". All the hooks in \"index\" will be executed in the\n>> listing order.\n>\n> Hooks that take arbitrary amount of information from the body read\n> their standard input. How are your multiple hooks supposed to\n> interact?\n\nIf each only needs to read a few lines from stdin, they can do so in\norder. If two hooks need to read till the end of stdin, they are\nincompatible. If we support some sort of hook signature, we could warn\nthe user when they combine the two. If not, the second's failing\n(because stdin is already closed) may show the incompatibility. \"git\nhook\" should support dry-run mode to test out new combinations.\n\n> Hooks that prevent you from doing something stupid signal allow/deny\n> with their exit code. Do you fail a commit if any of your pre-commit\n> hook fails, or is it OK to commit as long as one of them says so?\n> If the former, do all the hooks described in the index still run, or\n> does the first failure short-cut the remainder?\n\nOne failed hook fails the commit and stops the remaining from\nexecuting. You can skip the hook if you want with --exclude-hooks.\n-- \nDuy\n"},{"id":"229990","messageId":"xmqqtxfx2da2.fsf@gitster.dls.corp.google.com","threadId":"35213","inReplyTo":"20131031234514.GC41460@vauxhall.crustytoothpaste.net","subject":"Re: [PATCH] Documentation: add a script to generate a (long/short) options overview","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-11-01T00:09:41Z","receivedAt":"2013-11-01T00:09:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> RFC 5321 forbids lines exceeding 1000 octets (including CRLF).  RFC 5322\n> forbids lines exceeding 998 characters (excluding CRLF).  If you want to\n> get around that, you need to base64-encode the content, which is\n> generally discouraged when sending patches, I believe.\n\nAll true.\n\nA message like the one posted before and got a positive \"wow, good\nwork\", is a good thinkg to motivate somebody to work on bringing the\ncodebase and build procedure to aspire for producing that table from\nwithin the build procedure; I do not think this information fixed in\ntime belongs to the source tree (iow, making it into a patch form is\nof no use).  It will go stale over time without a way to automate\nthe synchronization somehow.\n"},{"id":"229991","messageId":"CALKQrgcTA6cODDMOwX_hNwsfKU-+X-rhgf0U9SVYqg7bpMAthA@mail.gmail.com","threadId":"35213","inReplyTo":"xmqqa9hp9x2e.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-11-01T00:16:33Z","receivedAt":"2013-11-01T00:16:33Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Thu, Oct 31, 2013 at 6:20 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>> OK how about, if $GIT_DIR/hooks/something is a directory, then the\n>> directory must contain a file named \"index\", listing all the hooks of\n>> type \"something\". All the hooks in \"index\" will be executed in the\n>> listing order.\n>\n> Hooks that take arbitrary amount of information from the body read\n> their standard input. How are your multiple hooks supposed to\n> interact?\n\nAs an example, at $dayjob we have a \"dispatcher\" post-receive hook\nrunning on our Git server that captures the current environment, and\nreads all of stdin. It then iterates through a (configurable) sequence\nof \"subhooks\" providing them each with a copy of the data that was\npassed to it. The \"subhooks\" may perform duties such as notifying\nautomated build and test systems, triggering updates of mirrors,\nupdating bug trackers, formatting and sending commit emails to mailing\nlists, etc. Some of them are run synchronously (redirecting their\noutput back to the push client), and some are run asynchronously\n(redirecting their output to logs). The nice thing is that each of the\n\"subhooks\" use the same post-receive hook interface, and is therefore\na fully capable stand-alone hook by itself (often implemented in\ndifferent languages, some of them are not even written by us), and\nalso fully independent of the other \"subhooks\". It is therefore\nrelatively straightforward to add, remove and mix hooks.\n\n> Hooks that prevent you from doing something stupid signal allow/deny\n> with their exit code. Do you fail a commit if any of your pre-commit\n> hook fails, or is it OK to commit as long as one of them says so?\n> If the former, do all the hooks described in the index still run, or\n> does the first failure short-cut the remainder?\n\nThis clearly needs to be configurable, as there are valid use cases\nfor all the behaviors you mention. That said, I believe that a sane\ndefault would be for a single hook failure to cause the entire\nchain-of-hooks to fail, including short-cutting the remainder of the\nhooks (at least for the hooks where the exit code determines the\noutcome of the entire operation). For example, one could envision a\nsequence of pre-commit hooks being configured something like this:\n\n  [hook \"pre-commit.check-whitespace\"]\n          run = /path/to/whitespace-checker\n          on-error = fail-later\n  [hook \"pre-commit.check-valid-ident\"]\n          run = /path/to/ident-checker\n          on-error = fail-later\n  [hook \"pre-commit.run-testsuite\"]\n          run = \"/path/to/testsuite --with --arguments\"\n          on-error = fail-later\n\nThe hooks would be run in sequence. The hook.pre-commit.*.run variable\nspecifies how to execute the hook (it is assumed that each of the\nconfigured hooks behaves according to the pre-commit hook interface).\nThe hook.pre-commit.*.on-error variable specifies how to handle a\nnon-zero exit code from the hook. Possible values would be \"abort\"\n(abort the remaining hooks and return failure immediately),\n\"fail-later\" (keep running the remainder of the hooks, but make sure\nwe do return failure in the end), or \"ignore\" (always pretend the hook\nreturns successfully). The default on-error behavior should IMHO be\n\"abort\", but in this case, we don't want to abort on the first\nfailure, as we'd rather report errors from _multiple_ hooks to the\nuser in a single go.\n\nSimilarly, a sequence of post-receive hooks could be configure like this:\n\n  [hook \"post-receive.trigger-buildbot\"]\n          run = /path/to/buildbot-trigger-hook\n  [hook \"post-receive.update-bugtracker\"]\n          run = /path/to/bugtracker-update-hook\n  [hook \"post-receive.trigger-mirror-update\"]\n          run = /path/to/mirror-update-hook\n          async = true\n          redirect-output = /var/log/mirror-update-hook.log\n  [hook \"post-receive.send-commit-emails\"]\n          run = /path/to/commit-emailer\n          async = true\n\nHere, the .on-error variable is probably less than useful, since\npost-receive hooks cannot affect the outcome of the push operation\n(and having one post-receive hook abort the running of another is\nprobably uncommon). Instead, the .async variable (default: false) is\nused to indicate which hooks should be run asynchronously (i.e. the\nclient does not have to wait for these hooks to complete).\n\nOn a server with many repos, you could even store the above in the\nglobal git config, to have the hooks available to all repos, and then\nuse hook.post-receive.*.enabled = true/false to turn hooks on/off for\nindividual repos.\n\n(A nice side-effect of putting this stuff in the config is that it\nmakes is easy to add/remove/manage hooks through our Gitolite setup -\nwhich already has support for managing per-repo config options in the\nGitolite config.)\n\nThis is just some initial thoughts about a possible config format. A\nmore important point though, is that we don't really need to add\nanything to core Git to support this. All we need to do is to\nimplement a set of \"dispatcher\" hooks that read the relevant\nconfiguration and perform the job accordingly.\n\nAlthough these \"dispatcher\" hooks could certainly be developed as a\nseparate project - more or less independent from git.git, I do believe\nthere would be considerable value in distributing them along with Git\nand easily enabling them (maybe even enabling them by default, as\nwithout the config options they would just be no-ops). Otherwise, it\nwould be hard to make them used/accepted widely enough to actually\nreplace current ad hoc solutions.\n\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"230035","messageId":"CAP8UFD0RvFo9cHm56+_HFOt2NOvqF0i=65irYd_0-TUbKm4WBA@mail.gmail.com","threadId":"35213","inReplyTo":"CALKQrgdo=RP6vgCUML_L_NPsvSbg8Lyjy4HqmWYXk+NmWOjCvw@mail.gmail.com","subject":"Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2013-11-02T12:54:52Z","receivedAt":"2013-11-02T12:54:52Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Oct 30, 2013 at 8:07 PM, Johan Herland <johan@herland.net> wrote:\n> On Tue, Oct 29, 2013 at 7:23 AM, Christian Couder\n> <christian.couder@gmail.com> wrote:\n>>\n>> I don't agree. Git doesn't need to dictate anything to be able to do\n>> these expansions.\n>> Git only needs some hints to do these expansions properly and it could\n>> just look at the commit template, or the config, to get those hints.\n>>\n>> For example, if there is a \"Acked-by:\" line in the commit template,\n>> then Git might decide that \"ack\" means \"Acked-by\", and then that \"-by\"\n>> means that \"Peff\" should be related to an author, and then that it is\n>> probably \"Jeff King <peff@peff.net>\".\n>\n> I don't like putting that much Magic into core Git... Especially not\n> into builtin/commit.c. However, if we - as you suggest further below -\n> put it into a separate helper, and we make that helper available (and\n> usable) from elsewhere (most importantly from hooks where\n> people/projects can add their own more specific functionality), then I\n> don't have a problem with it.\n\nOk, great! I started working on \"git interpret-trailers\" and I will\npost an RFC patch soon.\nIt will support both configuration as Junio suggested and reading a\ncommit template file as you suggested.\n\n>> Ok, let's call the new plumbing command \"git interpret-trailers\".\n>> And let's suppose that \"git commit\" is passed \"-f ack:Peff -f\n>> fix:security-bug\" (or \"--trailer ack=Peff --trailer\n>> fix=security-bug\").\n>>\n>> \"git commit\" would then call something like:\n>>\n>> git interpret-trailers --file commit_message_template.txt 'ack:Peff'\n>> 'fix:security-bug'\n>>\n>> And this command would output:\n>>\n>> ------------------\n>> <<<upper part of commit_message_template.txt>>>\n>>\n>> Fixes: 1234beef56 (Commit message summmary)\n>> Reported-by:\n>> Suggested-by:\n>> Improved-by:\n>> Acked-by: Jeff King <peff@peff.net>\n>> Reviewed-by:\n>> Tested-by:\n>> Signed-off-by: Myself <myself@example.com>\n>> ------------------\n>>\n>> Because it would have looked at the commit template it is passed and\n>> filled in the blanks it could fill using the arguments it is also\n>> passed.\n>>\n>> \"git commit\" would then put the above lines in the file that it passes\n>> to the prepare-commit-msg hook.\n>>\n>> Then the prepare-commit-msg could just do nothing.\n>>\n>> After the user has edited the commit message, the commit-msg hook\n>> could just call:\n>>\n>> git interpret-trailers --trim-empty --file commit_message.txt\n>>\n>> so that what the user changed is interpreted again.\n>>\n>> For example if the user changed the \"Reviewed-by:\" line to\n>> \"Reviewed-by: Johan\", then the output would be:\n>>\n>> ------------------\n>> <<<upper part of commit_message.txt>>>\n>>\n>> Fixes: 1234beef56 (Commit message summmary)\n>> Acked-by: Jeff King <peff@peff.net>\n>> Reviewed-by: Johan Herland <johan@herland.net>\n>> Signed-off-by: Myself <myself@example.com>\n>> ------------------\n>>\n>> And that would be the final commit message in most cases.\n>\n> This approach looks OK to me, as long as we make sure that this\n> functionality is (a) optional, (b) flexible/reusable from hooks, and\n> (c) not bound tightly to core Git (and AFAICS, your proposal is just\n> that). As I said above, this stuff certainly does not belong in\n> builtin/commit.c...\n\nOk, I think it will be very easy to do all with \"git interpret-trailers\".\n\nBest regards,\nChristian.\n"}]}