DEV Community

Cover image for ⏪ 4 Ways to Undo a Git Commit - Amend vs Reset
Leonardo Montini for This is Learning

Posted on • Originally published at leonardomontini.dev

⏪ 4 Ways to Undo a Git Commit - Amend vs Reset

I'm quite sure all of these happened to you at least once:

  • You committed a change with the wrong message (typo, wrong tense, etc.)
  • You committed a change with the wrong files (something missing, too many files, etc.)
  • You committed a change too early (feature isn't complete yet)
  • You committed a change you didn't want to (wrong code, just needs to be deleted)

Sure, you can just add a new commit, but in the long run this will mess up your git history (unless you're closing PRs with squash).

If you want to keep your history clean and make your mistake disappear, let me show you 4 different ways to undo a commit. They're similar but not exactly the same, so you can apply the best one for your situation.

Bonus content: I'll also show you how to restore hard deleted changes. What does that mean? I'll get into that later.


As usual, there's a live demo waiting for you on my YouTube channel where I show you all the content of this article plus some extra words and scenarios. If you're just here for the commands, you can skip the video and go straight to the article.

Table of Contents

1. Amend no-edit

Let's start with the easiest situation, you already did a commit but you forgot to add some files.

Instead of creating an extra commit on top, you can run git commit --amend --no-edit. As a result, the last commit will be updated with the new files.



git add .
git commit --amend --no-edit


Enter fullscreen mode Exit fullscreen mode

No extra actions required, you're done!

2. Amend & Change Message

Similar situation to the previous one, but you also want to change the commit message.



git add .
git commit --amend


Enter fullscreen mode Exit fullscreen mode

This will open your default editor and you can change the commit message. Once you're done, save and close the editor. The commit will be updated with the new message.

Actually, git add . is not required if all you wanted to do is to change the commit message. You can just run git commit --amend.

3. Reset (soft)

This is the case where you want to undo a commit, but you want to keep the changes so that you can make a new commit at a later time.

git reset is kind of a time travel, really powerful but also dangerous. The most common use case is probably to undo a commit but keep in mind that you can do much more.

The full command we need is git reset --soft HEAD~1.

  • --soft means that the changes will be kept.
  • HEAD means the current commit you're on.
  • HEAD~1 means the last commit, but you can also use HEAD~2 to undo the last 2 commits.
  • A shortcut for HEAD is @, so @~1 would be the same as HEAD~1.

After running this command, you'll see that the last commit is gone but the files still have your changes applied.

You can now keep working and whenever you're ready you can do a new commit.

4. Reset (hard)

This is the case where you want to undo a commit and you don't want to keep the changes.

If you want to delete the changes, you need to add the --hard flag while running git reset.

Warning: this will also delete any uncommitted changes you have.

The full command we need this time is git reset --hard HEAD~1 and it will delete the last commit and the changes. Forever. Or is it?

Bonus: Restore Hard Deleted Changes

If you run git reset --hard HEAD~1 and you're not happy with the result, you can still restore the changes.

As we've just seen, git reset is our time travel machine, but we need to tell it where to go. In this case we entirely removed a commit and there's no trace in the git history, so we cannot say HEAD~number anymore.

Luckily, git keeps a log of all the commits that have been removed. You can see this log by running git reflog.

You want to look at a log like this one:



1b2c3d4 HEAD@{0}: reset: moving to HEAD~1


Enter fullscreen mode Exit fullscreen mode

This means that you were at commit 1b2c3d4 and you did a reset to the previous commit. You can now use this commit ID to restore the changes.



git reset --hard 1b2c3d4


Enter fullscreen mode Exit fullscreen mode

What are we doing here? We're telling git to go back to the commit 1b2c3d4 and to get rid of all the changes we did (in this case, the change was deleting the commit). Undoing a delete operation actually means restoring the deleted commit.

Conclusion

I hope you found this article useful and learned something new. If you have any questions or suggestions, feel free to leave a comment below.

I know there are at least a dozen different ways of moving around in git. I selected these 4 for simplicity but if you want to expand and add more in the comment section, let's do it!

Let me recommend once more to also watch the live demo and leave a like in this article (and to the video) to support my work. Thanks!


Thanks for reading this article, I hope you found it interesting!

I recently launched my Discord server to talk about Open Source and Web Development, feel free to join: https://discord.gg/bqwyEa6We6

Do you like my content? You might consider subscribing to my YouTube channel! It means a lot to me ❤️
You can find it here:
YouTube

Feel free to follow me to get notified when new articles are out ;)

Latest comments (19)

Collapse
 
uchitesting profile image
UchiTesting

Thank you for this article.
I learnt new things here.

I also use rebase and Squash in some cases.

I am working across several machines and I was trying to find a way to share a stash with remote. It is in order to continue working from home.

5 PM → Traffic Jam Fun Time
Likely 5:30/6PM - Home Switch Home... I meant PC.

I did look for an option on StackOverflow but did not find anything that is quick and simple.
When I realise it's 2 to 5 PM, all I'd want to do is prepare to leave.

Basically I just commit with any commit message.

Then I work on my content from another machine and I squash the missing changes.

It works perfectly fro my purpose.

Collapse
 
balastrong profile image
Leonardo Montini

That's a smart idea, thanks for sharing it! :D

Collapse
 
esteban_vc7 profile image
Esteban

Great article, but i think this can be avoid with conventional-commit?

Collapse
 
balastrong profile image
Leonardo Montini

Thanks for the comment :)

I'm not sure how... I mean, even with conventional-commit, if you forget to add a file or write a typo in the commit message, you might want to go back :)

Another example, if you did a commit but you later realize you didn't want to commit at all.

Or am I missing something here?

Collapse
 
esteban_vc7 profile image
Esteban

Conventional commit works to set a standard for the commits, but in the case that you are mentioning, it makes sense to use the amend, thanks for the response.

Collapse
 
jahidulsaeid profile image
Jahidul Islam (Saeid)

Very helpful article. Thanks for sharing

Collapse
 
balastrong profile image
Leonardo Montini

Thank you for the feedback! :)

I see articles on git are usually well appreciated, I'll probably write more :D

Collapse
 
krisztinasamu profile image
KrisztinaSamu

As a beginner web developer, I find this "git better" series very useful :)
But I would like to add an experience to point 2 of this article.

I didn't know about --amend.
It came at the right time, so I tried it.
I was stuck because when the editor opened I couldn't figure out how it worked.

I searched for amend online and found this solution:

git commit --amend -m "change commit text"

It worked easier for me.

Nevertheless, I look forward to more of your articles because they are very useful for me.

Thank you!

Collapse
 
balastrong profile image
Leonardo Montini

Thanks for the comment! :)

Regardless of the --amend flag, if you do not use -m, git will open your default text editor to insert a commit message.

So yeah, to make it in one step you can use both --amend and -m "message" and you can skip the step with the text editor.

You're right, I could have just used both in the same command to make it easier :)

Collapse
 
joshjm profile image
Josh

i like these kind of articles; tips that should be easy and daily practice; but is something lots of people might never know about due to other work arounds

Collapse
 
balastrong profile image
Leonardo Montini

Thank you for the feedback! :)

I'll probably do more articles like this one in the future then, I also like reading these kind of tips that are usually simple but not necessarily known by everyone :D

Collapse
 
stefjoosten profile image
Stef Joosten

This is great, Leonardo. Thanks a lot! I didn't know about amend nor about reversing a hard reset. Useful indeed :-) 👍🏻😃

You might add a warning for the less experienced: These actions are about changing your own history. Do NOT change the history after you have shared it (in a shared branch of a shared repo), to prevent your peers from getting some nasty conflicts.

You want to do this stuff primarily to get your own history cleaned up before sharing your commits with others.

Collapse
 
balastrong profile image
Leonardo Montini

Yeah that's true, I'll add a line about that. If commits have already been pushed, it's a whole another story :P

Collapse
 
miguelmj profile image
MiguelMJ

I didn't know about -amend. Now I wonder how many commits I could have prevented with this knowledge.

fragment of commit history

For example, I recently forgot to update the README of a project after adding a feature, so I did a second commit for that. From now on I'll be able to prevent this.

Thank you!

Collapse
 
djangolc profile image
Enrique Perez

Nice to know! i always use rebase for that case

Collapse
 
balastrong profile image
Leonardo Montini

Exactly that! It's the perfect usecase for amend :D

Enjoy ;)

Collapse
 
leonbeau profile image
Leon Huang

tks

Collapse
 
reacthunter0324 profile image
React Hunter

this helped me,
thanks

Collapse
 
balastrong profile image
Leonardo Montini

Thanks for sharing your feedback, it's great to hear someone found it helpful :D