Skip to content

Commit 4608a02

Browse files
committed
Merge branch 'pw/rebase-i-show-HEAD-to-reword'
"git rebase -i" showed a wrong HEAD while "reword" open the editor. * pw/rebase-i-show-HEAD-to-reword: sequencer: simplify root commit creation rebase -i: check for updated todo after squash and reword rebase -i: always update HEAD before rewording
2 parents 020011f + b0a3186 commit 4608a02

5 files changed

+75
-103
lines changed

sequencer.c

Lines changed: 39 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -869,34 +869,6 @@ static char *get_author(const char *message)
869869
return NULL;
870870
}
871871

872-
/* Read author-script and return an ident line (author <email> timestamp) */
873-
static const char *read_author_ident(struct strbuf *buf)
874-
{
875-
struct strbuf out = STRBUF_INIT;
876-
char *name, *email, *date;
877-
878-
if (read_author_script(rebase_path_author_script(),
879-
&name, &email, &date, 0))
880-
return NULL;
881-
882-
/* validate date since fmt_ident() will die() on bad value */
883-
if (parse_date(date, &out)){
884-
warning(_("invalid date format '%s' in '%s'"),
885-
date, rebase_path_author_script());
886-
strbuf_release(&out);
887-
return NULL;
888-
}
889-
890-
strbuf_reset(&out);
891-
strbuf_addstr(&out, fmt_ident(name, email, WANT_AUTHOR_IDENT, date, 0));
892-
strbuf_swap(buf, &out);
893-
strbuf_release(&out);
894-
free(name);
895-
free(email);
896-
free(date);
897-
return buf->buf;
898-
}
899-
900872
static const char staged_changes_advice[] =
901873
N_("you have staged changes in your working tree\n"
902874
"If these changes are meant to be squashed into the previous commit, run:\n"
@@ -954,47 +926,6 @@ static int run_git_commit(struct repository *r,
954926
{
955927
struct child_process cmd = CHILD_PROCESS_INIT;
956928

957-
if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
958-
struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
959-
const char *author = NULL;
960-
struct object_id root_commit, *cache_tree_oid;
961-
int res = 0;
962-
963-
if (is_rebase_i(opts)) {
964-
author = read_author_ident(&script);
965-
if (!author) {
966-
strbuf_release(&script);
967-
return -1;
968-
}
969-
}
970-
971-
if (!defmsg)
972-
BUG("root commit without message");
973-
974-
if (!(cache_tree_oid = get_cache_tree_oid(r->index)))
975-
res = -1;
976-
977-
if (!res)
978-
res = strbuf_read_file(&msg, defmsg, 0);
979-
980-
if (res <= 0)
981-
res = error_errno(_("could not read '%s'"), defmsg);
982-
else
983-
res = commit_tree(msg.buf, msg.len, cache_tree_oid,
984-
NULL, &root_commit, author,
985-
opts->gpg_sign);
986-
987-
strbuf_release(&msg);
988-
strbuf_release(&script);
989-
if (!res) {
990-
update_ref(NULL, "CHERRY_PICK_HEAD", &root_commit, NULL,
991-
REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR);
992-
res = update_ref(NULL, "HEAD", &root_commit, NULL, 0,
993-
UPDATE_REFS_MSG_ON_ERR);
994-
}
995-
return res < 0 ? error(_("writing root commit")) : 0;
996-
}
997-
998929
cmd.git_cmd = 1;
999930

1000931
if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
@@ -1378,7 +1309,7 @@ static int try_to_commit(struct repository *r,
13781309
struct object_id *oid)
13791310
{
13801311
struct object_id tree;
1381-
struct commit *current_head;
1312+
struct commit *current_head = NULL;
13821313
struct commit_list *parents = NULL;
13831314
struct commit_extra_header *extra = NULL;
13841315
struct strbuf err = STRBUF_INIT;
@@ -1413,7 +1344,8 @@ static int try_to_commit(struct repository *r,
14131344
}
14141345
parents = copy_commit_list(current_head->parents);
14151346
extra = read_commit_extra_headers(current_head, exclude_gpgsig);
1416-
} else if (current_head) {
1347+
} else if (current_head &&
1348+
(!(flags & CREATE_ROOT_COMMIT) || (flags & AMEND_MSG))) {
14171349
commit_list_insert(current_head, &parents);
14181350
}
14191351

@@ -1490,8 +1422,7 @@ static int do_commit(struct repository *r,
14901422
{
14911423
int res = 1;
14921424

1493-
if (!(flags & EDIT_MSG) && !(flags & VERIFY_MSG) &&
1494-
!(flags & CREATE_ROOT_COMMIT)) {
1425+
if (!(flags & EDIT_MSG) && !(flags & VERIFY_MSG)) {
14951426
struct object_id oid;
14961427
struct strbuf sb = STRBUF_INIT;
14971428

@@ -1775,7 +1706,7 @@ static int do_pick_commit(struct repository *r,
17751706
enum todo_command command,
17761707
struct commit *commit,
17771708
struct replay_opts *opts,
1778-
int final_fixup)
1709+
int final_fixup, int *check_todo)
17791710
{
17801711
unsigned int flags = opts->edit ? EDIT_MSG : 0;
17811712
const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
@@ -1785,7 +1716,7 @@ static int do_pick_commit(struct repository *r,
17851716
char *author = NULL;
17861717
struct commit_message msg = { NULL, NULL, NULL, NULL };
17871718
struct strbuf msgbuf = STRBUF_INIT;
1788-
int res, unborn = 0, allow;
1719+
int res, unborn = 0, reword = 0, allow;
17891720

17901721
if (opts->no_commit) {
17911722
/*
@@ -1855,7 +1786,7 @@ static int do_pick_commit(struct repository *r,
18551786
opts);
18561787
if (res || command != TODO_REWORD)
18571788
goto leave;
1858-
flags |= EDIT_MSG | AMEND_MSG | VERIFY_MSG;
1789+
reword = 1;
18591790
msg_file = NULL;
18601791
goto fast_forward_edit;
18611792
}
@@ -1913,7 +1844,7 @@ static int do_pick_commit(struct repository *r,
19131844
}
19141845

19151846
if (command == TODO_REWORD)
1916-
flags |= EDIT_MSG | VERIFY_MSG;
1847+
reword = 1;
19171848
else if (is_fixup(command)) {
19181849
if (update_squash_messages(r, command, commit, opts))
19191850
return -1;
@@ -1997,13 +1928,21 @@ static int do_pick_commit(struct repository *r,
19971928
} else if (allow)
19981929
flags |= ALLOW_EMPTY;
19991930
if (!opts->no_commit) {
2000-
fast_forward_edit:
20011931
if (author || command == TODO_REVERT || (flags & AMEND_MSG))
20021932
res = do_commit(r, msg_file, author, opts, flags);
20031933
else
20041934
res = error(_("unable to parse commit author"));
1935+
*check_todo = !!(flags & EDIT_MSG);
1936+
if (!res && reword) {
1937+
fast_forward_edit:
1938+
res = run_git_commit(r, NULL, opts, EDIT_MSG |
1939+
VERIFY_MSG | AMEND_MSG |
1940+
(flags & ALLOW_EMPTY));
1941+
*check_todo = 1;
1942+
}
20051943
}
20061944

1945+
20071946
if (!res && final_fixup) {
20081947
unlink(rebase_path_fixup_msg());
20091948
unlink(rebase_path_squash_msg());
@@ -3828,6 +3767,7 @@ static int pick_commits(struct repository *r,
38283767
while (todo_list->current < todo_list->nr) {
38293768
struct todo_item *item = todo_list->items + todo_list->current;
38303769
const char *arg = todo_item_get_arg(todo_list, item);
3770+
int check_todo = 0;
38313771

38323772
if (save_todo(todo_list, opts))
38333773
return -1;
@@ -3866,7 +3806,8 @@ static int pick_commits(struct repository *r,
38663806
command_to_string(item->command), NULL),
38673807
1);
38683808
res = do_pick_commit(r, item->command, item->commit,
3869-
opts, is_final_fixup(todo_list));
3809+
opts, is_final_fixup(todo_list),
3810+
&check_todo);
38703811
if (is_rebase_i(opts) && res < 0) {
38713812
/* Reschedule */
38723813
advise(_(rescheduled_advice),
@@ -3923,7 +3864,6 @@ static int pick_commits(struct repository *r,
39233864
} else if (item->command == TODO_EXEC) {
39243865
char *end_of_arg = (char *)(arg + item->arg_len);
39253866
int saved = *end_of_arg;
3926-
struct stat st;
39273867

39283868
if (!opts->verbose)
39293869
term_clear_line();
@@ -3934,17 +3874,8 @@ static int pick_commits(struct repository *r,
39343874
if (res) {
39353875
if (opts->reschedule_failed_exec)
39363876
reschedule = 1;
3937-
} else if (stat(get_todo_path(opts), &st))
3938-
res = error_errno(_("could not stat '%s'"),
3939-
get_todo_path(opts));
3940-
else if (match_stat_data(&todo_list->stat, &st)) {
3941-
/* Reread the todo file if it has changed. */
3942-
todo_list_release(todo_list);
3943-
if (read_populate_todo(r, todo_list, opts))
3944-
res = -1; /* message was printed */
3945-
/* `current` will be incremented below */
3946-
todo_list->current = -1;
39473877
}
3878+
check_todo = 1;
39483879
} else if (item->command == TODO_LABEL) {
39493880
if ((res = do_label(r, arg, item->arg_len)))
39503881
reschedule = 1;
@@ -3980,6 +3911,20 @@ static int pick_commits(struct repository *r,
39803911
item->commit,
39813912
arg, item->arg_len,
39823913
opts, res, 0);
3914+
} else if (check_todo && !res) {
3915+
struct stat st;
3916+
3917+
if (stat(get_todo_path(opts), &st)) {
3918+
res = error_errno(_("could not stat '%s'"),
3919+
get_todo_path(opts));
3920+
} else if (match_stat_data(&todo_list->stat, &st)) {
3921+
/* Reread the todo file if it has changed. */
3922+
todo_list_release(todo_list);
3923+
if (read_populate_todo(r, todo_list, opts))
3924+
res = -1; /* message was printed */
3925+
/* `current` will be incremented below */
3926+
todo_list->current = -1;
3927+
}
39833928
}
39843929

39853930
todo_list->current++;
@@ -4306,9 +4251,12 @@ static int single_pick(struct repository *r,
43064251
struct commit *cmit,
43074252
struct replay_opts *opts)
43084253
{
4254+
int check_todo;
4255+
43094256
setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
43104257
return do_pick_commit(r, opts->action == REPLAY_PICK ?
4311-
TODO_PICK : TODO_REVERT, cmit, opts, 0);
4258+
TODO_PICK : TODO_REVERT, cmit, opts, 0,
4259+
&check_todo);
43124260
}
43134261

43144262
int sequencer_pick_revisions(struct repository *r,

t/t3404-rebase-interactive.sh

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,16 +1014,26 @@ test_expect_success 'rebase -i --root fixup root commit' '
10141014
test 0 = $(git cat-file commit HEAD | grep -c ^parent\ )
10151015
'
10161016

1017-
test_expect_success 'rebase -i --root reword root commit' '
1017+
test_expect_success 'rebase -i --root reword original root commit' '
10181018
test_when_finished "test_might_fail git rebase --abort" &&
1019-
git checkout -b reword-root-branch master &&
1019+
git checkout -b reword-original-root-branch master &&
10201020
set_fake_editor &&
10211021
FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \
10221022
git rebase -i --root &&
10231023
git show HEAD^ | grep "A changed" &&
10241024
test -z "$(git show -s --format=%p HEAD^)"
10251025
'
10261026

1027+
test_expect_success 'rebase -i --root reword new root commit' '
1028+
test_when_finished "test_might_fail git rebase --abort" &&
1029+
git checkout -b reword-now-root-branch master &&
1030+
set_fake_editor &&
1031+
FAKE_LINES="reword 3 1" FAKE_COMMIT_MESSAGE="C changed" \
1032+
git rebase -i --root &&
1033+
git show HEAD^ | grep "C changed" &&
1034+
test -z "$(git show -s --format=%p HEAD^)"
1035+
'
1036+
10271037
test_expect_success 'rebase -i --root when root has untracked file conflict' '
10281038
test_when_finished "reset_rebase" &&
10291039
git checkout -b failing-root-pick A &&
@@ -1052,7 +1062,7 @@ test_expect_success 'rebase -i --root reword root when root has untracked file c
10521062
'
10531063

10541064
test_expect_success C_LOCALE_OUTPUT 'rebase --edit-todo does not work on non-interactive rebase' '
1055-
git checkout reword-root-branch &&
1065+
git checkout reword-original-root-branch &&
10561066
git reset --hard &&
10571067
git checkout conflict-branch &&
10581068
set_fake_editor &&

t/t3429-rebase-edit-todo.sh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@
33
test_description='rebase should reread the todo file if an exec modifies it'
44

55
. ./test-lib.sh
6+
. "$TEST_DIRECTORY"/lib-rebase.sh
7+
8+
test_expect_success 'setup' '
9+
test_commit first file &&
10+
test_commit second file &&
11+
test_commit third file
12+
'
613

714
test_expect_success 'rebase exec modifies rebase-todo' '
8-
test_commit initial &&
915
todo=.git/rebase-merge/git-rebase-todo &&
1016
git rebase HEAD -x "echo exec touch F >>$todo" &&
1117
test -e F
@@ -33,4 +39,17 @@ test_expect_success SHA1 'loose object cache vs re-reading todo list' '
3339
git rebase HEAD -x "./append-todo.sh 5 6"
3440
'
3541

42+
test_expect_success 'todo is re-read after reword and squash' '
43+
write_script reword-editor.sh <<-\EOS &&
44+
GIT_SEQUENCE_EDITOR="echo \"exec echo $(cat file) >>actual\" >>" \
45+
git rebase --edit-todo
46+
EOS
47+
48+
test_write_lines first third >expected &&
49+
set_fake_editor &&
50+
GIT_SEQUENCE_EDITOR="$EDITOR" FAKE_LINES="reword 1 squash 2 fixup 3" \
51+
GIT_EDITOR=./reword-editor.sh git rebase -i --root third &&
52+
test_cmp expected actual
53+
'
54+
3655
test_done

t/t7505-prepare-commit-msg-hook.sh

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -241,13 +241,7 @@ test_rebase () {
241241
git add b &&
242242
git rebase --continue
243243
) &&
244-
if test "$mode" = -p # reword amended after pick
245-
then
246-
n=18
247-
else
248-
n=17
249-
fi &&
250-
git log --pretty=%s -g -n$n HEAD@{1} >actual &&
244+
git log --pretty=%s -g -n18 HEAD@{1} >actual &&
251245
test_cmp "$TEST_DIRECTORY/t7505/expected-rebase${mode:--i}" actual
252246
'
253247
}

t/t7505/expected-rebase-i

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ message (no editor) [edit rebase-10]
77
message [fixup rebase-9]
88
message (no editor) [fixup rebase-8]
99
message (no editor) [squash rebase-7]
10-
message [reword rebase-6]
10+
HEAD [reword rebase-6]
11+
message (no editor) [reword rebase-6]
1112
message [squash rebase-5]
1213
message (no editor) [fixup rebase-4]
1314
message (no editor) [pick rebase-3]

0 commit comments

Comments
 (0)