Friday, 25 December 2015

Git - Undoing at different levels

New/Tracked/Staged Files

Scenario 1
Remove all the files from working directory which are not tracked.

Solution
First do dry run to see what all files will be removed.
$ git clean -n
Would remove a.log
Would remove b.log
Would remove c.log

And if you are ready execute following.
$ git clean -f
Removing a.log
Removing b.log
Removing c.log

Note: If in between dry run and actual execution, if you add any file to staging then it will not be removed.

Scenario 2
I was adding files to staging area for preparing a commit. But by mistake I added a file which should not be part of this commit. How to revert a file from staging to working directory?

Solution
Hint: If you execute $git status, it provides you with command to do this.
$ git status
On branch core
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)


        modified:   header.html


Execute following to bring header.html back from staging to working.
$ git reset HEAD -- header.html
Unstaged changes after reset:
M       header.html

Scenario 3
I changed a tracked file. Git started showing it as modified in working directory. But now I want to revert those changes in that particular file.

Solution
$ git checkout -- <file_name>

Scenario 4 [Retrieving old versions]
I changed a file and committed. I did series of changes and committed each time. Now I want to revert its state to 2 commits back from current commit.

Solution
$ git checkout HEAD~2 -- <file_name>

or

$ git checkout <sha-1_value> -- <file_name>

Note: Post checkout changes will be staged.

To undo this action and just get back to the state in which the file is in last commit,
$ git checkout HEAD -- header.html

Amending Last Commit

Scenario 1
I have committed header.html. But I missed index.html file which should also be part of that commit. How can I add index.html to my last commit and change commit message as well?

Solution
See how the git log looks -
$ git log --oneline
0ec1496 Adds heading 1 in header.html
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

Add index.html (& other such files which you think should be part of last commit) to staging. Then
$ git commit --amend

This will open editor where you can also change the message and write-quit. Then see log again -
$ git log --oneline
0c31ce8 Adds heading 1 in header.html Also adds index.html
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

Scenario 2
I just want to change message of previous commit.

Solution
Make sure that there is nothing in staging. Then execute following and change message.
$ git commit --amend

Reverting Commit

You can revert changes made by any commit but it is recorded in the history. It will

  • delete any file(s) if added
  • add any file(s) if deleted
  • restore any file(s) if modified in that commit.

Let's see it in action.

Scenario 1
Revert a commit

Solution
$ git log --oneline
1e98c30 Adds commit to sidebar
cb23721 Adds index page of website.
cae4680 Add websites's Home page.
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

Add bottom_bar.html, modify homepage.html and delete index.html
Finally commit all your changes in one.

$ git log --oneline
e671180 Adds bottom_bar, edits homepage and deletes index
1e98c30 Adds commit to sidebar
cb23721 Adds index page of website.
cae4680 Add websites's Home page.
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

Now do a git revert -

$ git revert HEAD
[core-3 ac79e95] Reverts commit -> "Adds bottom_bar, edits homepage and deletes index"
 3 files changed, 5 insertions(+), 3 deletions(-)
 delete mode 100644 bottom_bar.html
 create mode 100644 index.html

You will notice -
  • delete any file(s) if added - bottom_bar got deleted
  • add any file(s) if deleted - index.html created as it was deleted
  • restore any file(s) if modified in that commit - homepage.html is restored
And when you see history, it will show which commit was reverted.

$ git log --oneline
ac79e95 Reverts commit -> "Adds bottom_bar, edits homepage and deletes index"
e671180 Adds bottom_bar, edits homepage and deletes index
1e98c30 Adds commit to sidebar
cb23721 Adds index page of website.
cae4680 Add websites's Home page.
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

Scenario 2
Abort a revert in progress waiting for a conflict to be resolved

Solution
Consider following file -
$ cat sidebar.html
<html>
        <body>
                <ul>
                        <li> Home </li>
                        <li> Contact Us </li>
                </ul>
        </body>
</html>

Commit log -

$ git log --oneline
ac79e95 Reverts commit -> "Adds bottom_bar, edits homepage and deltes index"
e671180 Adds bottom_bar, edits homepage and deltes index
1e98c30 Adds commit to sidebar
cb23721 Adds index page of website.
cae4680 Add websites's Home page.
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

I add item 1 & item 4 and commits. Then I add item 2 & item 3 and commits. Commit log is as follows.

$ git log --oneline
6ee1d05 Add item 2 and 3 in sidebar
ead6c93 Add item 1 and 4 into sidebar
ac79e95 Reverts commit -> "Adds bottom_bar, edits homepage and deltes index"
e671180 Adds bottom_bar, edits homepage and deltes index
1e98c30 Adds commit to sidebar
cb23721 Adds index page of website.
cae4680 Add websites's Home page.
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

Now I want commit one up the header to be reverted.

$ git revert HEAD^
error: could not revert ead6c93... Add item 1 and 4 into sidebar
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

There is error as it is not able to revert sidebar to ead6c93 version as the file is also edited in 6ee1d05.

$ git status
On branch core-3
You are currently reverting commit ead6c93.
  (fix conflicts and run "git revert --continue")
  (use "git revert --abort" to cancel the revert operation)

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

        both modified:   sidebar.html

no changes added to commit (use "git add" and/or "git commit -a")

Now you need to resolve this conflict or abort the revert operation.

$ git revert --abort

Scenario 3
Resolving a conflict and continue with revert.

Solution
Consider Scenario 2 only just that we will resolve the conflict and continue with revert. Resolve the conflict in sidebar.html file.

$ cat sidebar.html
<html>
        <body>
                <ul>
                        <li> Home </li>
                        <li> Item 2 </li>
                        <li> Item 3 </li>
                        <li> Contact Us </li>
                </ul>
        </body>
</html>

Add it to staging
$ git add sidebar.html

Continue revert operation (it will open editor to enter commit message)

$ git revert --continue
[core-3 33fc97f] Reverts commit -> "Add item 1 and 4 into sidebar"
 1 file changed, 2 deletions(-)

And finally see your commit log.
$ git log --oneline
33fc97f Reverts commit -> "Add item 1 and 4 into sidebar"
6ee1d05 Add item 2 and 3 in sidebar
ead6c93 Add item 1 and 4 into sidebar
ac79e95 Reverts commit -> "Adds bottom_bar, edits homepage and deltes index"
e671180 Adds bottom_bar, edits homepage and deltes index
1e98c30 Adds commit to sidebar
cb23721 Adds index page of website.
cae4680 Add websites's Home page.
8816355 Adds body tag in header.html
94f8df4 Adds html with header.html
3a86518 Initial Checkin

There is more to it - how can you rewrite history? Click here to know more. 

No comments:

Post a Comment

Your comments are very much valuable for us. Thanks for giving your precious time.