Practical Git: Rebasing

A commonly suggested git practice is to commit distinct units of work, often. Following this practice can provide a helpful outline showing the historical progression of a feature. However, when the work of each contributor is merged into the main branch of the repository, a tome of commit history has now accumulated.

For the case of a team who seeks a more readable, organized commit structure, git rebase offers several options for cleaning up commit history. Rebase is a powerful way to perform merge-like operations, condense a group of commits, and edit a larger context of version history on a branch.

Due to the power of the rebase workflow, it may be beneficial to create a copy of the working branch before trying the below commands for the first time.

Rebasing

As we work on adding commits to a feature branch, the main branch also moves forward in history, gaining commits. We’ll typically keep the feature branch up to date as needed by merging main into it, but we can also perform a rebase. This is a great method for keeping commit history free of clutter from merge commits.

Performing a rebase is akin to lifting all feature commits and placing them on the HEAD of the given base branch (main) as if they were started from the newest commit in the base branch’s history.

The log below shows the commit a working branch was started from (dd4292267) as well as the most recent commit (c954abec). We’ll rebase the branch as if it had started from the current HEAD commit of main.

From the working branch, we run:
git rebase main

Looking at the commit history, we can see that the commit (c1e74f3b) was successfully rebased against the most recent commit on main (d8aecf84).

Note that a rebase should only happen on unpublished work. Pushing a branch that has rebased its existing commits in the remote will require a “—force push”, and will override the remote history – potentially affecting collaborators working with the branch.

Rebasing with Fixup

We can go another step further and use an interactive rebase with fixup to condense commits and have greater control over the rebase. The use case here is, again, about condensing and cleaning to reduce the noise level of commits merged into the main branch. For example, if a developer has 16 commits on a long running feature branch, it may be a good candidate for a rebase using fixup, or similarly a rebase with squashing – described in the next section.

Observe the branch history below.

We’ll now rebase while simultaneously combining the 2 most recent commits.

Run:

git rebase -i main
With the “-i” flag, git enters interactive mode and opens the default editor. The comments (#) outline several operations that can be performed on both commit history and messaging.
Below, we’ll edit the text using ‘pick’ to keep the most recent commit and ‘fixup’ to condense the earlier commit into it.
We can see the commit was successfully rebased from main.
Again, these actions make significant changes to repo history and in most cases, we should only rebase our own history and not published commits.

Squashing Commits

Another option within the scope of an interactive rebase is to perform a squash. When squashing commits, we’re condensing multiple commits into a single commit, though we can retain the existing commit messages within the resulting or ‘picked’ commit.

We’ll squash the 3 most recent commits, by running:
git rebase -i HEAD~3

The output again opens our default editor in the context of an interactive rebase. Note that the commits shown are placed in reverse chronological order. We actually squash backwards in time toward an earlier commit. This is the native behavior of git.

Mark each commit to squash.
Lastly, edit commit messages if necessary, then save and quit the editor.
We see the resulting squashed commits as condensed commit messages added to the picked commit.

In Conclusion

The rebasing workflow is powerful in its ability to manage and rewrite version history. Finally, a reminder that caution should be taken when performing any of these actions as they may create a conflicted version history for collaborating team members.

Documentation on the above commands can be found at: Git – Git Rebase Documentation

About Intertech

Intertech is a Software Development Consulting Firm that provides single and multiple turnkey software development teams, available on your schedule and configured to achieve success as defined by your requirements independently or in co-development with your team. Intertech teams combine proven full-stack, DevOps, Agile-experienced lead consultants with Delivery Management, User Experience, Software Development, and QA experts in Business Process Automation (BPA), Microservices, Client- and Server-Side Web Frameworks of multiple technologies, Custom Portal and Dashboard development, Cloud Integration and Migration (Azure and AWS), and so much more. Each Intertech employee leads with the soft skills necessary to explain complex concepts to stakeholders and team members alike and makes your business more efficient, your data more valuable, and your team better prepared. In addition, Intertech is a trusted partner of more than 4000 satisfied customers and has a 99.70% “would recommend” rating.