105
*/
106
static const char *author_message, *author_message_buffer;
107
static char *edit_message, *use_message;
108
-static char *fixup_message, *squash_message;
108
+static char *fixup_message, *fixup_commit, *squash_message;
109
+static const char *fixup_prefix;
110
static int all, also, interactive, patch_interactive, only, amend, signoff;
111
static int edit_flag = -1; /* unspecified */
112
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
358
die(_("--pathspec-file-nul requires --pathspec-from-file"));
359
}
360
360
- if (!pathspec.nr && (also || (only && !amend && !allow_empty)))
361
+ if (!pathspec.nr && (also || (only && !allow_empty &&
362
+ (!amend || (fixup_message && strcmp(fixup_prefix, "amend"))))))
363
die(_("No paths with --include/--only does not make sense."));
364
365
if (read_cache_preload(&pathspec) < 0)
683
comment_line_char = *p;
684
}
685
686
+static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
687
+ struct pretty_print_context *ctx)
688
+{
689
+ const char *buffer, *subject, *fmt;
690
+
691
+ buffer = get_commit_buffer(commit, NULL);
692
+ find_commit_subject(buffer, &subject);
693
+ /*
694
+ * If we amend the 'amend!' commit then we don't want to
695
+ * duplicate the subject line.
696
+ */
697
+ fmt = starts_with(subject, "amend!") ? "%b" : "%B";
698
+ format_commit_message(commit, fmt, sb, ctx);
699
+ unuse_commit_buffer(commit, buffer);
700
+}
701
+
702
static int prepare_to_commit(const char *index_file, const char *prefix,
703
struct commit *current_head,
704
struct wt_status *s,
763
} else if (fixup_message) {
764
struct pretty_print_context ctx = {0};
765
struct commit *commit;
748
- commit = lookup_commit_reference_by_name(fixup_message);
766
+ char *fmt;
767
+ commit = lookup_commit_reference_by_name(fixup_commit);
768
if (!commit)
750
- die(_("could not lookup commit %s"), fixup_message);
769
+ die(_("could not lookup commit %s"), fixup_commit);
770
ctx.output_encoding = get_commit_output_encoding();
752
- format_commit_message(commit, "fixup! %s\n\n",
753
- &sb, &ctx);
754
- if (have_option_m)
755
- strbuf_addbuf(&sb, &message);
771
+ fmt = xstrfmt("%s! %%s\n\n", fixup_prefix);
772
+ format_commit_message(commit, fmt, &sb, &ctx);
773
+ free(fmt);
774
hook_arg1 = "message";
775
+
776
+ /*
777
+ * Only `-m` commit message option is checked here, as
778
+ * it supports `--fixup` to append the commit message.
779
+ *
780
+ * The other commit message options `-c`/`-C`/`-F` are
781
+ * incompatible with all the forms of `--fixup` and
782
+ * have already errored out while parsing the `git commit`
783
+ * options.
784
+ */
785
+ if (have_option_m && !strcmp(fixup_prefix, "fixup"))
786
+ strbuf_addbuf(&sb, &message);
787
+
788
+ if (!strcmp(fixup_prefix, "amend")) {
789
+ if (have_option_m)
790
+ die(_("cannot combine -m with --fixup:%s"), fixup_message);
791
+ prepare_amend_commit(commit, &sb, &ctx);
792
+ }
793
} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
794
size_t merge_msg_start;
795
1206
if (force_author && renew_authorship)
1207
die(_("Using both --reset-author and --author does not make sense"));
1208
1173
- if (logfile || have_option_m || use_message || fixup_message)
1209
+ if (logfile || have_option_m || use_message)
1210
use_editor = 0;
1211
if (0 <= edit_flag)
1212
use_editor = edit_flag;
1263
1264
if (also + only + all + interactive > 1)
1265
die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
1266
+
1267
+ if (fixup_message) {
1268
+ /*
1269
+ * We limit --fixup's suboptions to only alpha characters.
1270
+ * If the first character after a run of alpha is colon,
1271
+ * then the part before the colon may be a known suboption
1272
+ * name `amend` or a misspelt suboption name. In this case,
1273
+ * we treat it as --fixup=<suboption>:<arg>.
1274
+ *
1275
+ * Otherwise, we are dealing with --fixup=<commit>.
1276
+ */
1277
+ char *p = fixup_message;
1278
+ while (isalpha(*p))
1279
+ p++;
1280
+ if (p > fixup_message && *p == ':') {
1281
+ *p = '\0';
1282
+ fixup_commit = p + 1;
1283
+ if (!strcmp("amend", fixup_message)) {
1284
+ fixup_prefix = "amend";
1285
+ allow_empty = 1;
1286
+ } else {
1287
+ die(_("unknown option: --fixup=%s:%s"), fixup_message, fixup_commit);
1288
+ }
1289
+ } else {
1290
+ fixup_commit = fixup_message;
1291
+ fixup_prefix = "fixup";
1292
+ use_editor = 0;
1293
+ }
1294
+ }
1295
+
1296
cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
1297
1298
handle_untracked_files_arg(s);
1570
OPT_CALLBACK('m', "message", &message, N_("message"), N_("commit message"), opt_parse_m),
1571
OPT_STRING('c', "reedit-message", &edit_message, N_("commit"), N_("reuse and edit message from specified commit")),
1572
OPT_STRING('C', "reuse-message", &use_message, N_("commit"), N_("reuse message from specified commit")),
1507
- OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
1573
+ /*
1574
+ * TRANSLATORS: Leave "[amend:]" as-is, and
1575
+ * only translate <commit>.
1576
+ */
1577
+ OPT_STRING(0, "fixup", &fixup_message, N_("[amend:]commit"), N_("use autosquash formatted message to fixup or amend specified commit")),
1578
OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
1579
OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
1580
OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
1733
exit(1);
1734
}
1735
1736
+ if (fixup_message && starts_with(sb.buf, "amend! ") &&
1737
+ !allow_empty_message) {
1738
+ struct strbuf body = STRBUF_INIT;
1739
+ size_t len = commit_subject_length(sb.buf);
1740
+ strbuf_addstr(&body, sb.buf + len);
1741
+ if (message_is_empty(&body, cleanup_mode)) {
1742
+ rollback_index_files();
1743
+ fprintf(stderr, _("Aborting commit due to empty commit message body.\n"));
1744
+ exit(1);
1745
+ }
1746
+ strbuf_release(&body);
1747
+ }
1748
+
1749
if (amend) {
1750
const char *exclude_gpgsig[3] = { "gpgsig", "gpgsig-sha256", NULL };
1751
extra = read_commit_extra_headers(current_head, exclude_gpgsig);