summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-rebase.txt2
-rw-r--r--rebase-interactive.c9
-rw-r--r--sequencer.c23
-rw-r--r--t/lib-rebase.sh7
-rwxr-xr-xt/t3437-rebase-fixup-options.sh122
5 files changed, 87 insertions, 76 deletions
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index a6903419c4..8bfa5a9272 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -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
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"
-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
an editor.
diff --git a/rebase-interactive.c b/rebase-interactive.c
index c3bd02adee..b6cbd16a17 100644
--- a/rebase-interactive.c
+++ b/rebase-interactive.c
@@ -44,9 +44,10 @@ void append_todo_help(int command_count,
"r, reword <commit> = use commit, but edit the commit message\n"
"e, edit <commit> = use commit, but stop for amending\n"
"s, squash <commit> = use commit, but meld into previous commit\n"
-"f, fixup [-C | -c] <commit> = like \"squash\", but discard this\n"
-" commit's log message. Use -C to replace with this\n"
-" commit message or -c to edit the commit message\n"
+"f, fixup [-C | -c] <commit> = like \"squash\" but keep only the previous\n"
+" commit's log message, unless -C is used, in which case\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"
"b, break = stop here (continue rebase later with 'git rebase --continue')\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"
". create a merge commit using the original merge commit's\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"
"These lines can be re-ordered; they are executed from top to bottom.\n");
unsigned edit_todo = !(shortrevisions && shortonto);
diff --git a/sequencer.c b/sequencer.c
index e32020252d..aedca2d52b 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -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 combined_commit_msg_fmt[] = N_("This is a combination of %d commits.");
-static int check_fixup_flag(enum todo_command command,
- enum todo_item_flags flag)
+static int is_fixup_flag(enum todo_command command, unsigned flag)
{
return command == TODO_FIXUP && ((flag & TODO_REPLACE_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,
enum todo_command command, struct replay_opts *opts,
- enum todo_item_flags flag)
+ unsigned flag)
{
const char *fixup_msg;
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);
/* 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
* 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,
struct commit *commit,
struct replay_opts *opts,
- enum todo_item_flags flag)
+ unsigned flag)
{
struct strbuf buf = STRBUF_INIT;
int res = 0;
@@ -1937,7 +1936,7 @@ static int update_squash_messages(struct repository *r,
opts->current_fixup_count + 2);
strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
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);
} else {
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, _(combined_commit_msg_fmt), 2);
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) :
_(first_commit_msg_str));
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));
else
strbuf_addstr(&buf, body);
@@ -1977,7 +1976,7 @@ static int update_squash_messages(struct repository *r,
oid_to_hex(&commit->object.oid));
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);
} else if (command == TODO_FIXUP) {
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 *);
-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) ||
skip_prefix(subject, "amend! ", p) ||
skip_prefix(subject, "squash! ", p);
@@ -5734,13 +5733,13 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
format_subject(&buf, subject, " ");
subject = subjects[i] = strbuf_detach(&buf, &subject_len);
unuse_commit_buffer(item->commit, commit_buffer);
- if (skip_fixup_amend_squash(subject, &p)) {
+ if (skip_fixupish(subject, &p)) {
struct commit *commit2;
for (;;) {
while (isspace(*p))
p++;
- if (!skip_fixup_amend_squash(p, &p))
+ if (!skip_fixupish(p, &p))
break;
}
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 27928ecb94..dc75b83451 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -15,10 +15,11 @@
# specified line.
#
# "<cmd> <lineno>" -- add a line with the specified command
-# ("pick", "squash", "fixup", "edit", "reword" or "drop") and the
-# SHA1 taken from the specified line.
+# ("pick", "squash", "fixup"|"fixup_-C"|"fixup_-c", "edit", "reword" or "drop")
+# 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.
#
diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh
index 945df2555b..a5a20354e3 100755
--- a/t/t3437-rebase-fixup-options.sh
+++ b/t/t3437-rebase-fixup-options.sh
@@ -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"
replaces the original commit message with the message of the fixup
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
@@ -18,35 +20,35 @@ editor to allow the user to edit the message before committing.
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 () {
- rev="$1" && # commit or tag we want to test
- file="$2" && # test against the content of a file
- git show --no-patch --pretty=format:%B "$rev" >actual-message &&
- if test "$2" = -m
- then
- str="$3" && # test against a string
- printf "%s\n" "$str" >tmp-expected-message &&
- file="tmp-expected-message"
- fi
- test_cmp "$file" actual-message
+ git show --no-patch --pretty=format:%B "$1" >actual &&
+ case "$2" in
+ -m)
+ echo "$3" >expect &&
+ test_cmp expect actual ;;
+ *)
+ test_cmp "$2" actual ;;
+ esac
}
get_author () {
rev="$1" &&
- git log -1 --pretty=format:"%an %ae" "$rev"
+ git log -1 --pretty=format:"%an %ae %at" "$rev"
}
test_expect_success 'setup' '
cat >message <<-EOF &&
- amend! B
- ${EMPTY}
- new subject
- ${EMPTY}
- new
- body
- EOF
-
- sed "1,2d" message >expected-message &&
+ amend! B
+ $EMPTY
+ new subject
+ $EMPTY
+ new
+ body
+ EOF
test_commit A A &&
test_commit B B &&
@@ -68,40 +70,43 @@ test_expect_success 'setup' '
echo B1 >B &&
test_tick &&
git commit --fixup=HEAD -a &&
+ git tag B1 &&
test_tick &&
git commit --allow-empty -F - <<-EOF &&
- amend! B
- ${EMPTY}
- B
- ${EMPTY}
- edited 1
- EOF
+ amend! B
+ $EMPTY
+ B
+ $EMPTY
+ edited 1
+ EOF
test_tick &&
git commit --allow-empty -F - <<-EOF &&
- amend! amend! B
- ${EMPTY}
- B
- ${EMPTY}
- edited 1
- ${EMPTY}
- edited 2
- EOF
+ amend! amend! B
+ $EMPTY
+ B
+ $EMPTY
+ edited 1
+ $EMPTY
+ edited 2
+ EOF
echo B2 >B &&
test_tick &&
FAKE_COMMIT_AMEND="edited squash" git commit --squash=HEAD -a &&
+ git tag B2 &&
echo B3 >B &&
test_tick &&
git commit -a -F - <<-EOF &&
- amend! amend! amend! B
- ${EMPTY}
- B
- ${EMPTY}
- edited 1
- ${EMPTY}
- edited 2
- ${EMPTY}
- edited 3
- EOF
+ amend! amend! amend! B
+ $EMPTY
+ B
+ $EMPTY
+ edited 1
+ $EMPTY
+ edited 2
+ $EMPTY
+ edited 3
+ EOF
+ git tag B3 &&
GIT_AUTHOR_NAME="Rebase Author" &&
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_when_finished "test_might_fail git rebase --abort" &&
git checkout --detach A1 &&
+ git log -1 --pretty=format:%b >expected-message &&
FAKE_LINES="1 fixup_-C 2" git rebase -i A &&
test_cmp_rev HEAD^ A &&
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_when_finished "test_might_fail git rebase --abort" &&
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 &&
git checkout --theirs -- A &&
git add A &&
FAKE_COMMIT_AMEND=edited git rebase --continue &&
test_cmp_rev HEAD^ conflicts &&
test_cmp_rev HEAD^{tree} A1^{tree} &&
- test_write_lines "" edited >>expected-message &&
test_commit_message HEAD expected-message &&
get_author HEAD >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' '
- 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_COMMIT_AMEND=squashed \
FAKE_MESSAGE_COPY=actual-squash-message \
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_i18ncmp "$TEST_DIRECTORY/t3437/expected-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_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 &&
FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4" git rebase -i 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_when_finished "test_might_fail git rebase --abort" &&
git checkout --detach A3 &&
- base=$(git rev-parse HEAD~4) &&
- FAKE_COMMIT_MESSAGE="Modified-A3" \
+ git log -1 --pretty=format:%B >expected-message &&
+ test_write_lines "" "Modified-A3" >>expected-message &&
+ FAKE_COMMIT_AMEND="Modified-A3" \
FAKE_LINES="1 fixup_-C 2 fixup_-c 3 fixup_-c 4" \
EXPECT_HEADER_COUNT=4 \
- git rebase -i $base &&
- test_cmp_rev $base HEAD^ &&
- test 1 = $(git show | grep Modified-A3 | wc -l)
+ git rebase -i A &&
+ test_cmp_rev HEAD^ A &&
+ 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' '
@@ -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!' '
- git checkout --detach branch &&
+ git checkout --detach B3 &&
FAKE_COMMIT_AMEND=squashed \
FAKE_MESSAGE_COPY=actual-squash-message \
git -c commit.status=false rebase -ik --autosquash \
--signoff A &&
- git diff-tree --exit-code --patch HEAD branch -- &&
+ git diff-tree --exit-code --patch HEAD B3 -- &&
test_cmp_rev HEAD^ A &&
test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
actual-squash-message