How to Change a Git Commit Message (Last, Older, or Already Pushed)

Tested on RHEL 10.2 (Coughlan)
Package git 2.52.0
Applies to Any host with Git installed
Privilege Normal user
Scope Change the message on the most recent commit with git commit --amend --only, an older commit, or several commits in one pass, including commits already pushed to a remote. Covers why the commit hash changes, safe force pushing, and undoing a rewrite. Does not cover adding forgotten files or changing the author on a commit.
Related guides git commit --amend examples
Git rebase tutorial
Git reflog tutorial
Git push force examples
Git commit message guide

Almost everyone types a commit message they regret. You misspell a word, you write "fix bug" at midnight, or you paste something that was never meant to be public. Git lets you rewrite that message with git commit --amend --only, which changes only the message — the files saved in that commit stay the same.

Git does not edit the existing commit. It creates a new version of that commit with the new message. Because it is technically a new commit, its commit hash changes. That single fact explains every warning in this guide.


Which fix do you need?

The right command depends on two questions only: which commit has the bad message, and whether anyone else can already see it.

Your situation What to run What to expect
Bad message on the newest commit, not pushed yet git commit --amend --only Safe — only local history changes
Bad message on the newest commit, already pushed git commit --amend --only, then git push --force-with-lease Requires force push
Bad message a few commits back, not pushed git rebase -i and reword Safe if nobody else uses this history
Several bad messages at once One git rebase -i with several reword lines Safe if nobody else uses this history
Bad message on a branch your team shares Usually nothing — leave it Avoid on shared branches

If you are unsure whether the commit was already pushed, run git fetch first and then git status. If Git says your branch is ahead of its remote branch, those commits have not been pushed yet.


Change the last commit message

git commit --amend --only replaces only the latest commit message. The files stored in that commit remain unchanged. The commit hash will change, so if the old commit was already pushed, you will later need to update the remote history.

Before running it, look at what is actually on top of your branch, because amend only ever touches the newest commit:

bash
git log --oneline -1
output
7f3677f updat login validaton

Two typos, and 7f3677f is the commit's short hash. Keep an eye on that hash, because it will not survive the fix.

The --only flag is important here because it prevents changes you previously staged with git add from accidentally being included in the amended commit. Plain --amend without --only can pull those staged changes into the commit you are rewriting.

Replace the message with:

bash
git commit --amend --only -m "Update login validation to reject empty passwords"
output
[main 2e67285] Update login validation to reject empty passwords
 Date: Thu Aug 20 23:10:16 2026 +0530
 1 file changed, 2 insertions(+)
 create mode 100644 login.py

Notice two things in that output. The hash is now 2e67285 rather than 7f3677f, and the 1 file changed line matches the original commit exactly. Git rebuilt the commit with a new message, and the files saved in that commit stayed the same.

Confirm the branch reads the way you wanted:

bash
git log --oneline
output
2e67285 Update login validation to reject empty passwords
b4ad3a8 Fix bug
1dada68 Add config loader
36b9fca Add README with setup steps

The typo is gone, and the three older commits kept their original hashes. Only the commit you amended was rebuilt.

Write a longer message in your editor

A one-line -m message is fine for a typo fix, but real commit messages often need a short subject and an explanatory paragraph. Leave off -m and Git opens your editor with the current message already filled in:

bash
git commit --amend --only

Save and close the editor to apply the new message.

Adding a forgotten file or changing the commit author uses plain --amend with different flags, and those cases are covered in git commit --amend examples.


Why the commit hash changes

A Git commit ID is calculated from the commit's contents and metadata, including its message and parent. Changing the message therefore creates a different commit ID.

For the latest local commit, this is normally harmless. For an older commit, the commits after it also receive new hashes. If those commits were already pushed, you will need to force-push the rewritten history.

If the old commit was already pushed, the remote branch still has the old hash while your local branch has the new one. A normal push is rejected because those two histories no longer line up.

Behind the scenes, Git also stores a snapshot of your files inside each commit. With --only, that snapshot stays the same even though the commit ID changes. The old commit may still appear in the reflog for a while, which is why recovery is possible after a mistake.


Change a commit message you already pushed

git commit --amend --only changes only the message on the latest commit. The files in that commit stay the same, but the commit hash changes. After that rewrite, a normal push no longer works because the remote still has the old commit ID.

Amend locally exactly as in the previous section:

bash
git commit --amend --only -m "Reject empty passwords in login validation"

After you rewrite a commit that already exists on the remote, a normal push is rejected as non-fast-forward. Do not use git pull simply to fix that rejection; the intention here is to replace the remote commit with the rewritten history, not reconcile the two histories.

Only do this if the branch is yours to rewrite. If other people are working from the same branch, changing its existing history can make their local history conflict with the remote branch.

Push the replacement history with --force-with-lease rather than a plain --force:

bash
git push --force-with-lease
output
To gitlab.devlab.io:stackforge/deploy-kit.git
 + d5ff8e6...f5cd7e3 feature/login-validation -> feature/login-validation (forced update)

The difference between the two force options matters:

  • A plain --force can move the remote branch away from a teammate's commit and remove it from the branch's visible history.
  • --force-with-lease adds a safety check. If the remote branch changed since the version you last saw, Git normally refuses to overwrite it.

There is no situation where --force is safer, so make --force-with-lease your habit. Git push force examples goes deeper into both.

WARNING
If the bad message contained a password or token, rotate the credential — a force push alone does not remove the original commit from hosting platforms that keep objects reachable by hash.

Change an older commit message

git commit --amend --only only works on the newest commit. To rename an older commit, use interactive rebase. Git shows a list of recent commits, and you mark the one whose message you want to change with reword.

Look at what you are working with first:

bash
git log --oneline
output
2e67285 Update login validation to reject empty passwords
b4ad3a8 Fix bug
1dada68 Add config loader
36b9fca Add README with setup steps

"Fix bug" is the problem, and it sits two commits back. git rebase -i HEAD~3 opens the last three commits for editing, which includes b4ad3a8.

Running that command changes nothing immediately. Git first opens a to-do list in your editor with one line per commit and a reference of every available action underneath:

text
pick 1dada68 Add config loader
pick b4ad3a8 Fix bug
pick 2e67285 Update login validation to reject empty passwords

# Rebase 36b9fca..2e67285 onto 36b9fca (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit

The oldest commit is at the top, which is the reverse of git log and catches people out constantly. Every line starts as pick, meaning Git will keep that commit as it is unless you change the action.

To fix a message, change pick to reword on that one line and leave the others alone:

text
pick 1dada68 Add config loader
reword b4ad3a8 Fix bug
pick 2e67285 Update login validation to reject empty passwords
  • Change pick to reword on the commit line you want to rename.
  • Do not delete commit lines you did not mean to remove.
  • Save and close the to-do list, then enter the new message when Git prompts you.
  • If something goes wrong, run git rebase --abort to return to where you started.

Mark the Fix bug line as reword, save the to-do list, then type the replacement message in the second editor Git opens for you:

bash
git rebase -i HEAD~3
output
Rebasing (2/3)[detached HEAD 97a8772] Fix timeout value not being read from config
 Date: Thu Aug 20 23:10:16 2026 +0530
 1 file changed, 1 insertion(+)
Rebasing (3/3)Successfully rebased and updated refs/heads/main.

The counter shows Git working through all three commits even though you only edited one. Check the result:

bash
git log --oneline
output
d5ff8e6 Update login validation to reject empty passwords
97a8772 Fix timeout value not being read from config
1dada68 Add config loader
36b9fca Add README with setup steps

"Fix bug" now reads properly. Look carefully at the commit above it, though: it was 2e67285 before the rebase and it is d5ff8e6 now, even though you never touched its message.

The commit after "Fix bug" also gets a new hash because its parent commit changed. Git therefore has to recreate every later commit up to the current branch tip. Your files may still be identical, but Git now sees those as different commits. This is why changing an older commit that was already pushed requires rewriting more remote history.

If the rebase stops on a conflict or you simply change your mind, git rebase --abort returns the branch to exactly where it started. More rebase mechanics live in the Git rebase tutorial.


Change several commit messages at once

You do not need one rebase per message. Mark as many lines as you like in the same to-do list.

Here are three commits, two of which say nothing useful:

bash
git log --oneline -3
output
0515c31 Add cache warmup task
ce2892d stuff
a2c2886 wip

One interactive rebase covers all three. In its to-do list, set reword on both weak lines and leave the good one as pick:

text
reword a2c2886 wip
reword ce2892d stuff
pick 0515c31 Add cache warmup task

Git walks the list from top to bottom, opening an editor once per reworded commit — so expect two editor sessions here, not one. Each opens with that commit's old message, and the rebase moves on as you save each one:

bash
git rebase -i HEAD~3
output
Rebasing (1/3)[detached HEAD c2c8579] Add request retry helper
 Date: Thu Aug 20 23:11:53 2026 +0530
 1 file changed, 1 insertion(+)
 create mode 100644 a.txt
Rebasing (2/3)[detached HEAD 8f9bb2a] Add response cache layer
 Date: Thu Aug 20 23:11:53 2026 +0530
 1 file changed, 1 insertion(+)
 create mode 100644 b.txt
Rebasing (3/3)Successfully rebased and updated refs/heads/multi-demo.

Both replacements are reported, one per reworded commit. The history is now readable:

bash
git log --oneline -4
output
569e5d9 Add cache warmup task
8f9bb2a Add response cache layer
c2c8579 Add request retry helper
d5ff8e6 Update login validation to reject empty passwords

This is the usual tidy-up before opening a pull request: one rebase, every vague message replaced, reviewers get a history they can follow.


Undo a message change

Because Git does not delete the old commit immediately, a rewrite you regret is recoverable. Say you amend and immediately realise the new message is worse:

bash
git log --oneline -1
output
5e9a37e OOPS wrong message entirely

The commit you want back is not in git log any more, because your branch no longer points at it. It is still listed in the reflog, which records recent positions your branch has been in:

bash
git reflog -3
output
5e9a37e HEAD@{0}: commit (amend): OOPS wrong message entirely
569e5d9 HEAD@{1}: rebase (finish): returning to refs/heads/multi-demo
8f9bb2a HEAD@{2}: rebase (pick): Add response cache layer

Read this as a history of where your branch has pointed. Find the entry from immediately before the bad amend — here HEAD@{1} at 569e5d9 with the message you wanted — not a fixed offset like HEAD@{1} in every situation.

This moves the branch back to the selected commit without discarding your current working-directory or staged changes:

bash
git reset --soft 'HEAD@{1}'

You can also reset directly to the hash if that is clearer:

bash
git reset --soft 569e5d9
output
HEAD is now at 569e5d9 Add cache warmup task

The branch now points back to the original commit. The incorrect amended commit is no longer part of the branch history, although Git may keep it temporarily and it can still appear in the reflog. Reflog expiration is configurable; by default Git expires unreachable reflog entries after 30 days and other entries after 90 days. Git reflog tutorial covers recovering from harder situations, and Git reset examples explains the difference between --soft, --mixed, and --hard.


When you should leave the message alone

Every technique above rewrites history, which is harmless on your own branch and disruptive on a shared one. Rewriting a branch your teammates have already pulled means their copy no longer matches the server, and each of them has to sort it out by hand.

Leave the message as it is when:

  • the commit is on a long-lived branch such as main, master, or develop
  • the branch is protected by your host and rejects force pushes anyway
  • someone else has already built work on top of those commits
  • the message is merely imperfect rather than wrong or leaking something

Rewrite it when the branch is yours alone, when it is a feature branch nobody has pulled, or when the message contains something that genuinely must not stay.

One clarification, because it is a common misunderstanding: git revert does not fix a message. It adds a new commit that undoes the code changes, and the original commit keeps its bad message in the history. Reverting a commit because you disliked its wording removes working code and fixes nothing.

If a message on a shared branch is truly wrong, the low-drama option is to explain the correction in the pull request or in a later commit message, and to coordinate with your team before rewriting anything.


Troubleshooting

Symptom Likely cause Fix
! [rejected] ... (non-fast-forward) on push You rewrote a commit the remote already has Push the replacement with git push --force-with-lease; do not use git pull simply to clear the rejection
--force-with-lease itself is rejected Someone pushed to the branch since your last fetch Fetch and inspect the new remote commits. Integrate or coordinate those changes before deciding whether the remote history should still be replaced
Editor opens with # comment lines and nothing else useful Normal to-do list; comments explain the actions Edit only the pick words above the comment block
Rebase stopped and the shell prompt says rebasing Git paused for a reword or a conflict Finish the message and git rebase --continue, or git rebase --abort
Commits after the one you edited have new hashes Expected — a new parent changes every later commit Nothing to fix; force push the branch if it was already pushed
Amended the wrong commit Amend hit the newest commit, not the one you meant Run git reflog, identify the entry before the rewrite, then git reset --soft to that entry or hash
Wanted to edit an older commit but amend was used --amend only ever touches the newest commit Reset back using the correct reflog entry, then use git rebase -i
git log no longer shows a commit you need Nothing references it after the rewrite Find it in git reflog and reset or cherry-pick it back

References


Summary

Use git commit --amend --only for the newest commit, git rebase -i with reword for older or multiple messages, and git push --force-with-lease when the rewritten commit was already on the remote. If a rewrite goes wrong, recover through git reflog by resetting to the entry from before the change.


Frequently Asked Questions

1. How do I change the last commit message in Git?

Run git commit --amend --only -m "New message". This changes only the commit message; the files saved in that commit stay the same.

2. How do I change an older commit message in Git?

Start an interactive rebase that reaches back far enough to include the commit, for example git rebase -i HEAD~3, change the word pick to reword on that commit line, then save and close. Git stops and lets you type the new message.

3. Can I change a commit message after pushing to remote?

Yes, but you have to force push afterwards because the rewritten commit has a different hash than the one on the server. Run git commit --amend --only locally, then git push --force-with-lease. Only do this on a branch nobody else is working on.

4. Why does the commit hash change when I only edit the message?

A Git commit ID is calculated from the commit contents and metadata, including its message. Changing the message creates a different commit ID, so Git stores a new commit instead of editing the old one in place.

5. Does changing a commit message affect my code?

Not when you use git commit --amend --only or reword during interactive rebase. Those paths change only the message; the files saved in the commit stay the same. Plain git commit --amend without --only can also include changes you previously staged with git add.

6. How do I undo a commit message change?

Run git reflog, find the entry from before the rewrite, and run git reset --soft to that reflog entry or commit hash. Reflog expiration is configurable; by default Git expires unreachable reflog entries after 30 days and other entries after 90 days.

7. Is it safe to change commit messages in Git?

It is completely safe for commits that exist only on your machine. It becomes risky once the commits are pushed to a branch other people pull from, because everyone who already has the old commits has to recover manually.

8. What is the difference between git commit --amend and git rebase for messages?

git commit --amend --only changes only the most recent commit message without changing the files in that commit. Interactive rebase with reword can fix older or multiple messages, at the cost of giving new commit IDs to every commit that comes after the one you edit.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)