212

I was trying to edit an old commit message as explained here.

The thing is that now, when I try to run rebase -i HEAD~5 it says interactive rebase already started.

So then I try: git rebase --continue but got this error:

error: Ref refs/heads/master is at 7c1645b447a8ea86ee143dd08400710c419b945b but expected c7577b53d05c91026b9906b6d29c1cf44117d6ba
fatal: Cannot lock the ref 'refs/heads/master'.

Any ideas?

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
  • 4
    Users are told to add contents for question here, and not in links. One of the reasons is that those links become invalid sooner or later. The link https://schacon.github.com/history.html no longer works. – U. Windl Jun 25 '21 at 17:02
  • The link does work (again?), though. – questionto42 Apr 07 '22 at 07:13

6 Answers6

178

It says:

When you save and exit the editor, it will rewind you back to that last commit in that list and drop you on the command line with the following message:

$ git rebase -i HEAD~3
Stopped at 7482e0d... updated the gemspec to hopefully work better
You can amend the commit now, with

It does not mean:

type again git rebase -i HEAD~3

Try to not typing git rebase -i HEAD~3 when exiting the editor, and it should work fine.
(otherwise, in your particular situation, a git rebase -i --abort might be needed to reset everything and allow you to try again)


As Dave Vogt mentions in the comments, git rebase --continue is for going to the next task in the rebasing process, after you've amended the first commit.

Also, Gregg Lind mentions in his answer the reword command of git rebase:

By replacing the command "pick" with the command "edit", you can tell git rebase to stop after applying that commit, so that you can edit the files and/or the commit message, amend the commit, and continue rebasing.

If you just want to edit the commit message for a commit, replace the command "pick" with the command "reword", since Git1.6.6 (January 2010).

It does the same thing ‘edit’ does during an interactive rebase, except it only lets you edit the commit message without returning control to the shell. This is extremely useful.
Currently if you want to clean up your commit messages you have to:

$ git rebase -i next

Then set all the commits to ‘edit’. Then on each one:

# Change the message in your editor.
$ git commit --amend
$ git rebase --continue

Using ‘reword’ instead of ‘edit’ lets you skip the git-commit and git-rebase calls.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 2
    Also, `git rebase --continue` goes to the next task in the rebasing process, after you've amended the first commit. – Dave Vogt Aug 23 '10 at 13:42
  • 1
    Adding the [link](https://help.github.com/articles/changing-a-commit-message/) to github wiki article for changing a commit message – Joy Nov 18 '17 at 18:49
  • this does not seem to work if my commits since the one in question all were done with `--allow-empty` and have no actual diff. Rebase just says "Nothing to do" – lucidbrot Jan 11 '21 at 08:43
  • 1
    @lucidbrot What version of Git are you using? `git rebase -i` can retain empty commits since Git 2.26 (Q1 2020): https://stackoverflow.com/a/60532362/6309 – VonC Jan 11 '21 at 09:53
  • @VonC Interesting, thanks! I'm on `2.17`. Didn't realize it was out of date - I've got it from the ubuntu apt – lucidbrot Jan 11 '21 at 11:50
  • How can I keep commit date same? – Arpit Bhalla Jan 27 '22 at 06:55
  • `git checkout main` --> `git pull` --> `git rebase -i [hash of the 5th last commit]` or `git rebase HEAD~4` both show the last 4 commits in the interactive editor --> change first line (4th last commit) from "pick" to "reword" --> in vim: `wq` --> edit the commit message --> in vim `wq` --> I get back to the main branch. Now, I do not see the changed commit message online, but when I rebase again, the changes are done. Being in "main" again, should I then `git push -f`? Is it now needed to force push when checked out in "main" to see the changed old commit message online? – questionto42 Apr 06 '22 at 18:55
  • @questionto42standswithUkraine Any rebase would change the branch history indeed, so a `git push --force` is needed. – VonC Apr 06 '22 at 23:28
  • `git push --force-with-lease` gives: `Enumerating objects: 23, done. Counting objects: 100% (23/23), done. ... remote: GitLab: You are not allowed to force push code to a protected branch on this project.` This is what I had thought. I cannot just force push to the main. I guess I need to make a new branch only to force push to it even though that is only for refreshing the old commit message. – questionto42 Apr 06 '22 at 23:35
  • Probably, as main is protected by default – VonC Apr 07 '22 at 00:07
  • I found out what was the problem in my case. My branch was already merged. That is why I could not and should not change anything in the past anymore. I therefore put the non-truncated commit message to the documentation and leave it as it is. – questionto42 Apr 07 '22 at 16:28
  • @questionto42standswithUkraine Good catch. That would explain it. – VonC Apr 07 '22 at 20:11
169

As Gregg Lind suggested, you can use reword to be prompted to only change the commit message (and leave the commit intact otherwise):

git rebase -i HEAD~n

Here, n is the list of last n commits.

For example, if you use git rebase -i HEAD~4, you may see something like this:

pick e459d80 Do xyz
pick 0459045 Do something
pick 90fdeab Do something else
pick facecaf Do abc

Now replace pick with reword for the commits you want to edit the messages of:

pick e459d80 Do xyz
reword 0459045 Do something
reword 90fdeab Do something else
pick facecaf Do abc

Exit the editor after saving the file, and next you will be prompted to edit the messages for the commits you had marked reword, in one file per message. Note that it would've been much simpler to just edit the commit messages when you replaced pick with reword, but doing that has no effect.

Learn more on GitHub's page for Changing a commit message.

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Punit Vara
  • 3,744
  • 1
  • 16
  • 30
  • I did that, and then commits from other branches show up in my branch – Reza Jul 20 '20 at 19:18
  • @Reza you might have messed up somthing. Try this in some other repo. This solution works perfectly – Punit Vara Jul 22 '20 at 03:01
  • What is confusing a bit is the fact that git says "detached HEAD ..." after saving the modified commit message (using `reword`), but then a `git rebase --continue` triggers a "fatal: No rebase in progress?". Maybe point that out in the answer, too. Seen in git 2.26.2. – U. Windl Jun 25 '21 at 17:17
  • Perfect answer, especially because of the example and link. – bit Jun 06 '23 at 12:06
69

FWIW, git rebase interactive now has a reword option, which makes this much less painful!

Paolo
  • 20,112
  • 21
  • 72
  • 113
Gregg Lind
  • 20,690
  • 15
  • 67
  • 81
  • 6
    When using `reword`, why doesn't git simply let you edit the commit messages in that file with the list of commits? Instead it will launch the editor with one commit message file per `reword` line. This is just unnecessary. Even if other actions than `pick` or `reword` require launching external commands, `reword` would not necessitate that. – Dan Dascalescu Feb 24 '19 at 03:10
  • 1
    Could it be you are confusing one-line commit messages with full commit messages (You see the commit message title (summary) only when rebasing)? – U. Windl Jun 25 '21 at 17:20
  • @DanDascalescu, that would be convenient, but I can see internal reasons for Git to not support that. For instance, commit messages can be longer than just the summary line at the top. And perhaps because Git supports all sorts of other things in interactive rebase, and adding support for this would be a one-off. I'm not a `rebase -i` expert though; I barely use it. So just some thoughts. – Antrikshy Sep 05 '22 at 21:45
  • There is one good reason. As the accepted answer quotes "it will rewind you back to that last commit", eg change HEAD so that from another session, you can use simple forms of git commands like `git show` or look at the files as they were at that commit. Better to concoct a cleaner log message. – chipfall Feb 27 '23 at 17:17
23

Just wanted to provide a different option for this. In my case, I usually work on my individual branches then merge to master, and the individual commits I do to my local are not that important.

Due to a git hook that checks for the appropriate ticket number on Jira but was case sensitive, I was prevented from pushing my code. Also, the commit was done long ago and I didn't want to count how many commits to go back on the rebase.

So what I did was to create a new branch from latest master and squash all commits from problem branch into a single commit on new branch. It was easier for me and I think it's good idea to have it here as future reference.

From latest master:

git checkout -b new-branch

Then

git merge --squash problem-branch
git commit -m "new message" 

Referece: https://github.com/rotati/wiki/wiki/Git:-Combine-all-messy-commits-into-one-commit-before-merging-to-Master-branch

piyush
  • 868
  • 13
  • 29
silvio
  • 5,651
  • 2
  • 17
  • 14
  • 1
    Your answer really saved my day :). I was struggling with `rebase -i` for like about 2 hours and no success. My commit was behind 18 commits, so you can imagine. This was the simpler and handy way I could found without needing to use rebase. Thanks friend! – Carlos Parra May 25 '19 at 16:14
  • I'm unsure what happens to the commit history when merging all commits into one. Maybe explain in your answer, maybe showing an example. I tried to understand the manual page's description of the `--squash` option, but I failed to understand what it actually does. – U. Windl Jun 25 '21 at 17:25
  • As I mentioned, for this work-around, you should not be worried about the individual commits, as you will lose track of it and make it as one with a new message. Sorry for the delay to respond – silvio Oct 16 '21 at 22:54
  • That's helpful and really easy, but comes with the downside, there are now `n` number of files in a single commit, and also lost the entire commit history. – sharad_kalya Dec 23 '21 at 22:15
  • Yes, on the first 2 paragraphs I explained that I had a very specific use case where I was working on a branch alone for a long time and didnt need the history. Many files changed wasnt a problem as well. cheers – silvio Mar 29 '22 at 17:48
18

To change a commit message anywhere in history:

1- git rebase -i <commit_sha> , <commit_sha> is the SHA one commit before the commit to be changed (here: eb232eb6b): enter image description here

2- change pick (default) to reword in the first line (do not edit message itself)

3- save and exit

4- next you'll see the editor again with the old commit message line alone, so edit it and then save and exit enter image description here

and that's it, now the history is modified and a git push --force-with-lease will replace on remote

mirekphd
  • 4,799
  • 3
  • 38
  • 59
Erfan Azary
  • 488
  • 6
  • 11
11

Here's a very nice Gist that covers all the possible cases: https://gist.github.com/nepsilon/156387acf9e1e72d48fa35c4fabef0b4

Overview:

git rebase -i HEAD~X
# X is the number of commits to go back
# Move to the line of your commit, change pick into edit,
# then change your commit message:
git commit --amend
# Finish the rebase with:
git rebase --continue
Mahmoud Zalt
  • 30,478
  • 7
  • 87
  • 83