git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Git rescue mission

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Feb 8, 2007, 17:27 UTC
Message-ID
<Pine.LNX.4.64.0702080858430.8424@woody.linux-foundation.org>
In-Reply-To
<17866.27739.701406.722074@lisa.zopyra.com>
On Wed, 7 Feb 2007, Bill Lear wrote:
Show 5 quoted lines
> 
> I have a public bare repo on my machine that I have cloned to make a
> private repo.  I just want to sync my branches on my public and
> private repos.  I do not want to merge across branches, I just want to
> "sync".

Ok, others already replied, but here's a few rules to ease your mind in general:

 - First off: you can always _trivially_ get back to whatever state you 
   had before, as long as you committed it, and didn't have any dirty 
   state (uncommitted patches) in your working tree.

This is something that it's worth repeating, and even perhaps experimenting with to get really comfortable with. Why? Because once you learn to get back to any random state you had before, and once you are comfortable with that, you suddenly lose the fear of experimenting. Whatever you screw up, if you're confident you can get back, who cares?

So the "get back from a mistake" should probably be at the very front of our manuals and tutorials. I don't think it currently is, but it's actually not that hard. There's just one command to remember: "git reset", and the only issue you might ever have with it is:

 - make sure you're on the right branch first! If the problem you had is 
   that you're on the wrong branch, switch branches first! Don't try to 
   make the wrong branch "look right". But once you know you're on the 
   right branch, you know that "git reset" is your friend to getting it 
   anywhere you want.
 - do you want to throw away all your working tree changes (and if 
   you screwed up some git operation, the answer is usually "Yes!"). If 
   so, add the "--hard" flag. It's not on by default, exactly because it 
   *will* throw away all state in your tracked working tree, and reset it 
   to whatever you want to go back to.
 - exactly *what* do you want to go back to? The default is to go back to 
   the state at the last successful commit, but sometimes what you screwed 
   up was exactly the last commit (eg an unintentional "pull" that 
   actually succeeded), and then you need to tell it *what* to reset to.

That's really all there is to it. It's really simple, although especially the second point can take some practice to get right.

So NORMALLY, if you did something bad - say, you edited a file, and just realized that the whole edit was just crap, and you want to start over - you just do a simple

	git reset --hard
and it will just reset all your git state to the last commit you did. 

This is what you'd do in this case, when you had a "git pull" that simply *failed* due to conflicts, and you realize that you didn't do that merge at all.

However, what happens if you actually do a "git pull" that doesn't have any conflicts (or at least they merge fine), so the pull actually *succeeds*, but you realize that wasn't what you wanted to do at all?

In that case, you need to say
	git reset --hard <point-you-want-to-go-back-to>

to just reset to the previous state. Now we get to that "how do I figure out what state that was?" part of the question, and usually it's trivial to answer.

For example, a command like "git pull" will leave a special magic name around to tell you what the original HEAD was before the pull, and that magic name is (surprise surprise) called ORIG_HEAD. So if the pull succeeded, but you realized it was an error (perhaps you had even intended to do it, but once you pulled, you just saw that what you pulled was crap, so you decide that you didn't really want to do it after all), you can just do

	git reset --hard ORIG_HEAD
and you're back to where you were _before_ the pull.

It really is that easy. And once you get comfortable with it, and you really know deep down how easy it is, that should just relax you a lot. When you go "AIEE! I made a horrible mistake!" you should just laugh, and say "and I don't *care*, because I can just trivially undo it!".

Now, usually it's really as simple as just using ORIG_HEAD (or the top-of-the-branch itself when the pull simply failed), but you can actually do it for any commit. Say, you've worked for a week, and have committed five or six things (and you don't even quite remember), and you are just weary, and realize that IT IS ALL CRAP!

Now, before you just decide to drown your sorrows in a bottle (or, perhaps, the morning after), you realize that you haven't actually pushed it out to anybody else yet (because it wasn't ready anyway), and that you can just undo the whole thing!

So what do you do?

You just fire up gitk, or whatever your favourite history viewer is (git log, qgit, whatever), and you select the last good commit by hand, and do

	git reset --hard <selected-commit-sha1-name>

which you just cut-and-paste from your history viewer. And magic happens. It's all gone, and you're now at that old state in history, and all your crap is gone, gone, gone. You can now have a drink or five, happy in the knowledge that you just wasted five days of your life, but nobody will ever even know your dark dirty little secret, and hopefully you're getting paid by the hour, not by the end result anyway.

Of course, if you have reflogs enabled (see previous discussions), it's even easier. In particular, it's easier if you do a "git reset" to some other point in history, and suddenly realize that what you want to undo is really that "git reset" itself ;)

(Even if you undo things, that's also recoverable, as long as you haven't done any garbage collection. But it can be harder, because now you won't get "git log" or "gitk" to show the stuff you undid, so this is where reflogs can save your bacon, since they will remember the old stuff too. Without reflogs, you either need to have it in ORIG_HEAD, or you need to run "git fsck-objects" and look at all the dangling commits by hand).

So be happy. "git reset" can be dangerous (you *are* throwing things away), but it's also very powerful, and pretty easy to use. And git makes it fairly hard to *really* throw anything committed away, so even if you undo something, and realize you want to re-do it again, it's possible to go back - at most it's just a bit more involved to *find* the place to go back to.

One final (and unrelated) note. If all you want to do is "sync up", and not actually merge anything new into your current branch, you should just do "git fetch". Not "git pull". Doing a "pull" implies merging into your current branch, and thus does more than just "sync up" the branches you are tracking.

			Linus
Previous: Bill LearNext: Kalle Pokki
Message 14 of 51 in “Git rescue mission”
  1. Bill LearFeb 8, 2007
  2. Johannes SchindelinFeb 8, 2007
  3. Bill LearFeb 8, 2007
  4. Johannes SchindelinFeb 8, 2007
  5. Bill LearFeb 8, 2007
  6. Junio C HamanoFeb 8, 2007
  7. Alexander LitvinovFeb 8, 2007
  8. Junio C HamanoFeb 9, 2007
  9. Alexander LitvinovFeb 9, 2007
  10. Bill LearFeb 8, 2007
  11. Jakub NarebskiFeb 8, 2007
  12. Jeff KingFeb 8, 2007
  13. Bill LearFeb 8, 2007
  14. Linus TorvaldsFeb 8, 2007
  15. Kalle PokkiFeb 8, 2007
  16. Linus TorvaldsFeb 8, 2007
  17. Kalle PokkiFeb 8, 2007
  18. Shawn O. PearceFeb 8, 2007
  19. Theodore TsoFeb 9, 2007
  20. Shawn O. PearceFeb 9, 2007
  21. Jakub NarebskiFeb 9, 2007
  22. Theodore Ts'oFeb 10, 2007
  23. Print a sane error message if an alias expands to an invalid git commandTheodore Ts'o, Feb 10, 2007
  24. Allow aliases to expand to shell commandsTheodore Ts'o, Feb 10, 2007
  25. Linus TorvaldsFeb 10, 2007
  26. Theodore TsoFeb 10, 2007
  27. Johannes SchindelinFeb 10, 2007
  28. Theodore TsoFeb 11, 2007
  29. Johannes SchindelinFeb 11, 2007
  30. Theodore TsoFeb 11, 2007
  31. Johannes SchindelinFeb 11, 2007
  32. Junio C HamanoFeb 11, 2007
  33. Johannes SchindelinFeb 11, 2007
  34. Theodore TsoFeb 12, 2007
  35. Shawn O. PearceFeb 12, 2007
  36. Junio C HamanoFeb 10, 2007
  37. Kalle PokkiFeb 9, 2007
  38. Bill LearFeb 8, 2007
  39. Linus TorvaldsFeb 8, 2007
  40. Bill LearFeb 8, 2007
  41. Bill LearFeb 8, 2007
  42. Shawn O. PearceFeb 8, 2007
  43. Bill LearFeb 8, 2007
  44. Shawn O. PearceFeb 8, 2007
  45. Jakub NarebskiFeb 9, 2007
  46. Linus TorvaldsFeb 9, 2007
  47. Michael S. TsirkinFeb 9, 2007
  48. Jakub NarebskiFeb 8, 2007
  49. Linus TorvaldsFeb 8, 2007
  50. Junio C HamanoFeb 9, 2007
  51. Jakub NarebskiFeb 8, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.