On 12/08/2019 18:50, SZEDER Gábor wrote:
When running interactive rebase to reword a commit message, I would expect that the commit whose message I'm rewording is checked out. This is not quite the case when rewording multiple subsequent commit messages. Let's start with four commits, and start an interactive rebase from the first commit: $ git log --oneline 5835aa1 (HEAD -> master) fourth 64ecc64 third d5fad83 second 384b86f first $ git rebase -i 384b86f Update the instruction sheet to edit the log messages of two subsequent commits: r d5fad83 second r 64ecc64 third pick 5835aa1 fourth Now, after the editor opens up the second commit's log message, start a new terminal and check where HEAD is pointing to: ~/tmp/reword (master|REBASE-i 1/3)$ head -n1 .git/COMMIT_EDITMSG second ~/tmp/reword (master|REBASE-i 1/3)$ git log --oneline -1 d5fad83 (HEAD) second So far so good.
Because the sequencer can fast-forwarded to second from first it does that and then run 'commit --amend' to do the reword.
Save the updated commit message, and after the editor opens up the third commit's log message, check again where HEAD is pointing to now: ~/tmp/reword (master +|REBASE-i 2/3)$ head -n1 .git/COMMIT_EDITMSG third ~/tmp/reword (master +|REBASE-i 2/3)$ git log --oneline -1 c3db735 (HEAD) second - updated
As second has been updated the sequencer cannot fast-forward to third so it cherry-picks third and then passes --edit when it runs 'git commit' to commit the cherry-pick. HEAD is updated once the reworded commit has been created.
I think the scripted rebase always ran cherry-pick and then ran 'commit --amend' afterwards if the commit was being reworded. The C implementation is more efficient as it avoids creating an redundant commit but has the side effect that HEAD is not updated before the reword which was surprising here.
I don't think I've ever looked at HEAD while rewording, my shell prompt gets the current pick from .git/rebase-merge/done so does not look at HEAD. While it might seem odd if the user looks at HEAD it's quite nice not to create a new commit only to amend it straight away when it's reworded. We have REBASE_HEAD which always points to the current pick - HEAD is also an unreliable indicator of the current pick if there are conflicts.
Best Wishes Phillip
As you can see, HEAD still points to the (now rewritten) second commit. It's only HEAD, though: notice the '+' in the git prompt, indicating that both the worktree and index are dirty. And indeed, they both already match the state of the currently reworded, i.e. third, commit: ~/tmp/reword (master +|REBASE-i 2/3)$ cat file third This is good, because even though HEAD has not been updated yet, it already allows users to take a look at the "big picture", i.e. actual file contents, in case the diff included in the commit message template doesn't show enough context. This behavior changed in commit 18633e1a22 (rebase -i: use the rebase--helper builtin, 2017-02-09); prior to that HEAD pointed to the third commit while editing its log message. It's important to reword subsequent commits. When rewording multiple, but non subsequent commits (e.g. reword, pick, reword in the instruction sheet), then HEAD is pointing to the right commits during both rewords.