Git Revert (Quick Reference)

Git Revert (Quick Reference)

###PURPOSE Reverting to a previous state of your codebase can be challenging and at times scary, but mistakes do happen and in times like those, Git's version history is our best bet at recovery.

Revert last commit

# to uncommit but keep the changes intact
git reset --soft HEAD^
# to uncommit and remove the changes from the file as well
git reset --hard HEAD^

Revert to a Commit

# To see what commit you want to revert to, first check all the commits.
git log
# once you have a commit hash, let's say 0123456

git revert --no-commit 0123456..HEAD
git commit -m "some relevant message to why you reverted to this one. since you are essentially rewriting history"

Reverting commits

# To revert the most recent change
git revert HEAD
# To revert the change made before the most recent change
git revert HEAD~
# To revert changes made in a specific commit, say, 12345678
git revert 12345678

If you are reverting to a merge commit, add the -m flag, with the number specifying to which commit you want to go to

Reverting a Git Stash Pop

  • There are times when you accidentaly end up popping your git stash
  • For example, when you wanted to stash pop your changes to a different branch
  • Follow these steps to keep your stash saved, and remove the conflicts
git reset HEAD .
git stash
git checkout other_branch
git stash apply stash@{1}
  • Note: Mostly an unwanted stash pop would result in a merge conflict, due to which your stash will still be preserved
  • Still, it is better to stash the merge conflict as well, to avoid losing your stashed progress

Moving commits from one branch to another

Imaging that you want to raise a PR for a hotfix. So, you first the original work for tracking, and then commit the actual changes. That's a reasonable way to do things. However, when you push your changes, you realize, you never actually pushed the original work! In essence, what you want to do is, go from this state:

dev            C - D
             /
master A - B

to this state:

dev                D
                 /
master A - B - C

To do so, we can use the merge command, on a specific commit:

git checkout master
git merge C

# Result:
                 D (dev)
                /
master A - B - C (move master HEAD)

If you have raised a PR before doing these changes, chances are, you will not see the changes reflected after pushing them to master. To show the true-diff as it should be given that some changes have been merged in the base branch,

  • Use the Edit button when viewing the PR in GitHub
  • Change the base branch from master (if it was master) to some other branch
  • Change the base branch back to the original branch (master in our example)
  • Reference

Note: The solution for the opposite scenario can be found here

Cancelling a Merge

Sometimes, your dev branches are behind master branch, either because of directly commiting to master, or because the commits were made in devbranch2, and then pushed to master, making devbranch1 behind.

Nevertheless, In such cases, you try to pull changes from master back to dev branch so you can continue working on a feature. And lo-behold, you get a merge conflict!

You can either fix the conflicts, or cancel a merge by using --abort flag to look for other methods.

git merge --abort #when facing a merge conflict due to pull or merge
git cherry-pick --abort #when conflict came due to cherry pick operation

If you know that the merge should keep the pulled changes, and discard the local changes, you can specify the --theirs parameter

git pull -X theirs

If you are already in a conflicted state, worry not, just use

git checkout --theirs path/to/file

Move commit from one branch to another

Merge Commit onto the required branch

Firsty, identify the commit hash that you want to move.

git checkout feature_branch #branch from which commit will be picked
git log #identify commit hash

Let's say the hash is #0123456 Switch to the branch to which you want to move the commit.

git checkout master #branch to which commit will be applied

Use the cherry-pick command to apply the commit

git cherry-pick #0123456

This will apply the commit to the correct branch, after which you can push these changes

git push origin master #branch to which commit will be applied

Now your commit has been copied to the required branch, however, it is still there in the original branch as well.

Delete commit from the original branch

To finish the move, we should delete the commit from the feature_branch (original branch). To do so, we can use git rebase and drop the commit.

git checkout feature_branch
git rebase -i HEAD~3 #the number represents how far back the commit is from the head

The interactive rebase window will open up.

pick ece4b89f feat(Robusta): Generate report and send mail
pick 0123456 feat(Robusta): +install test case
pick 4da9b1dd feat(Robusta): move app installation to pagebase

Replace pick with drop

pick ece4b89f feat(Robusta): Generate report and send mail
drop 0123456 feat(Robusta): +install test case
pick 4da9b1dd feat(Robusta): move app installation to pagebase

Save and quit You would see a message such as Successfully rebased and updated refs/head/robusta-dev

Now, push your changes to the feature branch

git push <remote> <branch>

Use force (-f) if required.

Revert a single file to HEAD when there are multiple files with changes(https://stackoverflow.com/questions/7147270/hard-reset-of-a-single-file)

There are times when you wish that only some files loose their changes and be reset to HEAD.

  • One way would be to commit the rest of the files first and then git reset --hard However, this is an awkward compromise. What if you didn't want to commit the other files just yet?
  • Git checkout comes to rescue in such a situataion.
  • Git checkout HEAD -- file_name.extension The -- operator implies that further arguments are filenames. Also, please mind the space after the --.

Unstage deleted file (https://stackoverflow.com/questions/9591407/unstage-a-deleted-file-in-git)

We can use the -- operator to pass in file name in any git command. Here, we will use that feature to revert our accidental deletion. Note that you cannot use tab completion to fill in the file name because the file is deleted from the system.

git reset -- <name_of_file.extenstion>
git checkout -- <name_of_file.extenstion>

Undo a Commit (https://stackoverflow.com/questions/927358/how-do-i-undo-the-most-recent-local-commits-in-git)

To undo the most recent commit,

  1. If you want to keep the commit as it is (the files will be in staged state)
git reset --soft HEAD~
  1. If you want keep the changes intact, but remove the commit (files will be unstaged state)
git reset HEAD~

Undo an Ammend (https://stackoverflow.com/questions/1459150/how-to-undo-git-commit-amend-done-instead-of-git-commit/1459264)

First, we update the ammended commit back to previous state

git reset --soft HEAD@{1}

Note that HEAD@{1} is different from HEAD~ in this case

Then, we commit back the current tree with the original message

git commit -C HEAD@{1}

Recover Git Index file (https://stackoverflow.com/questions/38274887/how-to-recover-git-index-locally)

If you accidentally deleted your .git\index file, maybe because you wanted to remove the index.lock file, you can recover it back using the reset command.

git reset #re-scan the working directory
git add -u #updated the index

Tagged in git