commit: allow -c/-C for all kinds of --fixup
The previous commit allowed -m and -F for all --fixup variations. The -c/-C flags were blocked by the same higher-layer incompatibility check that previously caught -F, namely die_for_incompatible_opt4() grouping them with --fixup. Drop --fixup from that check and route the resolved commit through prepare_amend_commit() in the fixup path, mirroring the no-message-source behaviour of --fixup=amend. With this in place, -m/-F/-c/-C all behave consistently across the plain, amend, and reword --fixup forms. Signed-off-by: Erik Cervin-Edin <erik@cervined.in> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Erik Cervin-Edin committed
May 26, 2026 at 12:47 UTC
f1c098502df421cb0c96bb168044c278ef9d7990
3 files changed
+71
-11
Documentation/git-commit.adoc
+5
-4
@@ -102,8 +102,8 @@ include::diff-context-options.adoc[]
102
+
103
The commit created by plain `--fixup=<commit>` has a title
104
composed of "fixup!" followed by the title of _<commit>_,
105
-and is recognized specially by `git rebase --autosquash`. The `-m`
106
-or `-F` option may be used to supplement the log message
105
+and is recognized specially by `git rebase --autosquash`. The `-m`,
106
+`-F`, `-C`, or `-c` option may be used to supplement the log message
107
of the created commit, but the additional commentary will be thrown
108
away once the "fixup!" commit is squashed into _<commit>_ by
109
`git rebase --autosquash`.
@@ -112,8 +112,9 @@ The commit created by `--fixup=amend:<commit>` is similar but its
112
title is instead prefixed with "amend!". The log message of
113
_<commit>_ is copied into the log message of the "amend!" commit and
114
opened in an editor so it can be refined. The replacement message may
115
-also be supplied directly using `-m` or `-F`, bypassing the
116
-need to open an editor. When `git rebase
115
+also be supplied directly using `-m`, `-F`, or `-C`, bypassing the
116
+need to open an editor, or using `-c` to open the editor pre-populated
117
+with the referenced commit's message. When `git rebase
118
--autosquash` squashes the "amend!" commit into _<commit>_, the log
119
message of _<commit>_ is replaced by the refined log message from the
120
"amend!" commit. It is an error for the "amend!" commit's log message
builtin/commit.c
+9
-4
@@ -837,9 +837,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
837
hook_arg1 = "message";
838
839
/*
840
- * Only `-m` and `-F` are handled here. `-c`/`-C` are
841
- * incompatible with --fixup and have already errored out
842
- * during option parsing.
840
+ * `-m`, `-F`, `-C`, and `-c` provide the message body.
841
+ * If none was given and this is an amend, use the target
842
+ * commit's body instead.
843
*/
844
if (have_option_m) {
845
strbuf_addbuf(&sb, &message);
@@ -851,6 +851,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
851
} else if (logfile) {
852
if (strbuf_read_file(&sb, logfile, 0) < 0)
853
die_errno(_("could not read log file '%s'"), logfile);
854
+ } else if (use_message) {
855
+ struct commit *c = lookup_commit_reference_by_name(use_message);
856
+ if (!c)
857
+ die(_("could not lookup commit '%s'"), use_message);
858
+ prepare_amend_commit(c, &sb, &ctx);
859
} else if (!strcmp(fixup_prefix, "amend")) {
860
prepare_amend_commit(commit, &sb, &ctx);
861
}
@@ -1341,7 +1346,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
1346
die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
1347
die_for_incompatible_opt3(!!use_message, "-C",
1348
!!edit_message, "-c",
1344
- !!fixup_message, "--fixup");
1349
+ !!logfile, "-F");
1350
die_for_incompatible_opt4(have_option_m, "-m",
1351
!!edit_message, "-c",
1352
!!use_message, "-C",
t/t7500-commit-template-squash-signoff.sh
+57
-3
@@ -492,6 +492,62 @@ test_expect_success 'commit --fixup works with -F' '
492
EOF
493
'
494
495
+test_expect_success 'commit --fixup works with -C' '
496
+ commit_for_rebase_autosquash_setup &&
497
+ git commit --fixup HEAD~ -C HEAD &&
498
+ test_commit_message HEAD <<-EOF
499
+ fixup! $(git log -1 --format=%s HEAD~2)
500
+
501
+ $(get_commit_msg HEAD~)
502
+ EOF
503
+'
504
+
505
+test_expect_success 'commit --fixup=amend: works with -c' '
506
+ commit_for_rebase_autosquash_setup &&
507
+ test_set_editor : &&
508
+ git commit --fixup=amend:HEAD -c HEAD~ &&
509
+ test_commit_message HEAD <<-EOF
510
+ amend! intermediate commit
511
+
512
+ target message subject line
513
+
514
+ target message body line 1
515
+ target message body line 2
516
+ EOF
517
+'
518
+
519
+test_expect_success 'commit --fixup=amend:HEAD with -C HEAD and without have the same message' '
520
+ commit_for_rebase_autosquash_setup &&
521
+ start=$(git rev-parse HEAD) &&
522
+
523
+ git commit --fixup=amend:HEAD -C HEAD &&
524
+ git commit --fixup=amend:HEAD -C HEAD &&
525
+ git log -1 --pretty=%B >with-c &&
526
+
527
+ git reset --hard "$start" &&
528
+ test_set_editor : &&
529
+ git commit --fixup=amend:HEAD &&
530
+ git commit --fixup=amend:HEAD &&
531
+ git log -1 --pretty=%B >without-c &&
532
+
533
+ test_cmp with-c without-c
534
+'
535
+
536
+test_expect_success 'commit --fixup=amend: with -C copies full subject + body of squash commit' '
537
+ commit_for_rebase_autosquash_setup &&
538
+ git commit --squash HEAD~ -m "inner body" &&
539
+ echo "extra" >>foo &&
540
+ git add foo &&
541
+ git commit --fixup=amend:HEAD -C HEAD &&
542
+ test_commit_message HEAD <<-EOF
543
+ amend! squash! $(git log -1 --format=%s HEAD~3)
544
+
545
+ squash! $(git log -1 --format=%s HEAD~3)
546
+
547
+ inner body
548
+ EOF
549
+'
550
+
551
test_expect_success 'commit --fixup=reword: works with -F' '
552
commit_for_rebase_autosquash_setup &&
553
echo "message from file" >msgfile &&
@@ -553,9 +609,7 @@ test_expect_success 'invalid message options when using --fixup' '
609
echo changes >>foo &&
610
echo "message" >log &&
611
git add foo &&
556
- test_must_fail git commit --fixup HEAD~1 --squash HEAD~2 &&
557
- test_must_fail git commit --fixup HEAD~1 -C HEAD~2 &&
558
- test_must_fail git commit --fixup HEAD~1 -c HEAD~2
612
+ test_must_fail git commit --fixup HEAD~1 --squash HEAD~2
613
'
614
615
cat >expected-template <<EOF