{"thread":{"id":"25125","subject":"[PATCH 1/2] commit: add message options for rebase --autosquash","startedAt":"2010-09-17T01:39:54Z","lastAt":"2010-09-22T18:16:24Z","messageCount":21,"participants":["Pat Notz","Stephen Boyd","Bryan Drewery","Junio C Hamano","Sverre Rabbelier","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"150863","messageId":"1284687596-236-1-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":null,"subject":"[PATCH 0/2] Add commit message options for rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-17T01:39:54Z","receivedAt":"2010-09-17T01:39:54Z","isPatch":true,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"This change adds new command line options to git-commit to make it\neasy to specify messages for commits destined for\n'rebase -i --autosquash'.\n\nThe first commit adds the new options to git-commit.\n\nThe second commit adds tests of the new options.  The tests only look\nfor properly formed commit messages and expected error conditions.  They\ndo not test the rebase --autosquash functionality.\n\nPat Notz (2):\n  commit: add message options for rebase --autosquash\n  t7500: add tests of commit --fixup/--squash\n\n Documentation/git-commit.txt |   18 ++++++++++++++----\n builtin/commit.c             |   37 +++++++++++++++++++++++++++++++++----\n t/t7500-commit.sh            |   39 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 86 insertions(+), 8 deletions(-)\n\n-- \n1.7.2.3\n"},{"id":"150862","messageId":"1284687596-236-2-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-17T01:39:55Z","receivedAt":"2010-09-17T01:39:55Z","isPatch":true,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"These options make it convenient to construct commit messages for use\nwith 'rebase --autosquash'.  The resulting commit message will be\n\"fixup! ...\" or \"squash! ...\" where \"...\" is the subject line of the\nspecified commit message.\n\nExample usage:\n  $ git commit --fixup HEAD~2\n  $ git commit --squash HEAD~5\n\nSigned-off-by: Pat Notz <patnotz@gmail.com>\n---\n Documentation/git-commit.txt |   18 ++++++++++++++----\n builtin/commit.c             |   37 +++++++++++++++++++++++++++++++++----\n 2 files changed, 47 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 42fb1f5..1d1e0c8 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 | --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 \n DESCRIPTION\n -----------\n@@ -70,6 +70,16 @@ 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! \".\n+\n+--squash=<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 \"squash! \".\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 66fdd22..e525e78 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -57,6 +57,7 @@ static const char empty_amend_advice[] =\n static unsigned char head_sha1[20];\n \n static char *use_message_buffer;\n+static char *fixup_message_buffer;\n static const char commit_editmsg[] = \"COMMIT_EDITMSG\";\n static struct lock_file index_lock; /* real index */\n static struct lock_file false_lock; /* used only for partial commits */\n@@ -69,6 +70,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, *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@@ -124,6 +126,8 @@ 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_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@@ -586,6 +590,10 @@ 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 || squash_message) {\n+\t\tstrbuf_addstr(&sb, fixup_message_buffer);\n+\t\tfree(fixup_message_buffer);\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 +871,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 || squash_message)\n \t\tuse_editor = 0;\n \tif (edit_flag)\n \t\tuse_editor = 1;\n@@ -883,15 +891,19 @@ 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 (squash_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/--squash 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/--squash.\");\n \tif (edit_message)\n \t\tuse_message = edit_message;\n-\tif (amend && !use_message)\n+\tif (amend && (!use_message && !fixup_message && !squash_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@@ -932,6 +944,23 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tif (enc != utf8)\n \t\t\tfree(enc);\n \t}\n+\tif (fixup_message || squash_message) {\n+\t\tunsigned char sha1[20];\n+\t\tstruct commit *commit;\n+\t\tconst char * target_message = fixup_message ? fixup_message : squash_message;\n+\t\tconst char * msg_fmt = fixup_message ? \"fixup! %s\" : \"squash! %s\";\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\tstruct pretty_print_context ctx = {0};\n+\n+\t\tif (get_sha1(target_message, sha1))\n+\t\t\tdie(\"could not lookup commit %s\", target_message);\n+\t\tcommit = lookup_commit_reference(sha1);\n+\t\tif (!commit || parse_commit(commit))\n+\t\t\tdie(\"could not parse commit %s\", target_message);\n+\n+\t\tformat_commit_message(commit, msg_fmt, &buf, &ctx);\n+\t\tfixup_message_buffer = strbuf_detach(&buf, NULL);\n+\t}\n \n \tif (!!also + !!only + !!all + !!interactive > 1)\n \t\tdie(\"Only one of --include/--only/--all/--interactive can be used.\");\n-- \n1.7.2.3\n"},{"id":"150864","messageId":"1284687596-236-3-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCH 2/2] t7500: add tests of commit --fixup/--squash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-17T01:39:56Z","receivedAt":"2010-09-17T01:39:56Z","isPatch":true,"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 t/t7500-commit.sh |   39 +++++++++++++++++++++++++++++++++++++++\n 1 files changed, 39 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex aa9c577..cd21f67 100755\n--- a/t/t7500-commit.sh\n+++ b/t/t7500-commit.sh\n@@ -215,4 +215,43 @@ 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 for testing commit messages for rebase --autosquash\" >>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 for testing commit messages for rebase --autosquash\" >>foo &&\n+\tgit add foo &&\n+\tgit commit -m \"intermediate commit\" &&\n+\techo \"third content for testing commit messages for rebase --autosquash\" >>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+test_expect_success 'commit --squash provides correct one-line commit message' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tgit commit --squash HEAD~1 &&\n+\tcommit_msg_is \"squash! target message subject line\"\n+'\n+\n+test_expect_success 'multiple commit message options must fail' '\n+\techo changes >>foo &&\n+\techo \"message\" >log &&\n+\tgit add foo &&\n+\ttest_must_fail git commit --fixup HEAD~1 --squash HEAD~1 &&\n+\ttest_must_fail git commit --fixup HEAD~1 -m \"cmdline message\" &&\n+\ttest_must_fail git commit --fixup HEAD~1 -F log &&\n+\ttest_must_fail git commit --squash HEAD~1 -C HEAD~2 &&\n+\ttest_must_fail git commit --squash HEAD~1 -c HEAD~2\n+'\n+\n test_done\n-- \n1.7.2.3\n"},{"id":"150870","messageId":"4C93288B.7000908@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-2-git-send-email-patnotz@gmail.com","subject":"Re: [PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2010-09-17T08:36:27Z","receivedAt":"2010-09-17T08:36:27Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"On 09/16/2010 06:39 PM, Pat Notz wrote:\n> These options make it convenient to construct commit messages for use\n> with 'rebase --autosquash'.  The resulting commit message will be\n> \"fixup! ...\" or \"squash! ...\" where \"...\" is the subject line of the\n> specified commit message.\n> \n> Example usage:\n>   $ git commit --fixup HEAD~2\n>   $ git commit --squash HEAD~5\n> \n> Signed-off-by: Pat Notz <patnotz@gmail.com>\n> ---\n\nSo far I've been using an alias for these, but I suppose making them\nreal features of git could be worthwhile. What are the benefits with\nthis approach vs. an alias?\n\n> @@ -863,7 +871,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 || squash_message)\n>  \t\tuse_editor = 0;\n>  \tif (edit_flag)\n>  \t\tuse_editor = 1;\n\nThe whole point of squash is to combine two commit texts, right?\nOtherwise wouldn't you use --fixup where you throw away the text\neventually and thus don't want to open an editor?\n\n> @@ -883,15 +891,19 @@ 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 (squash_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/--squash 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/--squash.\");\n\n\nFurthering that point, perhaps I want to squash this commit into another\ncommit using the commit text from yet another commit or just with an\nextra note from the command line (-m). Perhaps this is where the benefit\nover an alias comes in?\n\n>  \tif (edit_message)\n>  \t\tuse_message = edit_message;\n> -\tif (amend && !use_message)\n> +\tif (amend && (!use_message && !fixup_message && !squash_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> @@ -932,6 +944,23 @@ static int parse_and_validate_options(int argc, const char *argv[],\n>  \t\tif (enc != utf8)\n>  \t\t\tfree(enc);\n>  \t}\n> +\tif (fixup_message || squash_message) {\n> +\t\tunsigned char sha1[20];\n> +\t\tstruct commit *commit;\n> +\t\tconst char * target_message = fixup_message ? fixup_message : squash_message;\n> +\t\tconst char * msg_fmt = fixup_message ? \"fixup! %s\" : \"squash! %s\";\n\nStyle nit: stick the * to the variable.\n\nI read this and became confused. fixup_message? target_message? Perhaps\nit should be renamed to fixup_commit, squash_commit, target_commit?\n\n> +\t\tstruct strbuf buf = STRBUF_INIT;\n> +\t\tstruct pretty_print_context ctx = {0};\n> +\n> +\t\tif (get_sha1(target_message, sha1))\n> +\t\t\tdie(\"could not lookup commit %s\", target_message);\n> +\t\tcommit = lookup_commit_reference(sha1);\n> +\t\tif (!commit || parse_commit(commit))\n> +\t\t\tdie(\"could not parse commit %s\", target_message);\n> +\n> +\t\tformat_commit_message(commit, msg_fmt, &buf, &ctx);\n> +\t\tfixup_message_buffer = strbuf_detach(&buf, NULL);\n> +\t}\n>  \n\nIs it necessary to do this block of code here? Couldn't you lookup and\nformat the commit in prepare_to_commit()? Then we wouldn't have to\nallocate another strbuf and the \"message\" code would be more centralized.\n"},{"id":"150882","messageId":"AANLkTikZTSiG6anuRR0h499JeTzRcdeE-jaYMu7Gqr8W@mail.gmail.com","threadId":"25125","inReplyTo":"4C93288B.7000908@gmail.com","subject":"Re: [PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-17T15:34:44Z","receivedAt":"2010-09-17T15:34:44Z","isPatch":true,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"On Fri, Sep 17, 2010 at 2:36 AM, Stephen Boyd <bebarino@gmail.com> wrote:\n> On 09/16/2010 06:39 PM, Pat Notz wrote:\n>> These options make it convenient to construct commit messages for use\n>> with 'rebase --autosquash'.  The resulting commit message will be\n>> \"fixup! ...\" or \"squash! ...\" where \"...\" is the subject line of the\n>> specified commit message.\n>>\n>> Example usage:\n>>   $ git commit --fixup HEAD~2\n>>   $ git commit --squash HEAD~5\n>>\n>> Signed-off-by: Pat Notz <patnotz@gmail.com>\n>> ---\n>\n> So far I've been using an alias for these, but I suppose making them\n> real features of git could be worthwhile. What are the benefits with\n> this approach vs. an alias?\n\nMainly it's convenience.  The rebase --autosquash feature seems too\nhard to use without this or an alias and making everyone code their\nown alias seems a lot to ask.\n\nStill, I admit that I was concerned with adding yet another option to\ngit-commit.  If enough people object, I can live with that.\n\n>> @@ -863,7 +871,7 @@ static int parse_and_validate_options(int argc, const char *argv[],\n>>       if (force_author && renew_authorship)\n>>               die(\"Using both --reset-author and --author does not make sense\");\n>>\n>> -     if (logfile || message.len || use_message)\n>> +     if (logfile || message.len || use_message || fixup_message || squash_message)\n>>               use_editor = 0;\n>>       if (edit_flag)\n>>               use_editor = 1;\n>\n> The whole point of squash is to combine two commit texts, right?\n> Otherwise wouldn't you use --fixup where you throw away the text\n> eventually and thus don't want to open an editor?\n\nGood point.  Admittedly, I was focusing on the 'fixup' case but squash\nneeds to open the editor with the first line pre-filled.\n\n>\n>> @@ -883,15 +891,19 @@ static int parse_and_validate_options(int argc, const char *argv[],\n>>               f++;\n>>       if (edit_message)\n>>               f++;\n>> +     if (fixup_message)\n>> +             f++;\n>> +     if (squash_message)\n>> +             f++;\n>>       if (logfile)\n>>               f++;\n>>       if (f > 1)\n>> -             die(\"Only one of -c/-C/-F can be used.\");\n>> +             die(\"Only one of -c/-C/-F/--fixup/--squash can be used.\");\n>>       if (message.len && f > 0)\n>> -             die(\"Option -m cannot be combined with -c/-C/-F.\");\n>> +             die(\"Option -m cannot be combined with -c/-C/-F/--fixup/--squash.\");\n>\n>\n> Furthering that point, perhaps I want to squash this commit into another\n> commit using the commit text from yet another commit or just with an\n> extra note from the command line (-m). Perhaps this is where the benefit\n> over an alias comes in?\n\nThat's a good use-case.  I'll re-work the --squash option.\n\n>\n>>       if (edit_message)\n>>               use_message = edit_message;\n>> -     if (amend && !use_message)\n>> +     if (amend && (!use_message && !fixup_message && !squash_message))\n>>               use_message = \"HEAD\";\n>>       if (!use_message && renew_authorship)\n>>               die(\"--reset-author can be used only with -C, -c or --amend.\");\n>> @@ -932,6 +944,23 @@ static int parse_and_validate_options(int argc, const char *argv[],\n>>               if (enc != utf8)\n>>                       free(enc);\n>>       }\n>> +     if (fixup_message || squash_message) {\n>> +             unsigned char sha1[20];\n>> +             struct commit *commit;\n>> +             const char * target_message = fixup_message ? fixup_message : squash_message;\n>> +             const char * msg_fmt = fixup_message ? \"fixup! %s\" : \"squash! %s\";\n>\n> Style nit: stick the * to the variable.\n>\n\nOops, thanks.\n\n> I read this and became confused. fixup_message? target_message? Perhaps\n> it should be renamed to fixup_commit, squash_commit, target_commit?\n>\n\nI was mostly trying to reduce duplicate code for the two cases... but,\nI bet when I re-work --squash this will go away.\n\n>> +             struct strbuf buf = STRBUF_INIT;\n>> +             struct pretty_print_context ctx = {0};\n>> +\n>> +             if (get_sha1(target_message, sha1))\n>> +                     die(\"could not lookup commit %s\", target_message);\n>> +             commit = lookup_commit_reference(sha1);\n>> +             if (!commit || parse_commit(commit))\n>> +                     die(\"could not parse commit %s\", target_message);\n>> +\n>> +             format_commit_message(commit, msg_fmt, &buf, &ctx);\n>> +             fixup_message_buffer = strbuf_detach(&buf, NULL);\n>> +     }\n>>\n>\n> Is it necessary to do this block of code here? Couldn't you lookup and\n> format the commit in prepare_to_commit()? Then we wouldn't have to\n> allocate another strbuf and the \"message\" code would be more centralized.\n>\n\nProbably not, I was mostly trying to follow the example from the\nuse_message (-C/-c) feature.  It *would* be nice to avoid the extra\nmemory (de)alloc.\n\nThanks for the great feedback!\n"},{"id":"150887","messageId":"4C9393CB.4010107@shatow.net","threadId":"25125","inReplyTo":"4C93288B.7000908@gmail.com","subject":"Re: [PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Bryan Drewery","fromEmail":"bryan@shatow.net","sentAt":"2010-09-17T16:14:03Z","receivedAt":"2010-09-17T16:14:03Z","isPatch":true,"sender":{"key":"bryan@shatow.net","avatar":"https://gravatar.com/avatar/97f2135497453f52d450b5cc8a09910e12efea7dc520a25107afcc666ab9a182?d=mp&s=160"},"body":"Stephen Boyd wrote:\n> On 09/16/2010 06:39 PM, Pat Notz wrote:\n>   \n>> These options make it convenient to construct commit messages for use\n>> with 'rebase --autosquash'.  The resulting commit message will be\n>> \"fixup! ...\" or \"squash! ...\" where \"...\" is the subject line of the\n>> specified commit message.\n>>\n>> Example usage:\n>>   $ git commit --fixup HEAD~2\n>>   $ git commit --squash HEAD~5\n>>\n>> Signed-off-by: Pat Notz <patnotz@gmail.com>\n>> ---\n>>     \n>\n> So far I've been using an alias for these, but I suppose making them\n> real features of git could be worthwhile. What are the benefits with\n> this approach vs. an alias?\n>\n>   \n\nI keep wanting to do these at commit time.\n\nWhat are the alternative aliases?\n\nBryan\n"},{"id":"150894","messageId":"AANLkTimBnzWQYy8z1duQw=4UL4YCaeyiMugXG1O-Q8yq@mail.gmail.com","threadId":"25125","inReplyTo":"4C9393CB.4010107@shatow.net","subject":"Re: [PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2010-09-17T17:07:52Z","receivedAt":"2010-09-17T17:07:52Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"On Fri, Sep 17, 2010 at 9:14 AM, Bryan Drewery <bryan@shatow.net> wrote:\n> Stephen Boyd wrote:\n>>\n>> On 09/16/2010 06:39 PM, Pat Notz wrote:\n>>\n>>>\n>>> These options make it convenient to construct commit messages for use\n>>> with 'rebase --autosquash'.  The resulting commit message will be\n>>> \"fixup! ...\" or \"squash! ...\" where \"...\" is the subject line of the\n>>> specified commit message.\n>>>\n>>> Example usage:\n>>>  $ git commit --fixup HEAD~2\n>>>  $ git commit --squash HEAD~5\n>>>\n>>> Signed-off-by: Pat Notz <patnotz@gmail.com>\n>>> ---\n>>>\n>>\n>> So far I've been using an alias for these, but I suppose making them\n>> real features of git could be worthwhile. What are the benefits with\n>> this approach vs. an alias?\n>>\n>>\n>\n> I keep wanting to do these at commit time.\n>\n> What are the alternative aliases?\n>\n\n`git fixup' is aliased to `!f() { git commit -m \"$(git show -s\n--pretty='format:fixup! %s%n%nFixup for %h%n' \"$1\")\" $2; }; f'\n`git squash' is aliased to `!f() { git commit -m \"$(git show -s\n--pretty='format:squash! %s%n%n' \"$1\")\" -e $2; }; f'\n"},{"id":"150899","messageId":"4C93A9B9.2060401@shatow.net","threadId":"25125","inReplyTo":"AANLkTimBnzWQYy8z1duQw=4UL4YCaeyiMugXG1O-Q8yq@mail.gmail.com","subject":"Re: [PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Bryan Drewery","fromEmail":"bryan@shatow.net","sentAt":"2010-09-17T17:47:37Z","receivedAt":"2010-09-17T17:47:37Z","isPatch":true,"sender":{"key":"bryan@shatow.net","avatar":"https://gravatar.com/avatar/97f2135497453f52d450b5cc8a09910e12efea7dc520a25107afcc666ab9a182?d=mp&s=160"},"body":"\n>>>> These options make it convenient to construct commit messages for use\n>>>> with 'rebase --autosquash'.  The resulting commit message will be\n>>>> \"fixup! ...\" or \"squash! ...\" where \"...\" is the subject line of the\n>>>> specified commit message.\n>>>>         \n> `git fixup' is aliased to `!f() { git commit -m \"$(git show -s\n> --pretty='format:fixup! %s%n%nFixup for %h%n' \"$1\")\" $2; }; f'\n> `git squash' is aliased to `!f() { git commit -m \"$(git show -s\n> --pretty='format:squash! %s%n%n' \"$1\")\" -e $2; }; f'\n>   \nThanks.\n\nI had missed that this was for the commit message. Thought it was doing \nthe rebase as well.\n\nBryan\n"},{"id":"150900","messageId":"7vzkvg2pur.fsf@alter.siamese.dyndns.org","threadId":"25125","inReplyTo":"4C93288B.7000908@gmail.com","subject":"Re: [PATCH 1/2] commit: add message options for rebase --autosquash","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-17T18:21:16Z","receivedAt":"2010-09-17T18:21:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> The whole point of squash is to combine two commit texts, right?\n> Otherwise wouldn't you use --fixup where you throw away the text\n> eventually and thus don't want to open an editor?\n\nYou mentioned almost everything I wanted to say.  I think --fixup makes\nsense, but I doubt --squash does, _unless_ its interactactions with other\nmessage pre-filling options, e.g. -m, -F, -c, are really well thought\nout.\n"},{"id":"151241","messageId":"1285100703-49087-1-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv2 0/4] Add commit message options for rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-21T20:24:59Z","receivedAt":"2010-09-21T20:24:59Z","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\nThis 2nd iteration address concerns raised earlier:\nhttp://thread.gmane.org/gmane.comp.version-control.git/156369 .  Most\nnotably, --squash=COMMIT now works with -m/-c/-C/-F and uses the\neditor when appropriate.\n\nPat Notz (4):\n  commit: --fixup option for use with rebase --autosquash\n  t7500: add tests of commit --fixup\n  commit: --squash option for use with rebase --autosquash\n  t7500: add tests of commit --squash\n\n Documentation/git-commit.txt |   19 +++++++--\n builtin/commit.c             |   58 ++++++++++++++++++++++++--\n t/t7500-commit.sh            |   90 ++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 158 insertions(+), 9 deletions(-)\n\n-- \n1.7.3\n"},{"id":"151244","messageId":"1285100703-49087-2-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv2 1/4] commit: --fixup option for use with rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-21T20:25:00Z","receivedAt":"2010-09-21T20:25:00Z","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 |   13 +++++++++----\n builtin/commit.c             |   23 +++++++++++++++++++----\n 2 files changed, 28 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 42fb1f5..3367f8f 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,11 @@ 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! \".\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 66fdd22..0901616 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,17 @@ 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\tunsigned char sha1[20];\n+\t\tstruct commit *commit;\n+\t\tstruct pretty_print_context ctx = {0};\n+\t\tif (get_sha1(fixup_message, sha1))\n+\t\t\tdie(\"could not lookup commit %s\", fixup_message);\n+\t\tcommit = lookup_commit_reference(sha1);\n+\t\tif (!commit || parse_commit(commit))\n+\t\t\tdie(\"could not parse commit %s\", fixup_message);\n+\t\tformat_commit_message(commit, \"fixup! %s\\n\\n\", &sb, &ctx);\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 +876,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 +896,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\n"},{"id":"151242","messageId":"1285100703-49087-3-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv2 2/4] t7500: add tests of commit --fixup","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-21T20:25:01Z","receivedAt":"2010-09-21T20:25:01Z","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 t/t7500-commit.sh |   33 +++++++++++++++++++++++++++++++++\n 1 files changed, 33 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex aa9c577..7656ed4 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 for testing commit messages for rebase --autosquash\" >>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 for testing commit messages for rebase --autosquash\" >>foo &&\n+\tgit add foo &&\n+\tgit commit -m \"intermediate commit\" &&\n+\techo \"third content for testing commit messages for rebase --autosquash\" >>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\n"},{"id":"151245","messageId":"1285100703-49087-4-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv2 3/4] commit: --squash option for use with rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-21T20:25:02Z","receivedAt":"2010-09-21T20:25:02Z","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 |    8 +++++++-\n builtin/commit.c             |   37 +++++++++++++++++++++++++++++++++++--\n 2 files changed, 42 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 3367f8f..b621dc4 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@@ -75,6 +75,12 @@ OPTIONS\n \tThe commit message will be the subject line from the specified\n \tcommit with a prefix of \"fixup! \".\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`).\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 0901616..d28b2ff 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,27 @@ 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\tunsigned char sha1[20];\n+\t\tstruct commit *commit;\n+\t\tstruct pretty_print_context ctx = {0};\n+\n+\t\tif (get_sha1(squash_message, sha1))\n+\t\t\tdie(\"could not lookup commit %s\", squash_message);\n+\t\tcommit = lookup_commit_reference(sha1);\n+\t\tif (!commit || parse_commit(commit))\n+\t\t\tdie(\"could not parse commit %s\", squash_message);\n+\n+\t\tif(use_message && strcmp(use_message, squash_message) == 0)\n+\t\t\tstrbuf_addstr(&sb,\"squash! \");\n+\t\telse\n+\t\t\tformat_commit_message(commit, \"squash! %s\\n\\n\", &sb, &ctx);\n+\t}\n+\n \tif (message.len) {\n \t\tstrbuf_addbuf(&sb, &message);\n \t\thook_arg1 = \"message\";\n@@ -620,6 +642,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@@ -891,7 +923,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\n"},{"id":"151243","messageId":"1285100703-49087-5-git-send-email-patnotz@gmail.com","threadId":"25125","inReplyTo":"1284687596-236-1-git-send-email-patnotz@gmail.com","subject":"[PATCHv2 4/4] t7500: add tests of commit --squash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-21T20:25:03Z","receivedAt":"2010-09-21T20:25:03Z","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 t/t7500-commit.sh |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 57 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex 7656ed4..a2406f4 100755\n--- a/t/t7500-commit.sh\n+++ b/t/t7500-commit.sh\n@@ -238,10 +238,67 @@ 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+cat >editor <<\\EOF\n+#!/bin/sh\n+sed -e \"s/intermediate/edited/g\" <\"$1\" >\"$1-\"\n+mv \"$1-\" \"$1\"\n+EOF\n+chmod 755 editor\n+\n+test_expect_success 'commit --squash works with -c' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tEDITOR=./editor git 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+\tEDITOR=./editor git commit --squash HEAD -c HEAD &&\n+\tcommit_msg_is \"squash! edited commit\"\n+'\n+\n+cat >editor <<\\EOF\n+#!/bin/sh\n+echo \"additional body content\" >>\"$1\"\n+EOF\n+chmod 755 editor\n+\n+test_expect_success 'commit --squash works with editor' '\n+\tcommit_for_rebase_autosquash_setup &&\n+\tEDITOR=./editor git commit --squash HEAD~1 &&\n+\tcommit_msg_is \"squash! target message subject lineadditional body content\"\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\" &&\n-- \n1.7.3\n"},{"id":"151246","messageId":"AANLkTi=ok2EBAkwgPAN9zBmfayKXBdCEneiAhoDDstZv@mail.gmail.com","threadId":"25125","inReplyTo":"1285100703-49087-2-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv2 1/4] commit: --fixup option for use with rebase --autosquash","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2010-09-21T20:35:18Z","receivedAt":"2010-09-21T20:35:18Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Tue, Sep 21, 2010 at 22:25, Pat Notz <patnotz@gmail.com> wrote:\n> This option makes it convenient to construct commit messages for use\n> with 'rebase --autosquash'.  The resulting commit message will be\n> \"fixup! ...\" where \"...\" is the subject line of the specified commit\n> message.\n>\n> Example usage:\n>  $ git commit --fixup HEAD~2\n\nThis is brilliant, I love it. I don't use 'autosquash' much atm\nbecause I don't like messing with commit messages. This would make\nusing it much more convenient, thanks!\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"151247","messageId":"AANLkTinTA23Xf2AFLW+tzeLq1AWUhBBuca63qs_foXtr@mail.gmail.com","threadId":"25125","inReplyTo":"1285100703-49087-5-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv2 4/4] t7500: add tests of commit --squash","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-09-21T20:36:21Z","receivedAt":"2010-09-21T20:36:21Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Tue, Sep 21, 2010 at 20:25, Pat Notz <patnotz@gmail.com> wrote:\n\n> +cat >editor <<\\EOF\n> +#!/bin/sh\n> +sed -e \"s/intermediate/edited/g\" <\"$1\" >\"$1-\"\n> +mv \"$1-\" \"$1\"\n> +EOF\n> +chmod 755 editor\n> +\n> +test_expect_success 'commit --squash works with -c' '\n> +       commit_for_rebase_autosquash_setup &&\n> +       EDITOR=./editor git commit --squash HEAD~1 -c HEAD &&\n> +       commit_msg_is \"squash! target message subject lineedited commit\"\n> +'\n\nWhy not put the editor in t/t7500/ and use test_set_editor() like the\nother tests?\n"},{"id":"151304","messageId":"AANLkTinajr6DvYeyiK79xESYqg0kegUN1s8LxEqGoUc+@mail.gmail.com","threadId":"25125","inReplyTo":"AANLkTinTA23Xf2AFLW+tzeLq1AWUhBBuca63qs_foXtr@mail.gmail.com","subject":"Re: [PATCHv2 4/4] t7500: add tests of commit --squash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-22T17:59:29Z","receivedAt":"2010-09-22T17:59:29Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"On Tue, Sep 21, 2010 at 2:36 PM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n>\n> On Tue, Sep 21, 2010 at 20:25, Pat Notz <patnotz@gmail.com> wrote:\n>\n> > +cat >editor <<\\EOF\n> > +#!/bin/sh\n> > +sed -e \"s/intermediate/edited/g\" <\"$1\" >\"$1-\"\n> > +mv \"$1-\" \"$1\"\n> > +EOF\n> > +chmod 755 editor\n> > +\n> > +test_expect_success 'commit --squash works with -c' '\n> > +       commit_for_rebase_autosquash_setup &&\n> > +       EDITOR=./editor git commit --squash HEAD~1 -c HEAD &&\n> > +       commit_msg_is \"squash! target message subject lineedited commit\"\n> > +'\n>\n> Why not put the editor in t/t7500/ and use test_set_editor() like the\n> other tests?\n\nThe real reason is that I'm new enough that I wasn't aware of this\npattern.  I saw what was done in t7501-commit.sh and followed along.\nI missed the use of test_set_editor() right there in t7500-commit.sh.\nDoh!\n\nI can certainly do that if it's preferred.  I must say, though, that I\nfind it odd to put test inputs in a separate file in a separate\ndirectory from where the test transforms those into expected outputs.\nTo see what the test is doing you have to load both files and trace\nthrough it.\n\nStill, I'd be happy to change do this if that's the preferred way.\n"},{"id":"151305","messageId":"AANLkTinKCuFRYf4Bu856nhtfA3gPY5FZpQ6jcik=4=GC@mail.gmail.com","threadId":"25125","inReplyTo":"1285100703-49087-2-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv2 1/4] commit: --fixup option for use with rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-22T18:01:13Z","receivedAt":"2010-09-22T18:01:13Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"On Tue, Sep 21, 2010 at 2:25 PM, Pat Notz <patnotz@gmail.com> wrote:\n> This option makes it convenient to construct commit messages for use\n> with 'rebase --autosquash'.  The resulting commit message will be\n> \"fixup! ...\" where \"...\" is the subject line of the specified commit\n> message.\n>\n> Example usage:\n>  $ git commit --fixup HEAD~2\n>\n> Signed-off-by: Pat Notz <patnotz@gmail.com>\n> ---\n>  Documentation/git-commit.txt |   13 +++++++++----\n>  builtin/commit.c             |   23 +++++++++++++++++++----\n>  2 files changed, 28 insertions(+), 8 deletions(-)\n>\n> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\n> index 42fb1f5..3367f8f 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> -          [(-c | -C) <commit>] [-F <file> | -m <msg>] [--reset-author]\n> -          [--allow-empty] [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n> -          [--date=<date>] [--cleanup=<mode>] [--status | --no-status] [--]\n> -          [[-i | -o ]<file>...]\n> +          [(-c | -C | --fixup) <commit>] [-F <file> | -m <msg>]\n> +          [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify]\n> +          [-e] [--author=<author>] [--date=<date>] [--cleanup=<mode>]\n> +          [--status | --no-status] [--] [[-i | -o ]<file>...]\n>\n>  DESCRIPTION\n>  -----------\n> @@ -70,6 +70,11 @@ OPTIONS\n>        Like '-C', but with '-c' the editor is invoked, so that\n>        the user can further edit the commit message.\n>\n> +--fixup=<commit>::\n> +       Construct a commit message for use with `rebase --autosquash`.\n> +       The commit message will be the subject line from the specified\n> +       commit with a prefix of \"fixup! \".\n> +\n\nI should add links to the git-rebase man page here.\n"},{"id":"151306","messageId":"AANLkTi=QnVX9=uPWQPbQWGtw+qu2tqhij47t7Z6_NX=O@mail.gmail.com","threadId":"25125","inReplyTo":"1285100703-49087-4-git-send-email-patnotz@gmail.com","subject":"Re: [PATCHv2 3/4] commit: --squash option for use with rebase --autosquash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-22T18:02:16Z","receivedAt":"2010-09-22T18:02:16Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"On Tue, Sep 21, 2010 at 2:25 PM, Pat Notz <patnotz@gmail.com> wrote:\n> This option makes it convenient to construct commit messages for use\n> with 'rebase --autosquash'.  The resulting commit message will be\n> \"squash! ...\" where \"...\" is the subject line of the specified commit\n> message.  This option can be used with other commit message options\n> such as -m, -c, -C and -F.\n>\n> If an editor is invoked (as with -c or -eF or no message options) the\n> commit message is seeded with the correctly formatted subject line.\n>\n> Example 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>\n> Signed-off-by: Pat Notz <patnotz@gmail.com>\n> ---\n>  Documentation/git-commit.txt |    8 +++++++-\n>  builtin/commit.c             |   37 +++++++++++++++++++++++++++++++++++--\n>  2 files changed, 42 insertions(+), 3 deletions(-)\n>\n> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\n> index 3367f8f..b621dc4 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> -          [(-c | -C | --fixup) <commit>] [-F <file> | -m <msg>]\n> +          [(-c | -C | --fixup | --squash) <commit>] [-F <file> | -m <msg>]\n>           [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify]\n>           [-e] [--author=<author>] [--date=<date>] [--cleanup=<mode>]\n>           [--status | --no-status] [--] [[-i | -o ]<file>...]\n> @@ -75,6 +75,12 @@ OPTIONS\n>        The commit message will be the subject line from the specified\n>        commit with a prefix of \"fixup! \".\n>\n> +--squash=<commit>::\n> +       Construct a commit message for use with `rebase --autosquash`.\n> +       The commit message subject line is taken from the specified\n> +       commit with a prefix of \"squash! \".  Can be used with additional\n> +       commit message options (`-m`/`-c`/`-C`/`-F`).\n> +\n\nDitto - I should add links to the git-rebase man page here.\n\n>  --reset-author::\n>        When used with -C/-c/--amend options, declare that the\n>        authorship of the resulting commit now belongs of the committer.\n> diff --git a/builtin/commit.c b/builtin/commit.c\n> index 0901616..d28b2ff 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>        OPT_STRING('c', \"reedit-message\", &edit_message, \"COMMIT\", \"reuse and edit message from specified commit\"),\n>        OPT_STRING('C', \"reuse-message\", &use_message, \"COMMIT\", \"reuse message from specified commit\"),\n>        OPT_STRING(0, \"fixup\", &fixup_message, \"COMMIT\", \"use autosquash formatted message to fixup specified commit\"),\n> +       OPT_STRING(0, \"squash\", &squash_message, \"COMMIT\", \"use autosquash formatted message to squash specified commit\"),\n>        OPT_BOOLEAN(0, \"reset-author\", &renew_authorship, \"the commit is authored by me now (used with -C-c/--amend)\"),\n>        OPT_BOOLEAN('s', \"signoff\", &signoff, \"add Signed-off-by:\"),\n>        OPT_FILENAME('t', \"template\", &template_file, \"use specified template file\"),\n> @@ -567,6 +568,27 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n>        if (!no_verify && run_hook(index_file, \"pre-commit\", NULL))\n>                return 0;\n>\n> +       if (squash_message) {\n> +               /*\n> +                * Insert the proper subject line before other commit\n> +                * message options add their content.\n> +                */\n> +               unsigned char sha1[20];\n> +               struct commit *commit;\n> +               struct pretty_print_context ctx = {0};\n> +\n> +               if (get_sha1(squash_message, sha1))\n> +                       die(\"could not lookup commit %s\", squash_message);\n> +               commit = lookup_commit_reference(sha1);\n> +               if (!commit || parse_commit(commit))\n> +                       die(\"could not parse commit %s\", squash_message);\n> +\n> +               if(use_message && strcmp(use_message, squash_message) == 0)\n> +                       strbuf_addstr(&sb,\"squash! \");\n> +               else\n> +                       format_commit_message(commit, \"squash! %s\\n\\n\", &sb, &ctx);\n> +       }\n> +\n>        if (message.len) {\n>                strbuf_addbuf(&sb, &message);\n>                hook_arg1 = \"message\";\n> @@ -620,6 +642,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n>        else if (in_merge)\n>                hook_arg1 = \"merge\";\n>\n> +       if (squash_message) {\n> +               /*\n> +                * If squash_commit was used for the commit subject,\n> +                * then we're possibly hijacking other commit log options.\n> +                * Reset the hook args to tell the real story.\n> +                */\n> +               hook_arg1 = \"message\";\n> +               hook_arg2 = \"\";\n> +       }\n> +\n>        fp = fopen(git_path(commit_editmsg), \"w\");\n>        if (fp == NULL)\n>                die_errno(\"could not open '%s'\", git_path(commit_editmsg));\n> @@ -891,7 +923,8 @@ static int parse_and_validate_options(int argc, const char *argv[],\n>                die(\"You have nothing to amend.\");\n>        if (amend && in_merge)\n>                die(\"You are in the middle of a merge -- cannot amend.\");\n> -\n> +       if (fixup_message && squash_message)\n> +               die(\"Options --squash and --fixup cannot be used together\");\n>        if (use_message)\n>                f++;\n>        if (edit_message)\n> --\n> 1.7.3\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":"151307","messageId":"AANLkTi=MjE3OBqAd8NqFCMdSb3qfNW_1QKvrL6-AK+Er@mail.gmail.com","threadId":"25125","inReplyTo":"AANLkTinajr6DvYeyiK79xESYqg0kegUN1s8LxEqGoUc+@mail.gmail.com","subject":"Re: [PATCHv2 4/4] t7500: add tests of commit --squash","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-09-22T18:12:09Z","receivedAt":"2010-09-22T18:12:09Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Wed, Sep 22, 2010 at 17:59, Pat Notz <patnotz@gmail.com> wrote:\n> On Tue, Sep 21, 2010 at 2:36 PM, Ævar Arnfjörð Bjarmason\n> <avarab@gmail.com> wrote:\n>>\n>> On Tue, Sep 21, 2010 at 20:25, Pat Notz <patnotz@gmail.com> wrote:\n>>\n>> > +cat >editor <<\\EOF\n>> > +#!/bin/sh\n>> > +sed -e \"s/intermediate/edited/g\" <\"$1\" >\"$1-\"\n>> > +mv \"$1-\" \"$1\"\n>> > +EOF\n>> > +chmod 755 editor\n>> > +\n>> > +test_expect_success 'commit --squash works with -c' '\n>> > +       commit_for_rebase_autosquash_setup &&\n>> > +       EDITOR=./editor git commit --squash HEAD~1 -c HEAD &&\n>> > +       commit_msg_is \"squash! target message subject lineedited commit\"\n>> > +'\n>>\n>> Why not put the editor in t/t7500/ and use test_set_editor() like the\n>> other tests?\n>\n> The real reason is that I'm new enough that I wasn't aware of this\n> pattern.  I saw what was done in t7501-commit.sh and followed along.\n> I missed the use of test_set_editor() right there in t7500-commit.sh.\n> Doh!\n>\n> I can certainly do that if it's preferred.  I must say, though, that I\n> find it odd to put test inputs in a separate file in a separate\n> directory from where the test transforms those into expected outputs.\n> To see what the test is doing you have to load both files and trace\n> through it.\n>\n> Still, I'd be happy to change do this if that's the preferred way.\n\nIt's a bit odd, but it's best to following existing style within a\ntest. Then maybe submit fixup patches to fix the whole thing later.\n"},{"id":"151309","messageId":"AANLkTi=5smrhYk0YA6qxoa7PZNRisVuhzciStXuje4=A@mail.gmail.com","threadId":"25125","inReplyTo":"AANLkTi=MjE3OBqAd8NqFCMdSb3qfNW_1QKvrL6-AK+Er@mail.gmail.com","subject":"Re: [PATCHv2 4/4] t7500: add tests of commit --squash","fromName":"Pat Notz","fromEmail":"patnotz@gmail.com","sentAt":"2010-09-22T18:16:24Z","receivedAt":"2010-09-22T18:16:24Z","isPatch":false,"sender":{"key":"patnotz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45364?v=4"},"body":"On Wed, Sep 22, 2010 at 12:12 PM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n> On Wed, Sep 22, 2010 at 17:59, Pat Notz <patnotz@gmail.com> wrote:\n>> On Tue, Sep 21, 2010 at 2:36 PM, Ævar Arnfjörð Bjarmason\n>> <avarab@gmail.com> wrote:\n>>>\n>>> On Tue, Sep 21, 2010 at 20:25, Pat Notz <patnotz@gmail.com> wrote:\n>>>\n>>> > +cat >editor <<\\EOF\n>>> > +#!/bin/sh\n>>> > +sed -e \"s/intermediate/edited/g\" <\"$1\" >\"$1-\"\n>>> > +mv \"$1-\" \"$1\"\n>>> > +EOF\n>>> > +chmod 755 editor\n>>> > +\n>>> > +test_expect_success 'commit --squash works with -c' '\n>>> > +       commit_for_rebase_autosquash_setup &&\n>>> > +       EDITOR=./editor git commit --squash HEAD~1 -c HEAD &&\n>>> > +       commit_msg_is \"squash! target message subject lineedited commit\"\n>>> > +'\n>>>\n>>> Why not put the editor in t/t7500/ and use test_set_editor() like the\n>>> other tests?\n>>\n>> The real reason is that I'm new enough that I wasn't aware of this\n>> pattern.  I saw what was done in t7501-commit.sh and followed along.\n>> I missed the use of test_set_editor() right there in t7500-commit.sh.\n>> Doh!\n>>\n>> I can certainly do that if it's preferred.  I must say, though, that I\n>> find it odd to put test inputs in a separate file in a separate\n>> directory from where the test transforms those into expected outputs.\n>> To see what the test is doing you have to load both files and trace\n>> through it.\n>>\n>> Still, I'd be happy to change do this if that's the preferred way.\n>\n> It's a bit odd, but it's best to following existing style within a\n> test. Then maybe submit fixup patches to fix the whole thing later.\n>\n\nYeah, there's certainly value in doing that.  I'll follow-up with a v3\nand include the documentation changes I noticed in the other patches.\n"}]}