10

As far as I know, when you want to undo something in Git you have to explicitly find the command to undo whatever it is you've done and issue it. For instance, one way among many to undo a commit and redo it is to follow the example from here,

$ git commit ...
$ git reset --soft HEAD^
$ edit
$ git add ....
$ git commit -c ORIG_HEAD 

Or to undo a pull, you can follow the instructions from here,

$ git reset --hard

But these commands do not necessarily work interchangeably. Is there a reason why Git does not allow simple undo and redo commands? Something to do with the philosophy behind it? Also, I don't have much experience with other version control systems, but do any of them offer a simple undo and redo command?

Community
  • 1
  • 1
john
  • 3,043
  • 5
  • 27
  • 48
  • I am not sure, but I think you can do this by using `git rebase`. Check this http://gitready.com/intermediate/2009/01/31/intro-to-rebase.html – gustavotkg Dec 01 '11 at 18:49
  • 2
    The idea is that you generally never want to do things that make you lose parts of the history. Undoing a commit would remove it from the history, so that is usually not something you would do. – poke Dec 01 '11 at 19:01
  • @poke Well, Adobe Photoshop, for example, maintains an extensive history and still lets you undo/redo. Why wouldn't Git do the same? – john Dec 01 '11 at 19:54
  • 2
    @awfullyjohn Well, Git allows you to create branches in a repository. Why doesn't Adobe Photoshop do the same? – asjo Dec 01 '11 at 21:50
  • @awfullyjohn: The comparison is not apt. Besides the obvious fact that source control and image editing are not the same thing... Photoshop is designed to be used by less technical people, and undo history was in mind from the beginning as a requirement. Photoshop also takes an obscene amount of memory in order to do that, many times the size of the image. – Cascabel Dec 02 '11 at 03:54

5 Answers5

8

There are several problems with such a notion:

  • Not all operations are reversible. Sometimes this is because Git doesn't record enough information to deduce the prior state - that'd be prohibitively expensive in general. Sometimes it's things like git reset --hard or git clean, which destroy untracked changes. In order to undo them, it'd have to be continuously automatically backing up. Sometimes this is because the notion of undo is ambiguous - as you yourself pointed out, there are many ways to undo a commit.

  • If an operation is reversible, and it involved some sort of history, should the undo/redo also be in the history, or should they make it vanish? Should a commit be undone by resetting back, or by reverting (creating another commit to cancel it)?

  • Without logging every last thing you do, how would you know what the most recent operation was? Say you added a file to the index, and created a branch. There's no record of which was first.

Even if everything were clearly defined, it'd be an absurd amount of work to implement. How do you decide what constitutes a single action? A single Git command might do many things. Should it undo one step, the whole thing? What if you've run a zillion commands each doing a tiny step and you want to undo it all? And it'd have to be perfect, completely perfect, because it's the kind of feature that will be used by inexperienced users who'll have no idea how to recover from any mistake.

So, just as Git gives you the tools to do things, it gives you the tools to see what you've done, and undo things yourself if so desired.

Also, with respect to "redo", as you defined it in your question, it's repeating a command, not doing the original operation again. When you redid a commit, it was a different one. Re-running a previous command is something that command-line shells were designed to do. Git doesn't need to reinvent it.

Cascabel
  • 479,068
  • 72
  • 370
  • 318
5

Actually your first example can be performed with:

$ git commit ...
$ edit
$ git add ...
$ git commit --amend

Your second example should be more like git reset --hard <hash>

The answer to your question is that it's potentially possible, but yes it's more the philosophy driving git that means it hasn't been done. Theoretically there's no way to tell whether you got to a commit by creating it or deleting another, but using the reflog it's maybe possible... haven't really thought about it in that way before.

I don't think 'undo' and 'redo' are a very common thing in source control though, but correct me if I'm wrong.

EDIT: You could possibly rig a script that could do what you're after using the reflog - not sure if there's enough information there, but it could be worth a try.

MattJenko
  • 1,208
  • 8
  • 11
1

git is actually multiple small tools that act on the repository, index and working directory, so it doesn't have a 'core' part for any 'undo'.

That said it does have various logs, such as reflog for you to look back at what was done.

Finally, by convention, many git actions are normally thought of as being 'one way only', that is, you wouldn't want any-one to publicly see it, so git tries to 'make you go round the block' when in public. If you are still in your local repo you can back up with various commands but a global undo isn't an appropriate command offering.

Philip Oakley
  • 13,333
  • 9
  • 48
  • 71
  • 'one-way only' is a good way of thinking about it actually, as once something is in the wild undo and redo become dangerous – MattJenko Dec 03 '11 at 10:20
0

Along with the other comments I would check out git stash. Many times I stash some work, fix something else, then unstash and continue. Or for a webapp, stash my finished-and-uncommitted work, refresh the browser, unstash, open a new tab, and then compare the two back and forth to make sure a UI related bug fix didn't break anything else.

Mauvis Ledford
  • 40,827
  • 17
  • 81
  • 86
0

I will sometimes snapshot the whole active source tree to a compressed file (one click on the Mac), before doing something that scares me, like a big rebase.

Because the git commands I will be using are just acting locally on a directory tree, that makes it easy to abandon the operation and revert to exactly the situation I had before (including not checked in or modified files), if things get horribly screwed up.

I don't need to do it often, but this manual "undo" has saved my ass more than once.

w0mbat
  • 2,430
  • 1
  • 15
  • 16