Git rebase to manage history meaningfully

git rebase for meaningful history

Developers tend to neglect the importance of meaningful git history and they end up into bad commit history and makes it hard to follow the story of how project was evolved.

Are you taking git history seriously? If no, then this is a must read on best practices to manage it. If yes, you can still validate whether you are following it correctly in your current projects.

In routine development work, it is always recommended to work in branch a.k.a. feature branch which is forked from master/production to keep the main branch unaffected of on-going development. Usually production releases are made from main branch therefore we do not want unfinished work to go in production.

It is quite common to have multiple developers working on same project and in fact on the same feature often hence they will endup working on same feature branch. Purpose of feature branch is to perform frequent commits as you achieve a logical part of whole module. It is encouraged to perform daily commits when intensity of development is high.

When multiple developers are working on same feature branch, you will find the following kinds of commits in your git history.

  1. Work in progress commits in main branch
    • “bug fix”, “more work”, “minor changes”, “formatted code”, “incorporated review comments”
    • “Fixed JIRA-5934”
    • “super long commit message goes here, something like 100 words and lots of characters!”
  2. Ugly merge commits all over the history
    • Merge branch ‘<branch name>’ of <git url>

Its okay as far as work in progress commits and ugly merge commits remains in the feature branch, as it helps for tracking purpose. However, as soon as they are merged to master, they will make master branch history messy and hard to follow due to disturbing intermittent commits.

How would we approach solution to this problem? Let’s see!

Let’s walk through the scenarios showing how git history is generated when multiple developers are working simultaneously on a branch

Annotation: c1, c2, c3…. cn represents commits.

Scenario 1:

Local feature branch is behind its own remote. Meaning other developers have pushed their commits while local commits are not yet pushed.

Consider you are at c3 before taking pull. c2 and c3 are still local commits. Merge commit will occur as shown below when you perform git pull.

Before pull:

scenario-1-1

After pull:

scenario-1-2

Recommended way to take pull –

git pull --rebase

This will pull new commits from remote and then apply your local commits on top of it without introducing any additional merge commit. So history will now look like as follows.

scenario-1-3

Clean! Isn’t it? Also more importantly commits are applied in correct order.

Scenario 2: You diverged your work and made commits on both master and feature branches. Meaning other developers might have added commits or merged other feature branches to master.

Current state of branches

scenario-2-1

You may want keep your feature branch up to date hence you will attempt to merge master into your feature branch. Command to merge branches as follows considering you are at feature branch.

git merge master

State after merge (Usually people may go for it):

scenario-2-2

Recommended way to merge:

Alternative 1 –

git rebase master

This command will first make sure feature branch is hanging off on latest of master branch. Meaning it will keep the local branch commits aside and ensure all commits of master are pulled. Post that it will place feature branch commits on top of master branch commits without introducing any merge commit.

scenario-2-3
Alternative 2 –
git rebase -i master

Here, -i option stands for interactive – refer official site for more details about options

It will open vi editor to allow you to pick commits you want to be as part of history and squash/fixup unwanted commits you wish to get rid of from history.
You must consider this when you think your feature is reviewed and approved to be merged in production code.

scenario-2-4

Scenario 3 (Most critical): Feature branch changes are approved and need to be merged into master.

Current state of branches:

scenario-3-1

If you perform git merge master then you will end up in merge commit as described in scenario-2.

Instead perform following steps:

  1. check out master
  2. In terminal, execute git merge --squash origin demo-feature. This doesn’t commit anything.
    – If this doesn’t work(can happen when feature branch is local and isn’t yet pushed at all in remote), try git merge --squash feature
  3. Execute -> git commit -m "My custom commit message for feature"
  4. All changes should be reflected as expected in local master branch. (Refer image below)
scenario-3-2

Looks professional, Isn’t it? This is how you would find meaningful git history in any well known open source projects.

Don’t hesitate to try on test repository. Any feedbacks/suggestions/questions are welcome.

Write a comment