Fixing Mistakes in Git
Tags: git, github
Published: 2020-10-11 11:54:22

Let's be real here, we all make mistakes when we code and to make matters worse we persist those changes in a version control system like Github. Sometimes they are benign and on the other hand it can cause a lot of damage.

In this blog I will discuss ways by which you can fix your mistakes when using git. 

PS: Keeping your commits "Atomic" would go a long way in helping you fix your mistakes, since you can throw a commit the introduced the issue with confidence.

There are a lot of ways you can fix mistakes in commits and each way is suitable under a specific circumstance. From a practical stand point we can broadly classify mistakes into types types

1. Pushed commit to remote repository
2. Commits that are not pushed to remote repository


# Pushed to remote

When commits are pushed to remote, To be on the safer side we should assume that other people might have already pulled the changes.

## Git revert

you can easily remove a commit from the repository by doing a `git revert`.
Revert does not actually remove the commit, instead it will create a new commit which reverts the changes done in the commit.

Revert in action.
```sh
# find the commit hash of the commit you want to revert
$ git log --oneline 
d77ce47 (HEAD -> master) add instructions
e3a5bd7 bad commit
e6f780f first commit


# Revert the commit
$ git revert e3a5bd7
git revert e3a5bd7
[master 5c69f9f] Revert "bad commit"
 1 file changed, 2 deletions(-)

# list commits again
$ git log --oneline
5c69f9f (HEAD -> master) Revert "bad commit"
d77ce47 add instructions
e3a5bd7 bad commit
e6f780f first commit
```

# Not pushed to remote

We have a lot of options when it comes to fixing mistakes that are not pushed.
Depending on the situation we can choose different approaches

## Mistake in the last commit

If the mistake is in the last commit we can use
1. commit amend
2. git reset

### Commit amend

With commit amend you can make changes and add the changes on top of the last commit.

Scenario:
I created a new feature but I missed to add an file which should be part of that commit.

```sh
$ git log --oneline
6a1d188 (HEAD -> master) added new feature
90c9958 first commit

# we missed the feature.txt which should be in the last commit.
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	feature.txt

nothing added to commit but untracked files present (use "git add" to track)

# Add the file and use amend to modify commit
$ git add feature.txt
$ git commit --amend
[master d2bd903] added new feature
 Date: Sun Oct 11 15:19:09 2020 +0530
 2 files changed, 2 insertions(+)
 create mode 100644 feature.txt

# check log
$ git log --oneline
d2bd903 (HEAD -> master) added new feature
90c9958 first commit
```

### Git reset

Git reset is very versatile. simply put we can use reset to undo commits.

to undo last commit

```sh
$ git reset HEAD^1
Unstaged changes after reset:
M	README.md
```

## Fixing intermediate commit

### Git reset
if do not wish to keep changes after the commit you want to change you can undo all the commits from the bad commit.

```sh
$ git log --oneline
36c4f05 (HEAD -> master) fix bug
e344740 added new feature
90c9958 first commit

# for fixing mistake in `e344740 added new feature` 
$ git reset e344740~1
Unstaged changes after reset:
M	README.md

$ git log --oneline 
90c9958 (HEAD -> master) first commit
```

The disadvantage of using this is that the commits after the commit that you want to change are also lost. This can be troublesome for you if you need the other commits, in that case you can use `git rebase`.

### Git rebase

To fix commit without removing / modifying other commits we can use rebase.

Scenario:
delete the commit `fix bug`.

```sh
$ git log --oneline
cf037c9 (HEAD -> master) add test file
36c4f05 fix bug
e344740 added new feature
90c9958 first commit

$ git rebase -i 36c4f05~1
```
![Screenshot 2020-10-11 at 5.10.43 PM](https://dev-to-uploads.s3.amazonaws.com/i/wt91n4z2vec5iq3uihh9.png)
 
`-i` is for interactive mode, this command will open a text editor allowing you to enter what you want to do with each commit.

to delete a commit we should specify `drop` for the corresponding commit.

![Screenshot 2020-10-11 at 5.15.20 PM](https://dev-to-uploads.s3.amazonaws.com/i/iugtqopvo9c997fc4ka5.png)

once you exit from editor the rebase will be applied and check git logs to see the commits 
```sh
$ git log --oneline
608fc51 (HEAD -> master) add test file
e344740 added new feature
90c9958 first commit
```
if you want to modify the commit you can specify `edit` instead of drop.
it will pause the rebasing at that commit and you can make changes then continue the rebasing with `git rebase --continue`

Hope this was informative, stay tuned for more git related blogs :)