Skip to content

Commit befd4f6

Browse files
szedergitster
authored andcommitted
sequencer: don't re-read todo for revert and cherry-pick
When 'git revert' or 'git cherry-pick --edit' is invoked with multiple commits, then after editing the first commit message is finished both these commands should continue with processing the second commit and launch another editor for its commit message, assuming there are no conflicts, of course. Alas, this inadvertently changed with commit a47ba3c (rebase -i: check for updated todo after squash and reword, 2019-08-19): after editing the first commit message is finished, both 'git revert' and 'git cherry-pick --edit' exit with error, claiming that "nothing to commit, working tree clean". The reason for the changed behaviour is twofold: - Prior to a47ba3c the up-to-dateness of the todo list file was only checked after 'exec' instructions, and that commit moved those checks to the common code path. The intention was that this check should be performed after instructions spawning an editor ('squash' and 'reword') as well, so the ongoing 'rebase -i' notices when the user runs a 'git rebase --edit-todo' while squashing/rewording a commit message. However, as it happened that check is now performed even after 'revert' and 'pick' instructions when they involved editing the commit message. And 'revert' by default while 'pick' optionally (with 'git cherry-pick --edit') involves editing the commit message. - When invoking 'git revert' or 'git cherry-pick --edit' with multiple commits they don't read a todo list file but assemble the todo list in memory, thus the associated stat data used to check whether the file has been updated is all zeroed out initially. Then the sequencer writes all instructions (including the very first) to the todo file, executes the first 'revert/pick' instruction, and after the user finished editing the commit message the changes of a47ba3c kick in, and it checks whether the todo file has been modified. The initial all-zero stat data obviously differs from the todo file's current stat data, so the sequencer concludes that the file has been modified. Technically it is not wrong, of course, because the file just has been written indeed by the sequencer itself, though the file's contents still match what the sequencer was invoked with in the beginning. Consequently, after re-reading the todo file the sequencer executes the same first instruction _again_, thus ending up in that "nothing to commit" situation. The todo list was never meant to be edited during multi-commit 'git revert' or 'cherry-pick' operations, so perform that "has the todo file been modified" check only when the sequencer was invoked as part of an interactive rebase. Reported-by: Brian Norris <[email protected]> Signed-off-by: SZEDER Gábor <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b0a3186 commit befd4f6

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

sequencer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3791,7 +3791,7 @@ static int pick_commits(struct repository *r,
37913791
item->commit,
37923792
arg, item->arg_len,
37933793
opts, res, 0);
3794-
} else if (check_todo && !res) {
3794+
} else if (is_rebase_i(opts) && check_todo && !res) {
37953795
struct stat st;
37963796

37973797
if (stat(get_todo_path(opts), &st)) {

t/t3429-rebase-edit-todo.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,34 @@ test_expect_success 'todo is re-read after reword and squash' '
5252
test_cmp expected actual
5353
'
5454

55+
test_expect_success 're-reading todo doesnt interfere with revert --edit' '
56+
git reset --hard third &&
57+
58+
git revert --edit third second &&
59+
60+
cat >expect <<-\EOF &&
61+
Revert "second"
62+
Revert "third"
63+
third
64+
second
65+
first
66+
EOF
67+
git log --format="%s" >actual &&
68+
test_cmp expect actual
69+
'
70+
71+
test_expect_success 're-reading todo doesnt interfere with cherry-pick --edit' '
72+
git reset --hard first &&
73+
74+
git cherry-pick --edit second third &&
75+
76+
cat >expect <<-\EOF &&
77+
third
78+
second
79+
first
80+
EOF
81+
git log --format="%s" >actual &&
82+
test_cmp expect actual
83+
'
84+
5585
test_done

0 commit comments

Comments
 (0)