Yo, happy new year…
As developers, we constantly need to tell stories with our git history. This story will most likely be read by us and every other member of the team.
Many times when you discover a bug you want to figure out when the bug was introduced, you need to read the history — go back in time. The reason it’s essential to write descriptive git commits.
However, some times we write some commits that made small changes that aren’t really relevant and some times commits that just do the same thing and doesn’t really tell a good story.
For example, you write a commit:
feat(todo-text-fields): add a todo text field
then you noticed that you did not add a complete test for the `todo text field`, you add a small test and commit:
test(todo-text-fields): add a minor test to the todo text fields`
The truth is, many times we write a lot of git commits that aren’t completely relevant.
Note: If you just want to amend a commit, there are other ways to do that like `git amend` you can look up how to do that here
So, if you really need to re-write history, then keep reading.
Re-write history? (^ o^)
Yea, rebasing is basically re-writing history to tell a better story.
So, how are you gonna do that?
Here are a few steps you should follow and master as it’s an important skill set every developer should have — this is my opinion though.
The first step is to make sure you are in the branch you want to rebase.
Checkout to that branch
git checkout branch-name
Then run the command:
git rebase -i origin/master
Note: If your develop branch is your based branch, you should use origin/develop instead of origin/master
You should see something like this if there are no conflicts.
pick 3488334 feat(todo-text-fields): add a todo text field
pick 3488354 test(todo-text-fields): add test to a todo text field
pick 3488354 fix(todo-text-fields): modified the unit test for the todo test field
pick 3488304 fix(remove-console-log): remove console.log from function
pick 3488314 fix(experimenting): add some console messages to test# Rebase 92e483c..3488334 onto 92e483c (1 command)## Commands:# p, pick <commit> = use commit# r, reword <commit> = use commit, but edit the commit message# e, edit <commit> = use commit, but stop for amending# s, squash <commit> = use commit, but meld into previous commit# f, fixup <commit> = like "squash", but discard this commit's log message# x, exec <command> = run command (the rest of the line) using shell# b, break = stop here (continue rebase later with 'git rebase --continue')# d, drop <commit> = remove commit# l, label <label> = label current HEAD with a name# t, reset <label> = reset HEAD to a label# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]# . create a merge commit using the original merge commit's# . message (or the oneline, if no original merge commit was# . specified). Use -c <commit> to reword the commit message.## These lines can be re-ordered; they are executed from top to bottom.## If you remove a line here THAT COMMIT WILL BE LOST.## However, if you remove everything, the rebase will be aborted.## Note that empty commits are commented out
So, squashing your commit — squashing a commit means just removing all the commit messages you don’t want anymore. And you just have to add the word `squash` before the commit:
pick 3488334 feat(todo-text-fields): adds a todo text field
squash 3488354 test(todo-text-fields): adds test to a todo text fieldsquash 3488354 fix(todo-text-fields): modified the unit test for the todo text fieldsquash 3488304 fix(remove-console-log): remove console.log from functionsquash 3488314 fix(experimenting): add some console messages to test
Notice that we didn’t squash one?
Yea, that’s the one we want to keep. Write your change to the file and exit.
If everything goes well, yay :), you have successfully squashed your commits.
Your terminal text editor will pop-up again with different information. You should see something like this:
# This is a combination of 3 commits.# This is the 1st commit message:feat(todo-text-fields): adds a todo text field# This is the commit message #2:fix(todo-text-fields): modified the unit test for the todo text field# This is the commit message #3:fix(remove-console-log): remove console.log from function# This is the commit message #3:add some console messages to test
Delete the commit messages and leave only the ones you want or edit it to whatever you want.
As for me, I want to keep only this one:
# This is a combination of 3 commits.# This is the 1st commit message:feat(todo-text-fields): adds a todo text field
After that just write your changes to the file and exit.
That’s really it.
But wait, If you just wanted to squash all commits together and keep the message of the first commit, you should use
fixup instead of
You can now force push to your branch.
git push origin -f branch-name
Congratulations, you now have just one or more commit that properly describes what you have done so far.
You don’t necessarily need to do this all the time. You just do it when it’s necessary to do so.
Sometimes those tiny commit messages might make sense and might tell a good story as well. So, it’s also a good thing to know when to rebase and when not to do it at all.