From: Phillip Wood Date: Mon, 12 Aug 2019 20:28:52 GMT Subject: Re: minor interactive rebase regression: HEAD points to wrong commit while rewording Message-ID: <2a7d69a9-cb3e-eb84-188f-5713876f6d78@gmail.com> In-Reply-To: <20190812175046.GM20404@szeder.dev> 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. > >