Skip to content

Commit a47ba3c

Browse files
phillipwoodgitster
authored andcommitted
rebase -i: check for updated todo after squash and reword
While a rebase is stopped for the user to edit a commit message it can be convenient for them to also edit the todo list. The scripted version of rebase supported this but the C version does not. We already check to see if the todo list has been updated by an exec command so extend this to rewords and squashes. It only costs a single stat call to do this so it should not affect the speed of the rebase (especially as it has just stopped for the user to edit a message) Note that for squashes the editor may be opened on a different pick to the squash itself as we edit the message at the end of a chain fixups and squashes. Signed-off-by: Phillip Wood <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 450efe2 commit a47ba3c

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

sequencer.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,7 +1773,7 @@ static int do_pick_commit(struct repository *r,
17731773
enum todo_command command,
17741774
struct commit *commit,
17751775
struct replay_opts *opts,
1776-
int final_fixup)
1776+
int final_fixup, int *check_todo)
17771777
{
17781778
unsigned int flags = opts->edit ? EDIT_MSG : 0;
17791779
const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
@@ -1999,11 +1999,14 @@ static int do_pick_commit(struct repository *r,
19991999
res = do_commit(r, msg_file, author, opts, flags);
20002000
else
20012001
res = error(_("unable to parse commit author"));
2002-
if (!res && reword)
2002+
*check_todo = !!(flags & EDIT_MSG);
2003+
if (!res && reword) {
20032004
fast_forward_edit:
20042005
res = run_git_commit(r, NULL, opts, EDIT_MSG |
20052006
VERIFY_MSG | AMEND_MSG |
20062007
(flags & ALLOW_EMPTY));
2008+
*check_todo = 1;
2009+
}
20072010
}
20082011

20092012

@@ -3711,6 +3714,7 @@ static int pick_commits(struct repository *r,
37113714
while (todo_list->current < todo_list->nr) {
37123715
struct todo_item *item = todo_list->items + todo_list->current;
37133716
const char *arg = todo_item_get_arg(todo_list, item);
3717+
int check_todo = 0;
37143718

37153719
if (save_todo(todo_list, opts))
37163720
return -1;
@@ -3749,7 +3753,8 @@ static int pick_commits(struct repository *r,
37493753
command_to_string(item->command), NULL),
37503754
1);
37513755
res = do_pick_commit(r, item->command, item->commit,
3752-
opts, is_final_fixup(todo_list));
3756+
opts, is_final_fixup(todo_list),
3757+
&check_todo);
37533758
if (is_rebase_i(opts) && res < 0) {
37543759
/* Reschedule */
37553760
advise(_(rescheduled_advice),
@@ -3806,7 +3811,6 @@ static int pick_commits(struct repository *r,
38063811
} else if (item->command == TODO_EXEC) {
38073812
char *end_of_arg = (char *)(arg + item->arg_len);
38083813
int saved = *end_of_arg;
3809-
struct stat st;
38103814

38113815
if (!opts->verbose)
38123816
term_clear_line();
@@ -3817,17 +3821,8 @@ static int pick_commits(struct repository *r,
38173821
if (res) {
38183822
if (opts->reschedule_failed_exec)
38193823
reschedule = 1;
3820-
} else if (stat(get_todo_path(opts), &st))
3821-
res = error_errno(_("could not stat '%s'"),
3822-
get_todo_path(opts));
3823-
else if (match_stat_data(&todo_list->stat, &st)) {
3824-
/* Reread the todo file if it has changed. */
3825-
todo_list_release(todo_list);
3826-
if (read_populate_todo(r, todo_list, opts))
3827-
res = -1; /* message was printed */
3828-
/* `current` will be incremented below */
3829-
todo_list->current = -1;
38303824
}
3825+
check_todo = 1;
38313826
} else if (item->command == TODO_LABEL) {
38323827
if ((res = do_label(r, arg, item->arg_len)))
38333828
reschedule = 1;
@@ -3863,6 +3858,20 @@ static int pick_commits(struct repository *r,
38633858
item->commit,
38643859
arg, item->arg_len,
38653860
opts, res, 0);
3861+
} else if (check_todo && !res) {
3862+
struct stat st;
3863+
3864+
if (stat(get_todo_path(opts), &st)) {
3865+
res = error_errno(_("could not stat '%s'"),
3866+
get_todo_path(opts));
3867+
} else if (match_stat_data(&todo_list->stat, &st)) {
3868+
/* Reread the todo file if it has changed. */
3869+
todo_list_release(todo_list);
3870+
if (read_populate_todo(r, todo_list, opts))
3871+
res = -1; /* message was printed */
3872+
/* `current` will be incremented below */
3873+
todo_list->current = -1;
3874+
}
38663875
}
38673876

38683877
todo_list->current++;
@@ -4189,9 +4198,12 @@ static int single_pick(struct repository *r,
41894198
struct commit *cmit,
41904199
struct replay_opts *opts)
41914200
{
4201+
int check_todo;
4202+
41924203
setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
41934204
return do_pick_commit(r, opts->action == REPLAY_PICK ?
4194-
TODO_PICK : TODO_REVERT, cmit, opts, 0);
4205+
TODO_PICK : TODO_REVERT, cmit, opts, 0,
4206+
&check_todo);
41954207
}
41964208

41974209
int sequencer_pick_revisions(struct repository *r,

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

0 commit comments

Comments
 (0)