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
- Pushed commit to remote repository
- Commits that are not pushed to remote repository
When commits are pushed to remote, To be on the safer side we should assume that other people might have already pulled the changes.
you can easily remove a commit from the repository by doing a
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.
# 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
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
If the mistake is in the last commit we can use
- commit amend
- git reset
With commit amend you can make changes and add the changes on top of the last commit.
I created a new feature but I missed to add an file which should be part of that commit.
$ 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 is very versatile. simply put we can use reset to undo commits.
to undo last commit
$ git reset HEAD^1 Unstaged changes after reset: M README.md
if do not wish to keep changes after the commit you want to change you can undo all the commits from the bad commit.
$ 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
To fix commit without removing / modifying other commits we can use rebase.
delete the commit
$ git log --oneline cf037c9 (HEAD -> master) add test file 36c4f05 fix bug e344740 added new feature 90c9958 first commit $ git rebase -i 36c4f05~1
-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.
once you exit from editor the rebase will be applied and check git logs to see the commits
$ 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 :)