If you know me, you know git is one of the tools I most like together with Ruby language, anyways. Today I want to share a little bit of my workflow when I’m doing merge and rebase operations.

First lets understand what merge does. Merge will combine 2 branchs by creating a new commit that ties then together, the result of this will be a true record of branching and merging.

example:

master:    A---B---C------D
             \        /
feature:      X---Y---M

M is the merge commit.

When we do that we are:

  • Keeping all branching context
  • not rewriting history

But the problem is that the history can become complex if you pull in master into your feature branch often.

Now lets understand what rebase does. Rebase re-applies commits from your branch on top of another branch, rewritting history, making it linear and clean (assuming your branch is based on master)

example:

master:    A---B---C---D
                 \
feature:          X'--Y'

X’ and Y’ = same commits, rebased onto master

When we do that we are:

  • Keeping history linear and clean
  • Making git log easy to follow
  • No more “merge master into feature” commits

But of course there are some downsides:

  • We are rewrinting history, it can be unsafe if commits are already pushed and shared with others
  • We lose the context of branching and merging
  • Requires more understanding of git

Worflow

Start your feature branch from master:

git checkout master
git checkout -b feature

Now that you are working on a feature branch and want to keep it up to date with master, prefer rebase. To do that you have to make sure your master is up to date first the apply rebase

git fetch origin
git rebase origin/master

This will reapply your feature branch commits on top of the latest master. When your feature is ready to be merged back into master, prefer merge.

First thing you should do is to make sure your master is up to date, to do that you can use pull with rebase option.

git checkout master
git pull --rebase
git merge --ff-only feature

This will create a fast-forward merge, keeping the history clean and linear.

Depending on your team, you can also use merge --squash to combine all feature branch commits into a single commit on master.

In the end your history will look like this:

master:    A---B---C---D---E

But why?

One good example of why you should do that is when you need to run operations like git revert.

Revert when you use merge in your workflow

Image you use merge to update your feature branch, your master branch will look like this:

master: A---B---C------D
             \        /
              X---Y---M

If you try to revert M (the merge commit), Git may ask: “Do you want to revert just the merge, or all changes from X and Y?” Often you end up needing to revert multiple commits (M + X + Y) and handle conflicts.

Another situation would be if you need to revert X or Y:

Git will try to create a new commit that undoes the changes introduced by that commit. But since the branch already merged into main, the context is different, the changes from X and Y might have been altered by the merge resolution at M. This can create conflicts, and sometimes the revert doesn’t cleanly represent “just undo X” because M may have combined X+Y+other changes from main.

Revert when you use rebase in your workflow

Now, If you use rebase to update your feature branch, your master branch will look like this:

master: A---B---C---D---X'---Y'

If you need to revert Y’, you can simply do:

git revert Y'

No confusion, no extra commits to revert, just a clean and simple history.

If you want to revert a commit in the middle of the branch (like X’), you can still do:

git revert X'

Git will create a new commit that undoes the changes introduced by X’, and since the history is linear, it’s straightforward and less error-prone.

Conclusion

  • Both merge and rebase have their pros and cons.
  • A linear history is easier to maintain making it easy to do operations like git bisect, git log --graph or git revert

This is a simplified worflow strategy and how merge and rebase work, if you want to know more about this please check the refereces:

Thats all, hope this can be useful for you.

References: