Merge branch 'cm/rebase-i-updates'

Follow-up fixes to "cm/rebase-i" topic.

* cm/rebase-i-updates:
  doc/rebase -i: fix typo in the documentation of 'fixup' command
  t/t3437: fixup the test 'multiple fixup -c opens editor once'
  t/t3437: use named commits in the tests
  t/t3437: simplify and document the test helpers
  t/t3437: check the author date of fixed up commit
  t/t3437: remove the dependency of 'expected-message' file from tests
  t/t3437: fixup here-docs in the 'setup' test
  t/lib-rebase: update the documentation of FAKE_LINES
  rebase -i: clarify and fix 'fixup -c' rebase-todo help
  sequencer: rename a few functions
  sequencer: fixup the datatype of the 'flag' argument
This commit is contained in:
Junio C Hamano 2021-03-26 14:59:03 -07:00
commit fde07fc356
5 changed files with 87 additions and 76 deletions

View File

@ -894,7 +894,7 @@ is used. In that case the suggested commit message is only the message
of the "fixup -c" commit, and an editor is opened allowing you to edit of the "fixup -c" commit, and an editor is opened allowing you to edit
the message. The contents (patch) of the "fixup -c" commit are still the message. The contents (patch) of the "fixup -c" commit are still
incorporated into the folded commit. If there is more than one "fixup -c" incorporated into the folded commit. If there is more than one "fixup -c"
commit, the message from the last last one is used. You can also use commit, the message from the final one is used. You can also use
"fixup -C" to get the same behavior as "fixup -c" except without opening "fixup -C" to get the same behavior as "fixup -c" except without opening
an editor. an editor.

View File

@ -44,9 +44,10 @@ void append_todo_help(int command_count,
"r, reword <commit> = use commit, but edit the commit message\n" "r, reword <commit> = use commit, but edit the commit message\n"
"e, edit <commit> = use commit, but stop for amending\n" "e, edit <commit> = use commit, but stop for amending\n"
"s, squash <commit> = use commit, but meld into previous commit\n" "s, squash <commit> = use commit, but meld into previous commit\n"
"f, fixup [-C | -c] <commit> = like \"squash\", but discard this\n" "f, fixup [-C | -c] <commit> = like \"squash\" but keep only the previous\n"
" commit's log message. Use -C to replace with this\n" " commit's log message, unless -C is used, in which case\n"
" commit message or -c to edit the commit message\n" " keep only this commit's message; -c is same as -C but\n"
" opens the editor\n"
"x, exec <command> = run command (the rest of the line) using shell\n" "x, exec <command> = run command (the rest of the line) using shell\n"
"b, break = stop here (continue rebase later with 'git rebase --continue')\n" "b, break = stop here (continue rebase later with 'git rebase --continue')\n"
"d, drop <commit> = remove commit\n" "d, drop <commit> = remove commit\n"
@ -55,7 +56,7 @@ void append_todo_help(int command_count,
"m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]\n" "m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]\n"
". create a merge commit using the original merge commit's\n" ". create a merge commit using the original merge commit's\n"
". message (or the oneline, if no original merge commit was\n" ". message (or the oneline, if no original merge commit was\n"
". specified). Use -c <commit> to reword the commit message.\n" ". specified); use -c <commit> to reword the commit message\n"
"\n" "\n"
"These lines can be re-ordered; they are executed from top to bottom.\n"); "These lines can be re-ordered; they are executed from top to bottom.\n");
unsigned edit_todo = !(shortrevisions && shortonto); unsigned edit_todo = !(shortrevisions && shortonto);

View File

@ -1752,8 +1752,7 @@ static const char skip_first_commit_msg_str[] = N_("The 1st commit message will
static const char skip_nth_commit_msg_fmt[] = N_("The commit message #%d will be skipped:"); static const char skip_nth_commit_msg_fmt[] = N_("The commit message #%d will be skipped:");
static const char combined_commit_msg_fmt[] = N_("This is a combination of %d commits."); static const char combined_commit_msg_fmt[] = N_("This is a combination of %d commits.");
static int check_fixup_flag(enum todo_command command, static int is_fixup_flag(enum todo_command command, unsigned flag)
enum todo_item_flags flag)
{ {
return command == TODO_FIXUP && ((flag & TODO_REPLACE_FIXUP_MSG) || return command == TODO_FIXUP && ((flag & TODO_REPLACE_FIXUP_MSG) ||
(flag & TODO_EDIT_FIXUP_MSG)); (flag & TODO_EDIT_FIXUP_MSG));
@ -1858,7 +1857,7 @@ static void update_squash_message_for_fixup(struct strbuf *msg)
static int append_squash_message(struct strbuf *buf, const char *body, static int append_squash_message(struct strbuf *buf, const char *body,
enum todo_command command, struct replay_opts *opts, enum todo_command command, struct replay_opts *opts,
enum todo_item_flags flag) unsigned flag)
{ {
const char *fixup_msg; const char *fixup_msg;
size_t commented_len = 0, fixup_off; size_t commented_len = 0, fixup_off;
@ -1882,7 +1881,7 @@ static int append_squash_message(struct strbuf *buf, const char *body,
strbuf_addstr(buf, body + commented_len); strbuf_addstr(buf, body + commented_len);
/* fixup -C after squash behaves like squash */ /* fixup -C after squash behaves like squash */
if (check_fixup_flag(command, flag) && !seen_squash(opts)) { if (is_fixup_flag(command, flag) && !seen_squash(opts)) {
/* /*
* We're replacing the commit message so we need to * We're replacing the commit message so we need to
* append the Signed-off-by: trailer if the user * append the Signed-off-by: trailer if the user
@ -1914,7 +1913,7 @@ static int update_squash_messages(struct repository *r,
enum todo_command command, enum todo_command command,
struct commit *commit, struct commit *commit,
struct replay_opts *opts, struct replay_opts *opts,
enum todo_item_flags flag) unsigned flag)
{ {
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
int res = 0; int res = 0;
@ -1937,7 +1936,7 @@ static int update_squash_messages(struct repository *r,
opts->current_fixup_count + 2); opts->current_fixup_count + 2);
strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len); strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
strbuf_release(&header); strbuf_release(&header);
if (check_fixup_flag(command, flag) && !seen_squash(opts)) if (is_fixup_flag(command, flag) && !seen_squash(opts))
update_squash_message_for_fixup(&buf); update_squash_message_for_fixup(&buf);
} else { } else {
struct object_id head; struct object_id head;
@ -1960,11 +1959,11 @@ static int update_squash_messages(struct repository *r,
strbuf_addf(&buf, "%c ", comment_line_char); strbuf_addf(&buf, "%c ", comment_line_char);
strbuf_addf(&buf, _(combined_commit_msg_fmt), 2); strbuf_addf(&buf, _(combined_commit_msg_fmt), 2);
strbuf_addf(&buf, "\n%c ", comment_line_char); strbuf_addf(&buf, "\n%c ", comment_line_char);
strbuf_addstr(&buf, check_fixup_flag(command, flag) ? strbuf_addstr(&buf, is_fixup_flag(command, flag) ?
_(skip_first_commit_msg_str) : _(skip_first_commit_msg_str) :
_(first_commit_msg_str)); _(first_commit_msg_str));
strbuf_addstr(&buf, "\n\n"); strbuf_addstr(&buf, "\n\n");
if (check_fixup_flag(command, flag)) if (is_fixup_flag(command, flag))
strbuf_add_commented_lines(&buf, body, strlen(body)); strbuf_add_commented_lines(&buf, body, strlen(body));
else else
strbuf_addstr(&buf, body); strbuf_addstr(&buf, body);
@ -1977,7 +1976,7 @@ static int update_squash_messages(struct repository *r,
oid_to_hex(&commit->object.oid)); oid_to_hex(&commit->object.oid));
find_commit_subject(message, &body); find_commit_subject(message, &body);
if (command == TODO_SQUASH || check_fixup_flag(command, flag)) { if (command == TODO_SQUASH || is_fixup_flag(command, flag)) {
res = append_squash_message(&buf, body, command, opts, flag); res = append_squash_message(&buf, body, command, opts, flag);
} else if (command == TODO_FIXUP) { } else if (command == TODO_FIXUP) {
strbuf_addf(&buf, "\n%c ", comment_line_char); strbuf_addf(&buf, "\n%c ", comment_line_char);
@ -5670,7 +5669,7 @@ static int subject2item_cmp(const void *fndata,
define_commit_slab(commit_todo_item, struct todo_item *); define_commit_slab(commit_todo_item, struct todo_item *);
static inline int skip_fixup_amend_squash(const char *subject, const char **p) { static int skip_fixupish(const char *subject, const char **p) {
return skip_prefix(subject, "fixup! ", p) || return skip_prefix(subject, "fixup! ", p) ||
skip_prefix(subject, "amend! ", p) || skip_prefix(subject, "amend! ", p) ||
skip_prefix(subject, "squash! ", p); skip_prefix(subject, "squash! ", p);
@ -5734,13 +5733,13 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
format_subject(&buf, subject, " "); format_subject(&buf, subject, " ");
subject = subjects[i] = strbuf_detach(&buf, &subject_len); subject = subjects[i] = strbuf_detach(&buf, &subject_len);
unuse_commit_buffer(item->commit, commit_buffer); unuse_commit_buffer(item->commit, commit_buffer);
if (skip_fixup_amend_squash(subject, &p)) { if (skip_fixupish(subject, &p)) {
struct commit *commit2; struct commit *commit2;
for (;;) { for (;;) {
while (isspace(*p)) while (isspace(*p))
p++; p++;
if (!skip_fixup_amend_squash(p, &p)) if (!skip_fixupish(p, &p))
break; break;
} }

View File

@ -15,10 +15,11 @@
# specified line. # specified line.
# #
# "<cmd> <lineno>" -- add a line with the specified command # "<cmd> <lineno>" -- add a line with the specified command
# ("pick", "squash", "fixup", "edit", "reword" or "drop") and the # ("pick", "squash", "fixup"|"fixup_-C"|"fixup_-c", "edit", "reword" or "drop")
# SHA1 taken from the specified line. # and the SHA1 taken from the specified line.
# #
# "exec_cmd_with_args" -- add an "exec cmd with args" line. # "_" -- add a space, like "fixup_-C" implies "fixup -C" and
# "exec_cmd_with_args" add an "exec cmd with args" line.
# #
# "#" -- Add a comment line. # "#" -- Add a comment line.
# #

View File

@ -9,7 +9,9 @@ This test checks the "fixup [-C|-c]" command of rebase interactive.
In addition to amending the contents of the commit, "fixup -C" In addition to amending the contents of the commit, "fixup -C"
replaces the original commit message with the message of the fixup replaces the original commit message with the message of the fixup
commit. "fixup -c" also replaces the original message, but opens the commit. "fixup -c" also replaces the original message, but opens the
editor to allow the user to edit the message before committing. editor to allow the user to edit the message before committing. Similar
to the "fixup" command that works with "fixup!", "fixup -C" works with
"amend!" upon --autosquash.
' '
. ./test-lib.sh . ./test-lib.sh
@ -18,35 +20,35 @@ editor to allow the user to edit the message before committing.
EMPTY="" EMPTY=""
# test_commit_message <rev> -m <msg>
# test_commit_message <rev> <path>
# Verify that the commit message of <rev> matches
# <msg> or the content of <path>.
test_commit_message () { test_commit_message () {
rev="$1" && # commit or tag we want to test git show --no-patch --pretty=format:%B "$1" >actual &&
file="$2" && # test against the content of a file case "$2" in
git show --no-patch --pretty=format:%B "$rev" >actual-message && -m)
if test "$2" = -m echo "$3" >expect &&
then test_cmp expect actual ;;
str="$3" && # test against a string *)
printf "%s\n" "$str" >tmp-expected-message && test_cmp "$2" actual ;;
file="tmp-expected-message" esac
fi
test_cmp "$file" actual-message
} }
get_author () { get_author () {
rev="$1" && rev="$1" &&
git log -1 --pretty=format:"%an %ae" "$rev" git log -1 --pretty=format:"%an %ae %at" "$rev"
} }
test_expect_success 'setup' ' test_expect_success 'setup' '
cat >message <<-EOF && cat >message <<-EOF &&
amend! B amend! B
${EMPTY} $EMPTY
new subject new subject
${EMPTY} $EMPTY
new new
body body
EOF EOF
sed "1,2d" message >expected-message &&
test_commit A A && test_commit A A &&
test_commit B B && test_commit B B &&
@ -68,40 +70,43 @@ test_expect_success 'setup' '
echo B1 >B && echo B1 >B &&
test_tick && test_tick &&
git commit --fixup=HEAD -a && git commit --fixup=HEAD -a &&
git tag B1 &&
test_tick && test_tick &&
git commit --allow-empty -F - <<-EOF && git commit --allow-empty -F - <<-EOF &&
amend! B amend! B
${EMPTY} $EMPTY
B B
${EMPTY} $EMPTY
edited 1 edited 1
EOF EOF
test_tick && test_tick &&
git commit --allow-empty -F - <<-EOF && git commit --allow-empty -F - <<-EOF &&
amend! amend! B amend! amend! B
${EMPTY} $EMPTY
B B
${EMPTY} $EMPTY
edited 1 edited 1
${EMPTY} $EMPTY
edited 2 edited 2
EOF EOF
echo B2 >B && echo B2 >B &&
test_tick && test_tick &&
FAKE_COMMIT_AMEND="edited squash" git commit --squash=HEAD -a && FAKE_COMMIT_AMEND="edited squash" git commit --squash=HEAD -a &&
git tag B2 &&
echo B3 >B && echo B3 >B &&
test_tick && test_tick &&
git commit -a -F - <<-EOF && git commit -a -F - <<-EOF &&
amend! amend! amend! B amend! amend! amend! B
${EMPTY} $EMPTY
B B
${EMPTY} $EMPTY
edited 1 edited 1
${EMPTY} $EMPTY
edited 2 edited 2
${EMPTY} $EMPTY
edited 3 edited 3
EOF EOF
git tag B3 &&
GIT_AUTHOR_NAME="Rebase Author" && GIT_AUTHOR_NAME="Rebase Author" &&
GIT_AUTHOR_EMAIL="rebase.author@example.com" && GIT_AUTHOR_EMAIL="rebase.author@example.com" &&
@ -134,6 +139,7 @@ test_expect_success 'simple fixup -c works' '
test_expect_success 'fixup -C removes amend! from message' ' test_expect_success 'fixup -C removes amend! from message' '
test_when_finished "test_might_fail git rebase --abort" && test_when_finished "test_might_fail git rebase --abort" &&
git checkout --detach A1 && git checkout --detach A1 &&
git log -1 --pretty=format:%b >expected-message &&
FAKE_LINES="1 fixup_-C 2" git rebase -i A && FAKE_LINES="1 fixup_-C 2" git rebase -i A &&
test_cmp_rev HEAD^ A && test_cmp_rev HEAD^ A &&
test_cmp_rev HEAD^{tree} A1^{tree} && test_cmp_rev HEAD^{tree} A1^{tree} &&
@ -145,13 +151,14 @@ test_expect_success 'fixup -C removes amend! from message' '
test_expect_success 'fixup -C with conflicts gives correct message' ' test_expect_success 'fixup -C with conflicts gives correct message' '
test_when_finished "test_might_fail git rebase --abort" && test_when_finished "test_might_fail git rebase --abort" &&
git checkout --detach A1 && git checkout --detach A1 &&
git log -1 --pretty=format:%b >expected-message &&
test_write_lines "" "edited" >>expected-message &&
test_must_fail env FAKE_LINES="1 fixup_-C 2" git rebase -i conflicts && test_must_fail env FAKE_LINES="1 fixup_-C 2" git rebase -i conflicts &&
git checkout --theirs -- A && git checkout --theirs -- A &&
git add A && git add A &&
FAKE_COMMIT_AMEND=edited git rebase --continue && FAKE_COMMIT_AMEND=edited git rebase --continue &&
test_cmp_rev HEAD^ conflicts && test_cmp_rev HEAD^ conflicts &&
test_cmp_rev HEAD^{tree} A1^{tree} && test_cmp_rev HEAD^{tree} A1^{tree} &&
test_write_lines "" edited >>expected-message &&
test_commit_message HEAD expected-message && test_commit_message HEAD expected-message &&
get_author HEAD >actual-author && get_author HEAD >actual-author &&
test_cmp expected-author actual-author test_cmp expected-author actual-author
@ -167,12 +174,12 @@ test_expect_success 'skipping fixup -C after fixup gives correct message' '
' '
test_expect_success 'sequence of fixup, fixup -C & squash --signoff works' ' test_expect_success 'sequence of fixup, fixup -C & squash --signoff works' '
git checkout --detach branch && git checkout --detach B3 &&
FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4 squash 5 fixup_-C 6" \ FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4 squash 5 fixup_-C 6" \
FAKE_COMMIT_AMEND=squashed \ FAKE_COMMIT_AMEND=squashed \
FAKE_MESSAGE_COPY=actual-squash-message \ FAKE_MESSAGE_COPY=actual-squash-message \
git -c commit.status=false rebase -ik --signoff A && git -c commit.status=false rebase -ik --signoff A &&
git diff-tree --exit-code --patch HEAD branch -- && git diff-tree --exit-code --patch HEAD B3 -- &&
test_cmp_rev HEAD^ A && test_cmp_rev HEAD^ A &&
test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \ test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
actual-squash-message actual-squash-message
@ -180,7 +187,7 @@ test_expect_success 'sequence of fixup, fixup -C & squash --signoff works' '
test_expect_success 'first fixup -C commented out in sequence fixup fixup -C fixup -C' ' test_expect_success 'first fixup -C commented out in sequence fixup fixup -C fixup -C' '
test_when_finished "test_might_fail git rebase --abort" && test_when_finished "test_might_fail git rebase --abort" &&
git checkout branch && git checkout --detach branch~2 && git checkout --detach B2~ &&
git log -1 --pretty=format:%b >expected-message && git log -1 --pretty=format:%b >expected-message &&
FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4" git rebase -i A && FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4" git rebase -i A &&
test_cmp_rev HEAD^ A && test_cmp_rev HEAD^ A &&
@ -190,13 +197,16 @@ test_expect_success 'first fixup -C commented out in sequence fixup fixup -C fix
test_expect_success 'multiple fixup -c opens editor once' ' test_expect_success 'multiple fixup -c opens editor once' '
test_when_finished "test_might_fail git rebase --abort" && test_when_finished "test_might_fail git rebase --abort" &&
git checkout --detach A3 && git checkout --detach A3 &&
base=$(git rev-parse HEAD~4) && git log -1 --pretty=format:%B >expected-message &&
FAKE_COMMIT_MESSAGE="Modified-A3" \ test_write_lines "" "Modified-A3" >>expected-message &&
FAKE_COMMIT_AMEND="Modified-A3" \
FAKE_LINES="1 fixup_-C 2 fixup_-c 3 fixup_-c 4" \ FAKE_LINES="1 fixup_-C 2 fixup_-c 3 fixup_-c 4" \
EXPECT_HEADER_COUNT=4 \ EXPECT_HEADER_COUNT=4 \
git rebase -i $base && git rebase -i A &&
test_cmp_rev $base HEAD^ && test_cmp_rev HEAD^ A &&
test 1 = $(git show | grep Modified-A3 | wc -l) get_author HEAD >actual-author &&
test_cmp expected-author actual-author &&
test_commit_message HEAD expected-message
' '
test_expect_success 'sequence squash, fixup & fixup -c gives combined message' ' test_expect_success 'sequence squash, fixup & fixup -c gives combined message' '
@ -211,12 +221,12 @@ test_expect_success 'sequence squash, fixup & fixup -c gives combined message' '
' '
test_expect_success 'fixup -C works upon --autosquash with amend!' ' test_expect_success 'fixup -C works upon --autosquash with amend!' '
git checkout --detach branch && git checkout --detach B3 &&
FAKE_COMMIT_AMEND=squashed \ FAKE_COMMIT_AMEND=squashed \
FAKE_MESSAGE_COPY=actual-squash-message \ FAKE_MESSAGE_COPY=actual-squash-message \
git -c commit.status=false rebase -ik --autosquash \ git -c commit.status=false rebase -ik --autosquash \
--signoff A && --signoff A &&
git diff-tree --exit-code --patch HEAD branch -- && git diff-tree --exit-code --patch HEAD B3 -- &&
test_cmp_rev HEAD^ A && test_cmp_rev HEAD^ A &&
test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \ test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
actual-squash-message actual-squash-message