Saturday, 16 October 2010

Beginner's guide to : Undo commits on Git

You have second though on your last(or more) commit(s),
for these sort of reasons :

(1) incomplete work / last minute idea (locally)
(2) incomplete work / last minute idea (remotely)(other solution git rebase)

Solution for (1)
Now, you'd like to undo your local commit; initially, here's what you need to be doing :

$ git reset --soft HEAD^

The line above tells git to remove the last commit.
Change HEAD^ to HEAD~2 if you want to remove last 2 commits, or HEAD~3 for three, and so on.
For the 3 cases mentioned above, git-reset(1) Manual Page recommend to use this line below after edit :

$ git commit -a -c ORIG_HEAD

But, personally, I wouldn't do this. Yes, the commit objects wouldn't have to be re-add-ed, but I have files that I don't want to be committed on the same commit group, '-a' would add all of those together with the recently modified files. And with using '-c' only, the recently modified file wouldn't be included while all un-staged files would be committed. This is hell!

I would recommend the good old fashion way of commit, where we would have full control on what/when should be committed. But first, remove the commit objects from previous reset --soft, like so :

$ git reset

Now, when you're done editing, run proper commit (run git add when needed).

$ git commit -m "commit message" filepath1 filepath2 filepath3 ..

You're all well & done! ^^

Solution for (2)
Your changes were committed to the remote repository, and then you realized, that the changes is not appropriate, and you would want to undo this, and let the repository holds only commit history until the one before. Run this :

$ git revert HEAD

Now, the line above means, to revert the changes you made on the last commit(HEAD). You can change HEAD to HEAD^ for next to last commit, or change with specific SHA (get it from git log --oneline), careful with merging tho'. Anyway, back to our subject, an editor would came, and you can change the commit message if you want (I don't find it necessary). Push and then run this :

$ git rebase -i HEAD~3

We need to pack the changes to one line history only, we don't want history that says something like 'I revert my own changes'. So now, on the editor you'll see :

pick 75589b5 seek method added
pick bfb8cf0 working seek method
pick a0f2df9 Revert "working seek method"

# Rebase 75589b5..a0f2df9 onto 75589b5

Now, the first line is older than the rest, we need it to be our base. The second line is your last commit, and the third is the reverted commit. What we want is to make second & third line to disappear; So, we need to change the word 'pick' to 'fixup' for those line, and then run save & quit. Another editor will show, it's to modify the commit message, I wouldn't recommend you to change it, just run another save and quit. Push force it, and it's like you never had commit it.

^^ Gittiful ^^

No comments:

Post a Comment