In this guide you'll learn how to keep a cleaner Git history having one commit per Pull Request (hereinafter referred to as "PR").
Benefits of a linear Git history
- Easier to do a Git bisect in order to find bugs: find the PR that has the bug more effortlessly because there is a one to one relationship between PRs and commits.
- Git log history will be more readable: since it will be a shorter and concise Git history.
- Commit early and commit often: quick disposable messages in case you want to go back and not start from the beginning when working on a feature or bug fix.
Configure your Github repository to allow rebase merging
The Github merge button for the PRs adds merge commits by default. As a first step update your Github repository settings in order to change this behaviour.
Commit early and commit often
If you fail to commit and then do something poorly thought out, you can run into trouble. Additionally, having periodic checkpoints means that you can understand how you broke something.
Let's say you are trying to add theming support to your app, here is an example of several commits in your feature branch:
git log --pretty=oneline
2ae83a39277d4940ce6d3c76c742047130be4adb (HEAD -> add-theming) Finish
0b47fcbaa276323fc43134652f77ccd49d072e1b WIP
4c2e809097df993ffc57b4c8ce01de1c0042efb2 Fix theming provider
db368b434628d3859c5f36cf7c74d9788af34bdf Add theming support
356351b29c79682393ee10ee6c6a6c97fc678d7b (origin/master, origin/HEAD, master) Initial commit
When finished, do a git rebase
git rebase -i master
This will prompt your editor to allow an interactive rebase:
pick db368b4 Add theming support
squash 4c2e809 Fix theming provider
squash 0b47fcb WIP
squash 2ae83a3 Finish
Squash all commits except the first one.
Save the changes and another screen will appear with your commit messages:
# This is a combination of 4 commits.
# This is the 1st commit message:
Add theming support
# This is the commit message #2:
Fix theming provider
# This is the commit message #3:
WIP
# This is the commit message #4:
Finish
That you can rewrite it with something similar to this:
# This is a combination of 4 commits.
# This is the 1st commit message:
Add theming support
- First step
- Second step
- Third step
# This is the commit message #2:
# Fix theming provider
# This is the commit message #3:
# WIP
# This is the commit message #4:
# Finish
Here the unuseful messages are commented out, and if we have useful ones or want to add more info, we can do it using bullet points below the commit title (in this case Add theming support
)
Once finished, push the changes to your Github repository:
git push --set-upstream origin add-theming
Create the PR and merge changes
Now go to the Github repository, you'll se a button to create the PR:
Once it's created, you'll see your changes, the title will be the first line of your commit message, and the body will be the rest of the commit message:
Click the "Create Pull Request" button and the PR will be created:
Finally press the "Rebase and merge" button.
Conclusion
That's it!
If you follow this workflow you'll always have a single commit for each PR with the benefits mentioned before.
If you want to comment on your preferred workflows and the reasons why you like them or you have suggestions or criticisms for this workflow, let me know in the comments.
Top comments (5)
Why not use "Squash and merge"? It will automatically combine all commits into one and merge it.
I'm glad you asked that question, I had exactly the same doubt when I started doing this workflow, so after researching a little I found this explanation from stackoverflow:
Merge commits
Will keep all commits history of the feature branch and move them into the master branch
Will add extra dummy commit.
Rebase and merge
Will append all commits history of the feature branch in the front of the master branch
Will NOT add extra dummy commit.
Squash and merge
Will group all feature branch commits into one commit then append it in the front of the master branch
Will add extra dummy commit.
Here is the link:
stackoverflow.com/questions/242723...
So, doing "squash and merge" instead of "rebase and merge", it seems that adds an extra dummy commit. I don't see a downside for using "rebase and merge" instead.
At DEV we use "squash and merge". People write their commits on their branches, then they submit the PR (rebased or not, depending on the situation or possible conflicts), when it's ready the title of the PR or an edited title will be the final and only commit.
If you look at the list of commits on master you can see how there's only one commit per PR
Thanks for the clarification rhymes, that's good to know. I will try this approach in my next public repository project, it seems that in both cases there is only one commit in the end but may be using "squash and merge" you can avoid the manual rebase step if there are no conflicts.
Yeah that's it. We only rebase if we need to bring in changes from master or if there's a conflict, but conflicts can be solved merging without rebasing as the final commit will be squashed anyway