{"thread":{"id":"25383","subject":"[PATCHv5 2/8] commit.c: new function for looking up a comit by name","startedAt":"2010-10-07T19:10:49Z","lastAt":"2010-10-13T22:44:14Z","messageCount":17,"participants":["Pat Notz","Sverre Rabbelier","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"152912","messageId":"1286478657-61581-1-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":null,"subject":"[PATCHv5 0/8] Add commit message options for rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:49Z","receivedAt":"2010-10-07T19:10:49Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"This patch series adds new command line options to git-commit to make\nit easy to specify messages for commits correctly formatted for use\nwit 'rebase -i --autosquash'.\n\nThe first three patches introduce minor refactorings that set the stage\nfor subsequent patches.\n\nThe fourth patch teaches format_commit_message to reencode the content\nif the caller's commit object uses an encoding different from the\ncommit encoding.\n\nThe remaining patches add the --fixup and --squash commands to\ngit-commit including tests of commit, interactions with rebase and\ni18n encodings.  \n\nOne issue which limits the testing (but not the implementation, I\nthink) is that when 'rebase --autosquash' is comparing commit subject\nlines it does not first make sure that the commits use a common\nencoding.  That's follow-on work.\n\nPat Notz (8):\n  commit.c: prefer get_header() to manual searching\n  commit.c: new function for looking up a comit by name\n  pretty.c: helper methods for getting output encodings\n  pretty.c: teach format_commit_message() to reencode the output\n  commit: --fixup option for use with rebase --autosquash\n  add tests of commit --fixup\n  commit: --squash option for use with rebase --autosquash\n  add tests of commit --squash\n\n Documentation/git-commit.txt |   21 +++++++++--\n archive.c                    |    2 +-\n builtin/commit.c             |   76 +++++++++++++++++++++++++++------------\n builtin/fmt-merge-msg.c      |    2 +-\n cache.h                      |    3 ++\n commit.c                     |   13 +++++++\n commit.h                     |    5 ++-\n environment.c                |   11 ++++++\n log-tree.c                   |    2 +-\n notes-cache.c                |    2 +-\n pretty.c                     |   47 +++++++++++++++++++-----\n submodule.c                  |    4 +-\n t/t3415-rebase-autosquash.sh |   29 ++++++++++++++-\n t/t3900-i18n-commit.sh       |   28 +++++++++++++++\n t/t7500-commit.sh            |   80 ++++++++++++++++++++++++++++++++++++++++++\n t/t7500/edit-content         |    4 ++\n 16 files changed, 283 insertions(+), 46 deletions(-)\n create mode 100755 t/t7500/edit-content\n\n-- \n1.7.3.1\n"},{"id":"152910","messageId":"1286478657-61581-2-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 1/8] commit.c: prefer get_header() to manual searching","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:50Z","receivedAt":"2010-10-07T19:10:50Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"Signed-off-by: Pat Notz <patnotz@gmail.com>\n---\n builtin/commit.c |   11 +++--------\n commit.h         |    1 +\n pretty.c         |    2 +-\n 3 files changed, 5 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 66fdd22..bf9fcc1 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -899,7 +899,7 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tunsigned char sha1[20];\n \t\tstatic char utf8[] = \"UTF-8\";\n \t\tconst char *out_enc;\n-\t\tchar *enc, *end;\n+\t\tchar *enc;\n \t\tstruct commit *commit;\n \n \t\tif (get_sha1(use_message, sha1))\n@@ -908,13 +908,8 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tif (!commit || parse_commit(commit))\n \t\t\tdie(\"could not parse commit %s\", use_message);\n \n-\t\tenc = strstr(commit->buffer, \"\\nencoding\");\n-\t\tif (enc) {\n-\t\t\tend = strchr(enc + 10, '\\n');\n-\t\t\tenc = xstrndup(enc + 10, end - (enc + 10));\n-\t\t} else {\n-\t\t\tenc = utf8;\n-\t\t}\n+\t\tenc = get_header(commit, \"encoding\");\n+\t\tenc = enc ? enc : utf8;\n \t\tout_enc = git_commit_encoding ? git_commit_encoding : utf8;\n \n \t\tif (strcmp(out_enc, enc))\ndiff --git a/commit.h b/commit.h\nindex 9113bbe..c246c94 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -87,6 +87,7 @@ struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */\n extern char *reencode_commit_message(const struct commit *commit,\n \t\t\t\t     const char **encoding_p);\n extern void get_commit_format(const char *arg, struct rev_info *);\n+extern char *get_header(const struct commit *commit, const char *key);\n extern void userformat_find_requirements(const char *fmt, struct userformat_want *w);\n extern void format_commit_message(const struct commit *commit,\n \t\t\t\t  const char *format, struct strbuf *sb,\ndiff --git a/pretty.c b/pretty.c\nindex f85444b..839944c 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -348,7 +348,7 @@ static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,\n \tstrbuf_addch(sb, '\\n');\n }\n \n-static char *get_header(const struct commit *commit, const char *key)\n+char *get_header(const struct commit *commit, const char *key)\n {\n \tint key_len = strlen(key);\n \tconst char *line = commit->buffer;\n-- \n1.7.3.1\n"},{"id":"152909","messageId":"1286478657-61581-3-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 2/8] commit.c: new function for looking up a comit by name","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:51Z","receivedAt":"2010-10-07T19:10:51Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"Signed-off-by: Pat Notz <patnotz@gmail.com>\n---\n builtin/commit.c |    7 +------\n commit.c         |   13 +++++++++++++\n commit.h         |    1 +\n 3 files changed, 15 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex bf9fcc1..9fe4bdc 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -896,17 +896,12 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \tif (!use_message && renew_authorship)\n \t\tdie(\"--reset-author can be used only with -C, -c or --amend.\");\n \tif (use_message) {\n-\t\tunsigned char sha1[20];\n \t\tstatic char utf8[] = \"UTF-8\";\n \t\tconst char *out_enc;\n \t\tchar *enc;\n \t\tstruct commit *commit;\n \n-\t\tif (get_sha1(use_message, sha1))\n-\t\t\tdie(\"could not lookup commit %s\", use_message);\n-\t\tcommit = lookup_commit_reference(sha1);\n-\t\tif (!commit || parse_commit(commit))\n-\t\t\tdie(\"could not parse commit %s\", use_message);\n+\t\tcommit = lookup_commit_reference_by_name(use_message);\n \n \t\tenc = get_header(commit, \"encoding\");\n \t\tenc = enc ? enc : utf8;\ndiff --git a/commit.c b/commit.c\nindex 0094ec1..f51098a 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -49,6 +49,19 @@ struct commit *lookup_commit(const unsigned char *sha1)\n \treturn check_commit(obj, sha1, 0);\n }\n \n+struct commit *lookup_commit_reference_by_name(const char *name)\n+{\n+\tunsigned char sha1[20];\n+\tstruct commit *commit;\n+\n+\tif (get_sha1(name, sha1))\n+\t\tdie(\"could not lookup commit %s\", name);\n+\tcommit = lookup_commit_reference(sha1);\n+\tif (!commit || parse_commit(commit))\n+\t\tdie(\"could not parse commit %s\", name);\n+\treturn commit;\n+}\n+\n static unsigned long parse_commit_date(const char *buf, const char *tail)\n {\n \tconst char *dateptr;\ndiff --git a/commit.h b/commit.h\nindex c246c94..6f4b586 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -36,6 +36,7 @@ struct commit *lookup_commit(const unsigned char *sha1);\n struct commit *lookup_commit_reference(const unsigned char *sha1);\n struct commit *lookup_commit_reference_gently(const unsigned char *sha1,\n \t\t\t\t\t      int quiet);\n+struct commit *lookup_commit_reference_by_name(const char *name);\n \n int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);\n \n-- \n1.7.3.1\n"},{"id":"152914","messageId":"1286478657-61581-4-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 3/8] pretty.c: helper methods for getting output encodings","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:52Z","receivedAt":"2010-10-07T19:10:52Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"Add helpers get_log_output_encoding() and get_commit_output_encoding()\nthat eliminate some messy and duplicate if-blocks.\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\n builtin/commit.c |    2 +-\n cache.h          |    3 +++\n environment.c    |   11 +++++++++++\n pretty.c         |    6 +-----\n 4 files changed, 16 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 9fe4bdc..ea3801d 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -905,7 +905,7 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \n \t\tenc = get_header(commit, \"encoding\");\n \t\tenc = enc ? enc : utf8;\n-\t\tout_enc = git_commit_encoding ? git_commit_encoding : utf8;\n+\t\tout_enc = get_commit_output_encoding();\n \n \t\tif (strcmp(out_enc, enc))\n \t\t\tuse_message_buffer =\ndiff --git a/cache.h b/cache.h\nindex 3d5ed51..7d49805 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1003,6 +1003,9 @@ extern int git_env_bool(const char *, int);\n extern int git_config_system(void);\n extern int git_config_global(void);\n extern int config_error_nonbool(const char *);\n+extern const char *get_log_output_encoding(void);\n+extern const char *get_commit_output_encoding(void);\n+\n extern const char *config_exclusive_filename;\n \n #define MAX_GITNAME (1000)\ndiff --git a/environment.c b/environment.c\nindex de5581f..a9d44a2 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -192,3 +192,14 @@ int set_git_dir(const char *path)\n \tsetup_git_env();\n \treturn 0;\n }\n+\n+const char *get_log_output_encoding(void)\n+{\n+\treturn git_log_output_encoding ? git_log_output_encoding\n+\t\t: get_commit_output_encoding();\n+}\n+\n+const char *get_commit_output_encoding(void)\n+{\n+\treturn git_commit_encoding ? git_commit_encoding : \"UTF-8\";\n+}\ndiff --git a/pretty.c b/pretty.c\nindex 839944c..a607fd6 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1159,11 +1159,7 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding\n {\n \tconst char *encoding;\n \n-\tencoding = (git_log_output_encoding\n-\t\t    ? git_log_output_encoding\n-\t\t    : git_commit_encoding);\n-\tif (!encoding)\n-\t\tencoding = \"UTF-8\";\n+\tencoding = get_log_output_encoding();\n \tif (encoding_p)\n \t\t*encoding_p = encoding;\n \treturn logmsg_reencode(commit, encoding);\n-- \n1.7.3.1\n"},{"id":"152915","messageId":"1286478657-61581-5-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 4/8] pretty.c: teach format_commit_message() to reencode the output","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:53Z","receivedAt":"2010-10-07T19:10:53Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"format_commit_message() will now reencode the content if the desired\noutput encoding is different from the encoding in the passed in\ncommit.\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\n archive.c               |    2 +-\n builtin/commit.c        |    6 +++---\n builtin/fmt-merge-msg.c |    2 +-\n commit.h                |    3 ++-\n log-tree.c              |    2 +-\n notes-cache.c           |    2 +-\n pretty.c                |   39 +++++++++++++++++++++++++++++++++++----\n submodule.c             |    4 ++--\n 8 files changed, 46 insertions(+), 14 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex edd6853..42b7ab1 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -51,7 +51,7 @@ static void format_subst(const struct commit *commit,\n \t\tstrbuf_add(&fmt, b + 8, c - b - 8);\n \n \t\tstrbuf_add(buf, src, b - src);\n-\t\tformat_commit_message(commit, fmt.buf, buf, &ctx);\n+\t\tformat_commit_message(commit, fmt.buf, buf, &ctx, NULL);\n \t\tlen -= c + 1 - src;\n \t\tsrc  = c + 1;\n \t}\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex ea3801d..e66f10c 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -826,7 +826,7 @@ static const char *find_author_by_nickname(const char *name)\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.date_mode = DATE_NORMAL;\n \t\tstrbuf_release(&buf);\n-\t\tformat_commit_message(commit, \"%an <%ae>\", &buf, &ctx);\n+\t\tformat_commit_message(commit, \"%an <%ae>\", &buf, &ctx, NULL);\n \t\treturn strbuf_detach(&buf, NULL);\n \t}\n \tdie(\"No existing author found with '%s'\", name);\n@@ -1135,8 +1135,8 @@ static void print_summary(const char *prefix, const unsigned char *sha1)\n \n \tstrbuf_addstr(&format, \"format:%h] %s\");\n \n-\tformat_commit_message(commit, \"%an <%ae>\", &author_ident, &pctx);\n-\tformat_commit_message(commit, \"%cn <%ce>\", &committer_ident, &pctx);\n+\tformat_commit_message(commit, \"%an <%ae>\", &author_ident, &pctx, NULL);\n+\tformat_commit_message(commit, \"%cn <%ce>\", &committer_ident, &pctx, NULL);\n \tif (strbuf_cmp(&author_ident, &committer_ident)) {\n \t\tstrbuf_addstr(&format, \"\\n Author: \");\n \t\tstrbuf_addbuf_percentquote(&format, &author_ident);\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex 78c7774..7619f4f 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -173,7 +173,7 @@ static void shortlog(const char *name, unsigned char *sha1,\n \t\tif (subjects.nr > limit)\n \t\t\tcontinue;\n \n-\t\tformat_commit_message(commit, \"%s\", &sb, &ctx);\n+\t\tformat_commit_message(commit, \"%s\", &sb, &ctx, NULL);\n \t\tstrbuf_ltrim(&sb);\n \n \t\tif (!sb.len)\ndiff --git a/commit.h b/commit.h\nindex 6f4b586..51c7110 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -92,7 +92,8 @@ extern char *get_header(const struct commit *commit, const char *key);\n extern void userformat_find_requirements(const char *fmt, struct userformat_want *w);\n extern void format_commit_message(const struct commit *commit,\n \t\t\t\t  const char *format, struct strbuf *sb,\n-\t\t\t\t  const struct pretty_print_context *context);\n+\t\t\t\t  const struct pretty_print_context *context,\n+\t\t\t\t  const char *output_encoding);\n extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \t\t\t\tstruct strbuf *sb,\n \t\t\t\tconst struct pretty_print_context *context);\ndiff --git a/log-tree.c b/log-tree.c\nindex b46ed3b..af3200d 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -274,7 +274,7 @@ void get_patch_filename(struct commit *commit, int nr, const char *suffix,\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.date_mode = DATE_NORMAL;\n \n-\t\tformat_commit_message(commit, \"%f\", buf, &ctx);\n+\t\tformat_commit_message(commit, \"%f\", buf, &ctx, NULL);\n \t\tif (max_len < buf->len)\n \t\t\tstrbuf_setlen(buf, max_len);\n \t\tstrbuf_addstr(buf, suffix);\ndiff --git a/notes-cache.c b/notes-cache.c\nindex dee6d62..461c474 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -19,7 +19,7 @@ static int notes_cache_match_validity(const char *ref, const char *validity)\n \t\treturn 0;\n \n \tmemset(&pretty_ctx, 0, sizeof(pretty_ctx));\n-\tformat_commit_message(commit, \"%s\", &msg, &pretty_ctx);\n+\tformat_commit_message(commit, \"%s\", &msg, &pretty_ctx, NULL);\n \tstrbuf_trim(&msg);\n \n \tret = !strcmp(msg.buf, validity);\ndiff --git a/pretty.c b/pretty.c\nindex a607fd6..e5ce7fb 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1009,16 +1009,47 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w)\n \n void format_commit_message(const struct commit *commit,\n \t\t\t   const char *format, struct strbuf *sb,\n-\t\t\t   const struct pretty_print_context *pretty_ctx)\n+\t\t\t   const struct pretty_print_context *pretty_ctx,\n+\t\t\t   const char *output_encoding)\n {\n \tstruct format_commit_context context;\n+\tstatic char utf8[] = \"UTF-8\";\n+\tchar *enc;\n+\tchar *buffer;\n+\tchar *enc_buffer;\n+\tstruct strbuf scratch_sb = STRBUF_INIT;\n+\tstruct strbuf *sb_ptr;\n+\n+\tenc = get_header(commit, \"encoding\");\n+\tenc = enc ? enc : utf8;\n+\tif(output_encoding && strcmp(enc,output_encoding)) {\n+\t\tsb_ptr = &scratch_sb;\n+\t} else {\n+\t\tsb_ptr = sb;\n+\t}\n \n \tmemset(&context, 0, sizeof(context));\n \tcontext.commit = commit;\n \tcontext.pretty_ctx = pretty_ctx;\n \tcontext.wrap_start = sb->len;\n-\tstrbuf_expand(sb, format, format_commit_item, &context);\n-\trewrap_message_tail(sb, &context, 0, 0, 0);\n+\tstrbuf_expand(sb_ptr, format, format_commit_item, &context);\n+\trewrap_message_tail(sb_ptr, &context, 0, 0, 0);\n+\n+\tif(sb_ptr != sb) {\n+\t\t/* if re-encoding fails, take the content byte-for-byte */\n+\t\tbuffer = strbuf_detach(sb_ptr, 0);\n+\t\tenc_buffer = reencode_string(buffer, output_encoding, enc);\n+\t\tenc_buffer = enc_buffer ? enc_buffer : buffer;\n+\n+\t\tstrbuf_addstr(sb,enc_buffer);\n+\n+\t\tif(enc_buffer != buffer)\n+\t\t\tfree(enc_buffer);\n+\t\tfree(buffer);\n+\t}\n+\n+\tif(enc != utf8)\n+\t\tfree(enc);\n }\n \n static void pp_header(enum cmit_fmt fmt,\n@@ -1177,7 +1208,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \tint need_8bit_cte = context->need_8bit_cte;\n \n \tif (fmt == CMIT_FMT_USERFORMAT) {\n-\t\tformat_commit_message(commit, user_format, sb, context);\n+\t\tformat_commit_message(commit, user_format, sb, context, NULL);\n \t\treturn;\n \t}\n \ndiff --git a/submodule.c b/submodule.c\nindex 91a4758..c108ff6 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -217,7 +217,7 @@ void show_submodule_summary(FILE *f, const char *path,\n \t\t\t}\n \t\t\telse if (add)\n \t\t\t\tstrbuf_addstr(&sb, add);\n-\t\t\tformat_commit_message(commit, format, &sb, &ctx);\n+\t\t\tformat_commit_message(commit, format, &sb, &ctx, NULL);\n \t\t\tif (reset)\n \t\t\t\tstrbuf_addstr(&sb, reset);\n \t\t\tstrbuf_addch(&sb, '\\n');\n@@ -362,7 +362,7 @@ static void print_commit(struct commit *commit)\n \tstruct strbuf sb = STRBUF_INIT;\n \tstruct pretty_print_context ctx = {0};\n \tctx.date_mode = DATE_NORMAL;\n-\tformat_commit_message(commit, \" %h: %m %s\", &sb, &ctx);\n+\tformat_commit_message(commit, \" %h: %m %s\", &sb, &ctx, NULL);\n \tfprintf(stderr, \"%s\\n\", sb.buf);\n \tstrbuf_release(&sb);\n }\n-- \n1.7.3.1\n"},{"id":"152913","messageId":"1286478657-61581-6-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 5/8] commit: --fixup option for use with rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:54Z","receivedAt":"2010-10-07T19:10:54Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"This option makes it convenient to construct commit messages for use\nwith 'rebase --autosquash'.  The resulting commit message will be\n\"fixup! ...\" where \"...\" is the subject line of the specified commit\nmessage.\n\nExample usage:\n  $ git commit --fixup HEAD~2\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\n Documentation/git-commit.txt |   14 ++++++++++----\n builtin/commit.c             |   20 ++++++++++++++++----\n 2 files changed, 26 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 42fb1f5..f4a2b8c 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -9,10 +9,10 @@ SYNOPSIS\n --------\n [verse]\n 'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend] [--dry-run]\n-\t   [(-c | -C) <commit>] [-F <file> | -m <msg>] [--reset-author]\n-\t   [--allow-empty] [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n-\t   [--date=<date>] [--cleanup=<mode>] [--status | --no-status] [--]\n-\t   [[-i | -o ]<file>...]\n+\t   [(-c | -C | --fixup) <commit>] [-F <file> | -m <msg>]\n+\t   [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify]\n+\t   [-e] [--author=<author>] [--date=<date>] [--cleanup=<mode>]\n+\t   [--status | --no-status] [--] [[-i | -o ]<file>...]\n \n DESCRIPTION\n -----------\n@@ -70,6 +70,12 @@ OPTIONS\n \tLike '-C', but with '-c' the editor is invoked, so that\n \tthe user can further edit the commit message.\n \n+--fixup=<commit>::\n+\tConstruct a commit message for use with `rebase --autosquash`.\n+\tThe commit message will be the subject line from the specified\n+\tcommit with a prefix of \"fixup! \".  See linkgit:git-rebase[1]\n+\tfor details.\n+\n --reset-author::\n \tWhen used with -C/-c/--amend options, declare that the\n \tauthorship of the resulting commit now belongs of the committer.\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex e66f10c..851bb59 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -69,6 +69,7 @@ static enum {\n static const char *logfile, *force_author;\n static const char *template_file;\n static char *edit_message, *use_message;\n+static char *fixup_message;\n static char *author_name, *author_email, *author_date;\n static int all, edit_flag, also, interactive, only, amend, signoff;\n static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;\n@@ -124,6 +125,7 @@ static struct option builtin_commit_options[] = {\n \tOPT_CALLBACK('m', \"message\", &message, \"MESSAGE\", \"specify commit message\", opt_parse_m),\n \tOPT_STRING('c', \"reedit-message\", &edit_message, \"COMMIT\", \"reuse and edit message from specified commit\"),\n \tOPT_STRING('C', \"reuse-message\", &use_message, \"COMMIT\", \"reuse message from specified commit\"),\n+\tOPT_STRING(0, \"fixup\", &fixup_message, \"COMMIT\", \"use autosquash formatted message to fixup specified commit\"),\n \tOPT_BOOLEAN(0, \"reset-author\", &renew_authorship, \"the commit is authored by me now (used with -C-c/--amend)\"),\n \tOPT_BOOLEAN('s', \"signoff\", &signoff, \"add Signed-off-by:\"),\n \tOPT_FILENAME('t', \"template\", &template_file, \"use specified template file\"),\n@@ -586,6 +588,14 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tstrbuf_add(&sb, buffer + 2, strlen(buffer + 2));\n \t\thook_arg1 = \"commit\";\n \t\thook_arg2 = use_message;\n+\t} else if (fixup_message) {\n+\t\tstruct pretty_print_context ctx = {0};\n+\t\tstruct commit *commit;\n+\t\tconst char *out_enc;\n+\t\tcommit = lookup_commit_reference_by_name(fixup_message);\n+\t\tout_enc = get_commit_output_encoding();\n+\t\tformat_commit_message(commit, \"fixup! %s\\n\\n\", &sb, &ctx, out_enc);\n+\t\thook_arg1 = \"message\";\n \t} else if (!stat(git_path(\"MERGE_MSG\"), &statbuf)) {\n \t\tif (strbuf_read_file(&sb, git_path(\"MERGE_MSG\"), 0) < 0)\n \t\t\tdie_errno(\"could not read MERGE_MSG\");\n@@ -863,7 +873,7 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \tif (force_author && renew_authorship)\n \t\tdie(\"Using both --reset-author and --author does not make sense\");\n \n-\tif (logfile || message.len || use_message)\n+\tif (logfile || message.len || use_message || fixup_message)\n \t\tuse_editor = 0;\n \tif (edit_flag)\n \t\tuse_editor = 1;\n@@ -883,15 +893,17 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tf++;\n \tif (edit_message)\n \t\tf++;\n+\tif (fixup_message)\n+\t\tf++;\n \tif (logfile)\n \t\tf++;\n \tif (f > 1)\n-\t\tdie(\"Only one of -c/-C/-F can be used.\");\n+\t\tdie(\"Only one of -c/-C/-F/--fixup can be used.\");\n \tif (message.len && f > 0)\n-\t\tdie(\"Option -m cannot be combined with -c/-C/-F.\");\n+\t\tdie(\"Option -m cannot be combined with -c/-C/-F/--fixup.\");\n \tif (edit_message)\n \t\tuse_message = edit_message;\n-\tif (amend && !use_message)\n+\tif (amend && !use_message && !fixup_message)\n \t\tuse_message = \"HEAD\";\n \tif (!use_message && renew_authorship)\n \t\tdie(\"--reset-author can be used only with -C, -c or --amend.\");\n-- \n1.7.3.1\n"},{"id":"152917","messageId":"1286478657-61581-7-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 6/8] add tests of commit --fixup","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:55Z","receivedAt":"2010-10-07T19:10:55Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"t7500: test expected behavior of commit --fixup\nt3415: test interaction of commit --fixup with rebase --autosquash\nt3900: test commit --fixup with i18n encodings\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\n t/t3415-rebase-autosquash.sh |   25 +++++++++++++++++++++++--\n t/t3900-i18n-commit.sh       |   26 ++++++++++++++++++++++++++\n t/t7500-commit.sh            |   33 +++++++++++++++++++++++++++++++++\n 3 files changed, 82 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh\nindex fd2184c..b77a413 100755\n--- a/t/t3415-rebase-autosquash.sh\n+++ b/t/t3415-rebase-autosquash.sh\n@@ -14,6 +14,7 @@ test_expect_success setup '\n \tgit add . &&\n \ttest_tick &&\n \tgit commit -m \"first commit\" &&\n+\tgit tag first-commit &&\n \techo 3 >file3 &&\n \tgit add . &&\n \ttest_tick &&\n@@ -21,7 +22,7 @@ test_expect_success setup '\n \tgit tag base\n '\n \n-test_auto_fixup() {\n+test_auto_fixup () {\n \tgit reset --hard base &&\n \techo 1 >file1 &&\n \tgit add -u &&\n@@ -50,7 +51,7 @@ test_expect_success 'auto fixup (config)' '\n \ttest_must_fail test_auto_fixup final-fixup-config-false\n '\n \n-test_auto_squash() {\n+test_auto_squash () {\n \tgit reset --hard base &&\n \techo 1 >file1 &&\n \tgit add -u &&\n@@ -94,4 +95,24 @@ test_expect_success 'misspelled auto squash' '\n \ttest 0 = $(git rev-list final-missquash...HEAD | wc -l)\n '\n \n+test_auto_commit_flags () {\n+\tgit reset --hard base &&\n+\techo 1 >file1 &&\n+\tgit add -u &&\n+\ttest_tick &&\n+\tgit commit --$1 first-commit &&\n+\tgit tag final-commit-$1 &&\n+\ttest_tick &&\n+\tgit rebase --autosquash -i HEAD^^^ &&\n+\tgit log --oneline >actual &&\n+\ttest 3 = $(wc -l <actual) &&\n+\tgit diff --exit-code final-commit-$1 &&\n+\ttest 1 = \"$(git cat-file blob HEAD^:file1)\" &&\n+\ttest $2 = $(git cat-file commit HEAD^ | grep first | wc -l)\n+}\n+\n+test_expect_success 'use commit --fixup' '\n+\ttest_auto_commit_flags fixup 1\n+'\n+\n test_done\ndiff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh\nindex 256c4c9..ff6d8dd 100755\n--- a/t/t3900-i18n-commit.sh\n+++ b/t/t3900-i18n-commit.sh\n@@ -133,4 +133,30 @@ do\n \t'\n done\n \n+test_commit_autosquash_flags () {\n+\tH=$1\n+\tflag=$2\n+\ttest_expect_success \"commit --$flag with $H encoding\" '\n+\t\tgit config i18n.commitencoding $H &&\n+\t\tgit checkout -b $H-$flag C0 &&\n+\t\techo $H >>F &&\n+\t\tgit commit -a -F \"$TEST_DIRECTORY\"/t3900/$H.txt &&\n+\t\ttest_tick &&\n+\t\techo intermediate stuff >>G &&\n+\t\tgit add G &&\n+\t\tgit commit -a -m \"intermediate commit\" &&\n+\t\ttest_tick &&\n+\t\techo $H $flag >>F &&\n+\t\tgit commit -a --$flag HEAD~1 $3 &&\n+\t\tE=$(git cat-file commit '$H-$flag' | sed -ne \"s/^encoding //p\") &&\n+\t\ttest \"z$E\" = \"z'$H'\" &&\n+\t\tgit config --unset-all i18n.commitencoding &&\n+\t\tgit rebase --autosquash -i HEAD^^^ &&\n+\t\tgit log --oneline >actual &&\n+\t\ttest 3 = $(wc -l <actual)\n+\t'\n+}\n+\n+test_commit_autosquash_flags eucJP fixup\n+\n test_done\ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex aa9c577..a41b819 100755\n--- a/t/t7500-commit.sh\n+++ b/t/t7500-commit.sh\n@@ -215,4 +215,37 @@ test_expect_success 'Commit a message with --allow-empty-message' '\n \tcommit_msg_is \"hello there\"\n '\n \n+commit_for_rebase_autosquash_setup () {\n+\techo \"first content line\" >>foo &&\n+\tgit add foo &&\n+\tcat >log <<EOF &&\n+target message subject line\n+\n+target message body line 1\n+target message body line 2\n+EOF\n+\tgit commit -F log &&\n+\techo \"second content line\" >>foo &&\n+\tgit add foo &&\n+\tgit commit -m \"intermediate commit\" &&\n+\techo \"third content line\" >>foo &&\n+\tgit add foo\n+}\n+\n+test_expect_success 'commit --fixup provides correct one-line commit message' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tgit commit --fixup HEAD~1 &&\n+\tcommit_msg_is \"fixup! target message subject line\"\n+'\n+\n+test_expect_success 'invalid message options when using --fixup' '\n+\techo changes >>foo &&\n+\techo \"message\" >log &&\n+\tgit add foo &&\n+\ttest_must_fail git commit --fixup HEAD~1 -C HEAD~2 &&\n+\ttest_must_fail git commit --fixup HEAD~1 -c HEAD~2 &&\n+\ttest_must_fail git commit --fixup HEAD~1 -m \"cmdline message\" &&\n+\ttest_must_fail git commit --fixup HEAD~1 -F log\n+'\n+\n test_done\n-- \n1.7.3.1\n"},{"id":"152916","messageId":"1286478657-61581-8-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 7/8] commit: --squash option for use with rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:56Z","receivedAt":"2010-10-07T19:10:56Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"This option makes it convenient to construct commit messages for use\nwith 'rebase --autosquash'.  The resulting commit message will be\n\"squash! ...\" where \"...\" is the subject line of the specified commit\nmessage.  This option can be used with other commit message options\nsuch as -m, -c, -C and -F.\n\nIf an editor is invoked (as with -c or -eF or no message options) the\ncommit message is seeded with the correctly formatted subject line.\n\nExample usage:\n  $ git commit --squash HEAD~2\n  $ git commit --squash HEAD~2 -m \"clever comment\"\n  $ git commit --squash HEAD~2 -F msgfile\n  $ git commit --squash HEAD~2 -C deadbeef\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\n Documentation/git-commit.txt |    9 ++++++++-\n builtin/commit.c             |   32 ++++++++++++++++++++++++++++++--\n 2 files changed, 38 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex f4a2b8c..6e4c220 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend] [--dry-run]\n-\t   [(-c | -C | --fixup) <commit>] [-F <file> | -m <msg>]\n+\t   [(-c | -C | --fixup | --squash) <commit>] [-F <file> | -m <msg>]\n \t   [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify]\n \t   [-e] [--author=<author>] [--date=<date>] [--cleanup=<mode>]\n \t   [--status | --no-status] [--] [[-i | -o ]<file>...]\n@@ -76,6 +76,13 @@ OPTIONS\n \tcommit with a prefix of \"fixup! \".  See linkgit:git-rebase[1]\n \tfor details.\n \n+--squash=<commit>::\n+\tConstruct a commit message for use with `rebase --autosquash`.\n+\tThe commit message subject line is taken from the specified\n+\tcommit with a prefix of \"squash! \".  Can be used with additional\n+\tcommit message options (`-m`/`-c`/`-C`/`-F`). See\n+\tlinkgit:git-rebase[1] for details.\n+\n --reset-author::\n \tWhen used with -C/-c/--amend options, declare that the\n \tauthorship of the resulting commit now belongs of the committer.\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 851bb59..6dfad73 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -69,7 +69,7 @@ static enum {\n static const char *logfile, *force_author;\n static const char *template_file;\n static char *edit_message, *use_message;\n-static char *fixup_message;\n+static char *fixup_message, *squash_message;\n static char *author_name, *author_email, *author_date;\n static int all, edit_flag, also, interactive, only, amend, signoff;\n static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;\n@@ -126,6 +126,7 @@ static struct option builtin_commit_options[] = {\n \tOPT_STRING('c', \"reedit-message\", &edit_message, \"COMMIT\", \"reuse and edit message from specified commit\"),\n \tOPT_STRING('C', \"reuse-message\", &use_message, \"COMMIT\", \"reuse message from specified commit\"),\n \tOPT_STRING(0, \"fixup\", &fixup_message, \"COMMIT\", \"use autosquash formatted message to fixup specified commit\"),\n+\tOPT_STRING(0, \"squash\", &squash_message, \"COMMIT\", \"use autosquash formatted message to squash specified commit\"),\n \tOPT_BOOLEAN(0, \"reset-author\", &renew_authorship, \"the commit is authored by me now (used with -C-c/--amend)\"),\n \tOPT_BOOLEAN('s', \"signoff\", &signoff, \"add Signed-off-by:\"),\n \tOPT_FILENAME('t', \"template\", &template_file, \"use specified template file\"),\n@@ -567,6 +568,22 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \tif (!no_verify && run_hook(index_file, \"pre-commit\", NULL))\n \t\treturn 0;\n \n+\tif (squash_message) {\n+\t\t/*\n+\t\t * Insert the proper subject line before other commit\n+\t\t * message options add their content.\n+\t\t */\n+\t\tstruct pretty_print_context ctx = {0};\n+\t\tstruct commit *commit;\n+\t\tconst char *out_enc;\n+\t\tcommit = lookup_commit_reference_by_name(squash_message);\n+\t\tout_enc = get_commit_output_encoding();\n+\t\tif(use_message && !strcmp(use_message, squash_message))\n+\t\t\tstrbuf_addstr(&sb,\"squash! \");\n+\t\telse\n+\t\t\tformat_commit_message(commit, \"squash! %s\\n\\n\", &sb, &ctx, out_enc);\n+\t}\n+\n \tif (message.len) {\n \t\tstrbuf_addbuf(&sb, &message);\n \t\thook_arg1 = \"message\";\n@@ -617,6 +634,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \telse if (in_merge)\n \t\thook_arg1 = \"merge\";\n \n+\tif (squash_message) {\n+\t\t/*\n+\t\t * If squash_commit was used for the commit subject,\n+\t\t * then we're possibly hijacking other commit log options.\n+\t\t * Reset the hook args to tell the real story.\n+\t\t */\n+\t\thook_arg1 = \"message\";\n+\t\thook_arg2 = \"\";\n+\t}\n+\n \tfp = fopen(git_path(commit_editmsg), \"w\");\n \tif (fp == NULL)\n \t\tdie_errno(\"could not open '%s'\", git_path(commit_editmsg));\n@@ -888,7 +915,8 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tdie(\"You have nothing to amend.\");\n \tif (amend && in_merge)\n \t\tdie(\"You are in the middle of a merge -- cannot amend.\");\n-\n+\tif (fixup_message && squash_message)\n+\t\tdie(\"Options --squash and --fixup cannot be used together\");\n \tif (use_message)\n \t\tf++;\n \tif (edit_message)\n-- \n1.7.3.1\n"},{"id":"152911","messageId":"1286478657-61581-9-git-send-email-patnotz@gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv5 8/8] add tests of commit --squash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-07T19:10:57Z","receivedAt":"2010-10-07T19:10:57Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"t7500: test expected behavior of commit --squash\nt3415: test interaction of commit --squash with rebase --autosquash\nt3900: test commit --squash with i18n encodings\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\nAs noted in the cover letter, one issue which limits the testing is\nthat rebase --autosquash does not (yet) consider encodings when\ncomparing commit subjects.  So, we can't test the case of a fixup! or\nsquash! commit having a different encoding than the commit with which\nit will be combined.\n\n t/t3415-rebase-autosquash.sh |    4 +++\n t/t3900-i18n-commit.sh       |    2 +\n t/t7500-commit.sh            |   47 ++++++++++++++++++++++++++++++++++++++++++\n t/t7500/edit-content         |    4 +++\n 4 files changed, 57 insertions(+), 0 deletions(-)\n create mode 100755 t/t7500/edit-content\n\ndiff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh\nindex b77a413..0028533 100755\n--- a/t/t3415-rebase-autosquash.sh\n+++ b/t/t3415-rebase-autosquash.sh\n@@ -115,4 +115,8 @@ test_expect_success 'use commit --fixup' '\n \ttest_auto_commit_flags fixup 1\n '\n \n+test_expect_success 'use commit --squash' '\n+\ttest_auto_commit_flags squash 2\n+'\n+\n test_done\ndiff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh\nindex ff6d8dd..dfabb3a 100755\n--- a/t/t3900-i18n-commit.sh\n+++ b/t/t3900-i18n-commit.sh\n@@ -159,4 +159,6 @@ test_commit_autosquash_flags () {\n \n test_commit_autosquash_flags eucJP fixup\n \n+test_commit_autosquash_flags ISO-2022-JP squash '-m \"squash message\"'\n+\n test_done\ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex a41b819..162527c 100755\n--- a/t/t7500-commit.sh\n+++ b/t/t7500-commit.sh\n@@ -238,10 +238,57 @@ test_expect_success 'commit --fixup provides correct one-line commit message' '\n \tcommit_msg_is \"fixup! target message subject line\"\n '\n \n+test_expect_success 'commit --squash works with -F' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\techo \"log message from file\" >msgfile &&\n+\tgit commit --squash HEAD~1 -F msgfile  &&\n+\tcommit_msg_is \"squash! target message subject linelog message from file\"\n+'\n+\n+test_expect_success 'commit --squash works with -m' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tgit commit --squash HEAD~1 -m \"foo bar\\nbaz\" &&\n+\tcommit_msg_is \"squash! target message subject linefoo bar\\nbaz\"\n+'\n+\n+test_expect_success 'commit --squash works with -C' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tgit commit --squash HEAD~1 -C HEAD &&\n+\tcommit_msg_is \"squash! target message subject lineintermediate commit\"\n+'\n+\n+test_expect_success 'commit --squash works with -c' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/edit-content &&\n+\tgit commit --squash HEAD~1 -c HEAD &&\n+\tcommit_msg_is \"squash! target message subject lineedited commit\"\n+'\n+\n+test_expect_success 'commit --squash works with -C for same commit' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tgit commit --squash HEAD -C HEAD &&\n+\tcommit_msg_is \"squash! intermediate commit\"\n+'\n+\n+test_expect_success 'commit --squash works with -c for same commit' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/edit-content &&\n+\tgit commit --squash HEAD -c HEAD &&\n+\tcommit_msg_is \"squash! edited commit\"\n+'\n+\n+test_expect_success 'commit --squash works with editor' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content &&\n+\tgit commit --squash HEAD~1 &&\n+\tcommit_msg_is \"squash! target message subject linecommit message\"\n+'\n+\n test_expect_success 'invalid message options when using --fixup' '\n \techo changes >>foo &&\n \techo \"message\" >log &&\n \tgit add foo &&\n+\ttest_must_fail git commit --fixup HEAD~1 --squash HEAD~2 &&\n \ttest_must_fail git commit --fixup HEAD~1 -C HEAD~2 &&\n \ttest_must_fail git commit --fixup HEAD~1 -c HEAD~2 &&\n \ttest_must_fail git commit --fixup HEAD~1 -m \"cmdline message\" &&\ndiff --git a/t/t7500/edit-content b/t/t7500/edit-content\nnew file mode 100755\nindex 0000000..08db9fd\n--- /dev/null\n+++ b/t/t7500/edit-content\n@@ -0,0 +1,4 @@\n+#!/bin/sh\n+sed -e \"s/intermediate/edited/g\" <\"$1\" >\"$1-\"\n+mv \"$1-\" \"$1\"\n+exit 0\n-- \n1.7.3.1\n"},{"id":"152931","messageId":"AANLkTinj5eZ7p8qW7U1iqNcjN4EG6HcftD2+etGvSKPA@mail.gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-2-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv5 1/8] commit.c: prefer get_header() to manual searching","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2010-10-07T21:11:47Z","receivedAt":"2010-10-07T21:11:47Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Thu, Oct 7, 2010 at 21:10, Pat Notz <patnotz@gmail.com> wrote:\n> Signed-off-by: Pat Notz <patnotz@gmail.com>\n\nCover letter?\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"152932","messageId":"AANLkTi=HLp_=MgC=oEqTB-4mNHGVJ7Ai=3Ba-_nE5BV_@mail.gmail.com","threadId":"25383","inReplyTo":"AANLkTinj5eZ7p8qW7U1iqNcjN4EG6HcftD2+etGvSKPA@mail.gmail.com","subject":"Re: [PATCHv5 1/8] commit.c: prefer get_header() to manual searching","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2010-10-07T21:12:16Z","receivedAt":"2010-10-07T21:12:16Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Thu, Oct 7, 2010 at 23:11, Sverre Rabbelier <srabbelier@gmail.com> wrote:\n> Cover letter?\n\nAh, there it is, sorry for the noise.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"153259","messageId":"AANLkTikZJWpm054Aw51Yt2CruEtx1XfX38vsVD8wVcOX@mail.gmail.com","threadId":"25383","inReplyTo":"1286478657-61581-1-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv5 0/8] Add commit message options for rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-11T21:06:38Z","receivedAt":"2010-10-11T21:06:38Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"Hiya -\n\nI didn't receive any feedback from this patch series so I thought I'd\njust ping the list to see if this is of interest at all (I fully\naccept that it might not be). Or perhaps no news is good news. Anyway,\nsorry for the spam.\n\n~ pat\n\nOn Thu, Oct 7, 2010 at 1:10 PM, Pat Notz <patnotz@gmail.com> wrote:\n> This patch series adds new command line options to git-commit to make\n> it easy to specify messages for commits correctly formatted for use\n> wit 'rebase -i --autosquash'.\n>\n> The first three patches introduce minor refactorings that set the stage\n> for subsequent patches.\n>\n> The fourth patch teaches format_commit_message to reencode the content\n> if the caller's commit object uses an encoding different from the\n> commit encoding.\n>\n> The remaining patches add the --fixup and --squash commands to\n> git-commit including tests of commit, interactions with rebase and\n> i18n encodings.\n>\n> One issue which limits the testing (but not the implementation, I\n> think) is that when 'rebase --autosquash' is comparing commit subject\n> lines it does not first make sure that the commits use a common\n> encoding.  That's follow-on work.\n>\n> Pat Notz (8):\n>  commit.c: prefer get_header() to manual searching\n>  commit.c: new function for looking up a comit by name\n>  pretty.c: helper methods for getting output encodings\n>  pretty.c: teach format_commit_message() to reencode the output\n>  commit: --fixup option for use with rebase --autosquash\n>  add tests of commit --fixup\n>  commit: --squash option for use with rebase --autosquash\n>  add tests of commit --squash\n>\n>  Documentation/git-commit.txt |   21 +++++++++--\n>  archive.c                    |    2 +-\n>  builtin/commit.c             |   76 +++++++++++++++++++++++++++------------\n>  builtin/fmt-merge-msg.c      |    2 +-\n>  cache.h                      |    3 ++\n>  commit.c                     |   13 +++++++\n>  commit.h                     |    5 ++-\n>  environment.c                |   11 ++++++\n>  log-tree.c                   |    2 +-\n>  notes-cache.c                |    2 +-\n>  pretty.c                     |   47 +++++++++++++++++++-----\n>  submodule.c                  |    4 +-\n>  t/t3415-rebase-autosquash.sh |   29 ++++++++++++++-\n>  t/t3900-i18n-commit.sh       |   28 +++++++++++++++\n>  t/t7500-commit.sh            |   80 ++++++++++++++++++++++++++++++++++++++++++\n>  t/t7500/edit-content         |    4 ++\n>  16 files changed, 283 insertions(+), 46 deletions(-)\n>  create mode 100755 t/t7500/edit-content\n>\n> --\n> 1.7.3.1\n>\n>\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n"},{"id":"153294","messageId":"AANLkTim9JuYbwpohP3tMTseLUgqe-CSM11T=N5-9-bV_@mail.gmail.com","threadId":"25383","inReplyTo":"AANLkTikZJWpm054Aw51Yt2CruEtx1XfX38vsVD8wVcOX@mail.gmail.com","subject":"Re: [PATCHv5 0/8] Add commit message options for rebase --autosquash","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2010-10-12T09:36:28Z","receivedAt":"2010-10-12T09:36:28Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Mon, Oct 11, 2010 at 23:06, Pat Notz <patnotz@gmail.com> wrote:\n> I didn't receive any feedback from this patch series so I thought I'd\n> just ping the list to see if this is of interest at all (I fully\n> accept that it might not be). Or perhaps no news is good news. Anyway,\n> sorry for the spam.\n\nI'm definitely interested as a user, but I don't think I'm qualified\nto review the actual code.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"153454","messageId":"7vocaxiwjq.fsf@alter.siamese.dyndns.org","threadId":"25383","inReplyTo":"1286478657-61581-2-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv5 1/8] commit.c: prefer get_header() to manual searching","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-13T21:59:21Z","receivedAt":"2010-10-13T21:59:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Pat Notz\" <patnotz@gmail.com> writes:\n\n> diff --git a/commit.h b/commit.h\n> index 9113bbe..c246c94 100644\n> --- a/commit.h\n> +++ b/commit.h\n> @@ -87,6 +87,7 @@ struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */\n>  extern char *reencode_commit_message(const struct commit *commit,\n>  \t\t\t\t     const char **encoding_p);\n>  extern void get_commit_format(const char *arg, struct rev_info *);\n> +extern char *get_header(const struct commit *commit, const char *key);\n\nThe name of the function was perfectly Ok within the context of pretty.c,\nas the file was about commit log message and nothing else, but it is a bit\nmindless to expose it to outside world still with such a generic name.\n\nBut the bigger question is why the patch doesn't get rid of the bulk of\nthe body of the block and replace it with a call to logmsg_reencode().\n\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 66fdd22..021fb1c 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -899,7 +899,6 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tunsigned char sha1[20];\n \t\tstatic char utf8[] = \"UTF-8\";\n \t\tconst char *out_enc;\n-\t\tchar *enc, *end;\n \t\tstruct commit *commit;\n \n \t\tif (get_sha1(use_message, sha1))\n@@ -908,18 +907,8 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tif (!commit || parse_commit(commit))\n \t\t\tdie(\"could not parse commit %s\", use_message);\n \n-\t\tenc = strstr(commit->buffer, \"\\nencoding\");\n-\t\tif (enc) {\n-\t\t\tend = strchr(enc + 10, '\\n');\n-\t\t\tenc = xstrndup(enc + 10, end - (enc + 10));\n-\t\t} else {\n-\t\t\tenc = utf8;\n-\t\t}\n \t\tout_enc = git_commit_encoding ? git_commit_encoding : utf8;\n-\n-\t\tif (strcmp(out_enc, enc))\n-\t\t\tuse_message_buffer =\n-\t\t\t\treencode_string(commit->buffer, out_enc, enc);\n+\t\tuse_message_buffer = logmsg_reencode(commit, out_enc);\n \n \t\t/*\n \t\t * If we failed to reencode the buffer, just copy it\n@@ -929,8 +918,6 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\t */\n \t\tif (use_message_buffer == NULL)\n \t\t\tuse_message_buffer = xstrdup(commit->buffer);\n-\t\tif (enc != utf8)\n-\t\t\tfree(enc);\n \t}\n \n \tif (!!also + !!only + !!all + !!interactive > 1)\n"},{"id":"153455","messageId":"7viq15iwjl.fsf@alter.siamese.dyndns.org","threadId":"25383","inReplyTo":"1286478657-61581-3-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv5 2/8] commit.c: new function for looking up a comit by name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-13T21:59:26Z","receivedAt":"2010-10-13T21:59:26Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"s/comit/commit/;\n\n\"Pat Notz\" <patnotz@gmail.com> writes:\n\n> diff --git a/commit.c b/commit.c\n> index 0094ec1..f51098a 100644\n> --- a/commit.c\n> +++ b/commit.c\n> @@ -49,6 +49,19 @@ struct commit *lookup_commit(const unsigned char *sha1)\n>  \treturn check_commit(obj, sha1, 0);\n>  }\n>  \n> +struct commit *lookup_commit_reference_by_name(const char *name)\n> +{\n> +\tunsigned char sha1[20];\n> +\tstruct commit *commit;\n> +\n> +\tif (get_sha1(name, sha1))\n> +\t\tdie(\"could not lookup commit %s\", name);\n> +\tcommit = lookup_commit_reference(sha1);\n> +\tif (!commit || parse_commit(commit))\n> +\t\tdie(\"could not parse commit %s\", name);\n> +\treturn commit;\n> +}\n\nAlthough this wouldn't _hurt_, not very excited without seeing codepaths\nthat can use this helper to reduce lines (there should be a lot of places,\nI would think).  And when that happens, the helper that dies would not be\nvery useful, as some potential callers that can benefit may want to decide\nwhat messages to issue themselves.\n"},{"id":"153456","messageId":"7vd3rdiwjh.fsf@alter.siamese.dyndns.org","threadId":"25383","inReplyTo":"1286478657-61581-5-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv5 4/8] pretty.c: teach format_commit_message() to reencode the output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-13T21:59:30Z","receivedAt":"2010-10-13T21:59:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Pat Notz\" <patnotz@gmail.com> writes:\n\n> diff --git a/pretty.c b/pretty.c\n> index a607fd6..e5ce7fb 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -1009,16 +1009,47 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w)\n>  \n>  void format_commit_message(const struct commit *commit,\n>  \t\t\t   const char *format, struct strbuf *sb,\n> -\t\t\t   const struct pretty_print_context *pretty_ctx)\n> +\t\t\t   const struct pretty_print_context *pretty_ctx,\n> +\t\t\t   const char *output_encoding)\n>  {\n>  \tstruct format_commit_context context;\n> +\tstatic char utf8[] = \"UTF-8\";\n> +\tchar *enc;\n> +\tchar *buffer;\n> +\tchar *enc_buffer;\n> +\tstruct strbuf scratch_sb = STRBUF_INIT;\n> +\tstruct strbuf *sb_ptr;\n> +\n> +\tenc = get_header(commit, \"encoding\");\n> +\tenc = enc ? enc : utf8;\n> +\tif(output_encoding && strcmp(enc,output_encoding)) {\n> +\t\tsb_ptr = &scratch_sb;\n> +\t} else {\n> +\t\tsb_ptr = sb;\n> +\t}\n\nStyle...\n\n>  \tmemset(&context, 0, sizeof(context));\n>  \tcontext.commit = commit;\n>  \tcontext.pretty_ctx = pretty_ctx;\n>  \tcontext.wrap_start = sb->len;\n> -\tstrbuf_expand(sb, format, format_commit_item, &context);\n> -\trewrap_message_tail(sb, &context, 0, 0, 0);\n> +\tstrbuf_expand(sb_ptr, format, format_commit_item, &context);\n> +\trewrap_message_tail(sb_ptr, &context, 0, 0, 0);\n> +\n> +\tif(sb_ptr != sb) {\n> +\t\t/* if re-encoding fails, take the content byte-for-byte */\n> +\t\tbuffer = strbuf_detach(sb_ptr, 0);\n> +\t\tenc_buffer = reencode_string(buffer, output_encoding, enc);\n> +\t\tenc_buffer = enc_buffer ? enc_buffer : buffer;\n> +\n> +\t\tstrbuf_addstr(sb,enc_buffer);\n> +\n> +\t\tif(enc_buffer != buffer)\n> +\t\t\tfree(enc_buffer);\n> +\t\tfree(buffer);\n> +\t}\n> +\n> +\tif(enc != utf8)\n> +\t\tfree(enc);\n>  }\n\nYou are expanding and wrapping commit->buf before re-encoding, but I am\nnot sure it is the right thing to do.  Wouldn't it become much simpler and\nmore consistent if you re-encode first and then give the result to later\nexpansion and wrapping process?  format_commit_one() would need to take\n\"msg\" not from c->commit->buffer but from a new field to hold reencoded\nresult you will add in your patch to the structure, if you do so, of\ncourse.\n\nBesides, I am a bit lost as to what this patch has to do with the stated\ngoal of the series, \"Add commit message options for rebase --autosquash\".\n"},{"id":"153464","messageId":"AANLkTi=+eBn86WBmcnASyhfDot1_5Cqkzvcn-Y_-cvrX@mail.gmail.com","threadId":"25383","inReplyTo":"7vd3rdiwjh.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv5 4/8] pretty.c: teach format_commit_message() to reencode the output","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-10-13T22:44:14Z","receivedAt":"2010-10-13T22:44:14Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"On Wed, Oct 13, 2010 at 3:59 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> \"Pat Notz\" <patnotz@gmail.com> writes:\n>\n>> diff --git a/pretty.c b/pretty.c\n>> index a607fd6..e5ce7fb 100644\n>> --- a/pretty.c\n>> +++ b/pretty.c\n>> @@ -1009,16 +1009,47 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w)\n>>\n>>  void format_commit_message(const struct commit *commit,\n>>                          const char *format, struct strbuf *sb,\n>> -                        const struct pretty_print_context *pretty_ctx)\n>> +                        const struct pretty_print_context *pretty_ctx,\n>> +                        const char *output_encoding)\n>>  {\n>>       struct format_commit_context context;\n>> +     static char utf8[] = \"UTF-8\";\n>> +     char *enc;\n>> +     char *buffer;\n>> +     char *enc_buffer;\n>> +     struct strbuf scratch_sb = STRBUF_INIT;\n>> +     struct strbuf *sb_ptr;\n>> +\n>> +     enc = get_header(commit, \"encoding\");\n>> +     enc = enc ? enc : utf8;\n>> +     if(output_encoding && strcmp(enc,output_encoding)) {\n>> +             sb_ptr = &scratch_sb;\n>> +     } else {\n>> +             sb_ptr = sb;\n>> +     }\n>\n> Style...\n>\n>>       memset(&context, 0, sizeof(context));\n>>       context.commit = commit;\n>>       context.pretty_ctx = pretty_ctx;\n>>       context.wrap_start = sb->len;\n>> -     strbuf_expand(sb, format, format_commit_item, &context);\n>> -     rewrap_message_tail(sb, &context, 0, 0, 0);\n>> +     strbuf_expand(sb_ptr, format, format_commit_item, &context);\n>> +     rewrap_message_tail(sb_ptr, &context, 0, 0, 0);\n>> +\n>> +     if(sb_ptr != sb) {\n>> +             /* if re-encoding fails, take the content byte-for-byte */\n>> +             buffer = strbuf_detach(sb_ptr, 0);\n>> +             enc_buffer = reencode_string(buffer, output_encoding, enc);\n>> +             enc_buffer = enc_buffer ? enc_buffer : buffer;\n>> +\n>> +             strbuf_addstr(sb,enc_buffer);\n>> +\n>> +             if(enc_buffer != buffer)\n>> +                     free(enc_buffer);\n>> +             free(buffer);\n>> +     }\n>> +\n>> +     if(enc != utf8)\n>> +             free(enc);\n>>  }\n>\n> You are expanding and wrapping commit->buf before re-encoding, but I am\n> not sure it is the right thing to do.  Wouldn't it become much simpler and\n> more consistent if you re-encode first and then give the result to later\n> expansion and wrapping process?  format_commit_one() would need to take\n> \"msg\" not from c->commit->buffer but from a new field to hold reencoded\n> result you will add in your patch to the structure, if you do so, of\n> course.\n>\n> Besides, I am a bit lost as to what this patch has to do with the stated\n> goal of the series, \"Add commit message options for rebase --autosquash\".\n\nThank you for the reviews; I'll digest your comments shortly. In\nresponse to your final comment, this patch was in response to your\nearlier suggestion[1] to teach format_commit_message() to deal with\npotentially different encodings.  I went for your option #3 there but\nperhaps it's overkill.  I still think that's the right thing to do\ndespite my implementation.  Otherwise, this routine is just adding\nbits to the buffer without regard for consistent encoding.  My goal\nwas to introduce this separately from any new features.\n\nAgain, thanks for all your comments -- I'll try to improve the series.\n\n[1] http://thread.gmane.org/gmane.comp.version-control.git/156883/focus=156891\n"}]}