Sunday, July 15, 2007

'git revert' Is Not Equivalent To 'svn revert'

I just learned that if you have some changes in your working tree that you want to get rid of, you don't type 'git revert' like you might guess. No, that's what cvs, subversion, mercurial, and bazaar (to name a few) use revert to mean, but not git. With git, revert is used to undo actual commits. Thankfully, you can undo your revert with another 'git revert', I just learned. So let me repeat to be clear, if you have changes to your working files that you want to abandon, DO NOT do this:

git revert HEAD

That will undo your last commit. Do this instead:

git reset --hard HEAD

I'm glad I have that straightened out now. I'm wondering if /etc was really a good place for me to start out playing with git.

UPDATE: Nearly two years later and I'm still getting comments on this. I'm glad I've been able to help people out this way. The discussion in the comments is good, and one thing I'd like to point out is that I now always use and recommend:

git checkout filename
(as recommended by Anonymous and others below) instead of git reset. I think the git stash trick from Nicolas is pretty cool too.

24 comments:

Anonymous said...

A command I like better for this purpose is "git checkout". You can get rid of all your changes by using "git checkout -f", or you can get rid of the changes for a subset of the changed files by using "get checkout FILENAME" (for one or more names).

I also note that CVS doesn't have a revert command. Getting rid of some changes was accomplished by removing the file ("rm FILE") and then updating it ("cvs up FILE").

Meitar said...

I'm new to git, so I'm still learning, but I'm confused as to how to get this svn revert-like behavior from git.

When I do git checkout -f file I get this message I can't understand:

git checkout: updating paths is incompatible with switching branches/forcing
Did you intend to checkout 'file' which can not be resolved as commit?

What does that mean? I've resigned to doing rm file; git checkout file in the mean time, but this seems like a kludge since the git-checkout manpage clearly states the the -f option "is used to throw away local changes."

Thanks.

arelcordero said...
This comment has been removed by the author.
arelcordero said...

I don't think you want to use the -f option with checkout. The man page actually says to omit it or it will complain, which it does.

(Also, you do not need to remove a file first before using checkout)

When [paths] are given, this command does not switch branches. It updates the named paths in the working tree from the index file (i.e. it runs git-checkout-index -f -u), or from a named commit. In this case, the -f and -b options are meaningless and giving either of them results in an error.

Khumba said...

I'm learning git, and a more manual way I've found to revert an individual file or a set of files is "git diff -R files | patch".

The -R creates a reverse patch, if you want to see what would be undone or keep track of what you undid (without the "| patch").

darcy said...

Thanks for the post!

Nicolas Marchildon said...

git stash
git stash drop

mae said...

ahhh thank you for this. I knew I was doing something wrong,

Anonymous said...

You can use de follow to revert an archive like revert of the SVN.
git checkout 4524b -- sample.txt

*The part of 4524b, is the version of the file which the content you want

autor said...

No, no! Don't use "git reset --hard HEAD", it's very dangerous! Use, instead, the command "git checkout <path-to-undo>"

It's better.

Sheldon Hearn said...

If you're more interested in versioning /etc (or your entire fileystem) than you are in playing with git, be sure to check out fsvs.

Anonymous said...

Thanks for this. I was caught in this mistake too.

yap said...

I just got hit with this as well (two years later). It's like a wonky traffic pattern--you may have learned it two years ago, but there's always someone new getting snarled in that forced-right-turn lane. Anyhow, thanks for the post, saved me a real headache!

Mickael said...

Thanks !

Dustin Davis said...

Just what I was looking for! Thanks. When I first started using SVN I was confused as to the revert function. It seemed to me that it should revert a commit. So I'm liking git already :)

SpamKids said...

I use "git revert" as "svn revert" for previous commits, it works fine, I didn't understand why you said is not the same.

Jon said...

Thanks this cleared up my confusion on this one perfectly - I'm liking git a lot but I sometimes am pulling my hair out at it's non-standard methods.

Bryce Verdier said...

Thanks for putting this up, good to know as I learn more & more about git.

Antoine Borg said...

I really hate git. Why can't I just issue one single command that will nuke every change I have locally and will re-download things from the server? That is _precisely_ what I want to do.

git revert, git reset reset --hard with or without its head on all _do not_ do this.

So what command do I need for this?

Antoine

Matthew said...

@Antoine Borg:

Sounds like a partial misunderstanding of git. The concept of a 'central server' is very very vague in git. You can use it that way, but every 'working copy' is a full repository, and could be used as a new source.

If you really want to blow away everything you've done locally, and just get what the 'server' has, delete your directory, and run another 'git clone' of the server. Otherwise, a 'git reset --hard' takes you back to the last commit on your local setup. Or, your can pick any commit in your history, and create a new branch from there, using 'git checkout -b '

JP said...

I recommend to use gitx - then use "Discard Changes" option. No misunderstandings or typos.

Anonymous said...

git checkout .

http://stackoverflow.com/questions/1146973/how-to-revert-all-local-changes-in-a-git-managed-project-to-previous-state

Anonymous said...

Thanks for the post. Must keep it up there on the top of Google search

Anonymous said...

i was going crazy trying to figure this out; thanks