41

I've made a commit, but now it is kind of difficult to see what I all changed. I can off course do a git diff, but I'd rather undo the last commit and keep all my changes in tact so that my IDE (PyCharm) simply shows me which files have been changed.

So is there a way to undo the last commit (really remove it) but still keep my changes in tact? All tips are welcome!

kramer65
  • 50,427
  • 120
  • 308
  • 488
  • 3
    Small point: you don't really ever _remove_ commits from the git history. Rather, you remove pointers (i.e. branches) to them. Eventually they will be garbage collected. If you mess something up and want to go back, you can find these dangling commits in the `reflog`. – Drew Noakes Mar 12 '14 at 15:17
  • I'd also recommend getting familiar with the built in git explorer in the JetBrains (PyCharm, etc) IDEs, as they will show you a changes you've made in a particular commit without having to "uncommit" your changes. This solution might work if you've just committed something, but imagine what would happen if you needed to go back to something committed last month! – technoplato Dec 27 '21 at 14:22

3 Answers3

35

I would leave off the --soft in the other two answers and go with a simple git reset @^ (or git reset HEAD^ in older versions of git), which will default to git reset --mixed @^. The difference is that a soft reset leaves the files staged for commit, which is not what it sounds like you want to do. If you really want to undo the commit, you should also probably unstage the changes, which is what the default does. I find this much more useful in the general case than a soft reset, which is probably why mixed is the default.

Gary Fixler
  • 5,632
  • 2
  • 23
  • 39
  • 1
    This should be the accepted answer-- simpler and exactly what the OP wanted. – chetstone Jul 31 '16 at 00:36
  • Could someone explain the `@^` in the above answer? I do this in windows and gitbash asks me `more?` whatever that means. – Post Impatica Aug 15 '22 at 12:18
  • Never mind, found the answer: In windows ^ is an escape, so you have to use 2 of them. Otherwise gitbash will ask you "more?". So: `git reset @^^` – Post Impatica Aug 15 '22 at 12:24
  • 1
    @PostImpatica using 2 `^` characters scares me, because the `^` characters stack, so `@^^` looks like it references 2 commits back. It sounds like `^^` evaluates in Windows down to a single `^`, but I'd probably still get in the habit of using `@~1` in that environment, which is equivalent to the normal, non-Windows `^`, just to keep from confusing myself. If you want to go back three, `@~3` more obviously means 3 back than `@^^^^^^` does! – Gary Fixler Aug 16 '22 at 20:51
29

As Peter says, I'd go with git reset --soft which should leave both your index, and working directory in tact.

In your case, if you want to go back 1 commit, you can use git reset --soft HEAD~ to point the branch at the parent commit of the current HEAD; your index and working directory will still contain your altered files.

A handy article about reset: http://git-scm.com/blog/2011/07/11/reset.html

Chris
  • 8,268
  • 3
  • 33
  • 46
  • 3
    Geez, man, you alone have solved the problem, THIS should be the accepted and most upvoted answer. Without `HEAD~` at the end `git reset --soft` did nothing. – Harry Jun 02 '20 at 20:56
  • Glad it helped =D – Chris Jun 02 '20 at 21:48
19

This sounds like a job for git reset --soft, whose help (git help reset) says this:

--soft
    Does not touch the index file nor the working tree at all
    (but resets the head to <commit>, just like all modes do).
    This leaves all your changed files "Changes to be
    committed", as git status would put it.

So the commit is undone, but the files still look the way they did before. Nothing is staged to the index.

Peter Westlake
  • 4,894
  • 1
  • 26
  • 35
  • I just ran `git reset --soft`, but when I run `git hist` I still see my last commit in there. So I guess this is not a solution to my problem. Any other ideas? – kramer65 Mar 12 '14 at 16:04
  • 2
    The commit is still in the history, but `HEAD` no longer points to it. It is a dangling reference, and will be garbage-collected. – Peter Westlake Mar 12 '14 at 16:16
  • 7
    As a tip; a finally succeeded by doing `git reset --soft `. Inserting the has finally solved it for me. Thanks anyway! – kramer65 Mar 13 '14 at 09:33