Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Managing Commit History Like a Pro: Tips and Techniques for Streamlined Code History

Sometimes we all have a hard time keeping track of our commit history. Not to mention making sense of your development timeline.

We've got the tips and techniques you need to streamline your code history and manage commits like a pro - when you stick to a few rules it's easier than you think.


Understand the difference: git private and public (shared) branches

The key difference between private and public (shared) branches in Git is that private branches are visible only to the developer who creates them (locally), while public (shared) branches are visible and accessible to all developers working on the project (remotely).

Here are some tips for managing commit history in private and public branches:

For private branches:

  • Use descriptive names to help you identify the branch's purpose and make it easier to merge with other branches.

  • Delete private branches once they have fulfilled their purpose.

For public (shared) branches:

  • Avoid force-pushing to shared branches, as this can overwrite other developers' changes.

  • Always create a new branch off the shared branch, make your changes, and merge back into the shared branch once your changes have been approved.

By following these tips alone, developers can already collaborate effectively with their team.


Rebasing: keeping your code up to date with the main branch

Rebasing is an essential technique for keeping your code up to date with the main branch while avoiding unnecessary merge commits.

The fine print: Rebasing involves altering the base of your branch by replacing the original base commit with a different one, thereby giving the impression that you had created your branch from a different starting point. This is achieved in Git by generating new commits and merging them with the designated base. It is crucial to grasp the fact that despite the branch appearing unchanged, it consists entirely of new commits.

Rebasing is like saying, “I want to base my changes on what everybody has already done.”

Rebasing allows you to integrate changes from the main branch into your codebase without creating additional merge commits, making reviewing and managing changes over time easier. Here's how to do it:

1. Start by checking out the branch you want to rebase, for example your private feature branch.

git checkout <feature-branch-name>

2. Run the "git fetch" command to bring your local repository up to date with the remote repository.

git fetch

3. Run the "git rebase" command, specifying the branch you want to rebase onto. This will apply the latest changes from the branch you're rebasing onto your codebase, for example the public main branch

git rebase <public-branch-to-rebase-onto>

4. If there are any conflicts, resolve them manually and run "git rebase --continue."

git rebase --continue

The rule of thumb is to rebase a private or local feature or bugfix branch onto a public shared branch like main or master.

Before Rebase:

            A---B---C feature
      D---E---F---G master

After Rebase:

                    A'--B'--C' feature
      D---E---F---G master

In this example, we have a master branch with four commits (D, E, F, G) and a feature branch with three commits (A, B, C). When we perform a rebase of the feature branch onto master, Git creates new commits for each of the original feature commits, resulting in a new commit history for the feature branch. The resulting branch now has new commits, represented by A', B', and C', that are based on the latest master commit (G).

Beware: Using rebase to update your feature branch requires repeatedly resolving similar conflicts.

Using the rebase command to keep your feature branch updated may seem like a convenient way to streamline your code history, but it comes with a caveat: resolving similar conflicts can become a recurring and time-consuming task.

Rebase can be a useful tool for maintaining a clean commit history and avoiding merge commits. However, when you rebase your feature branch onto the updated main branch, you may encounter conflicts that you've already resolved in the past. The more you rebase, the higher the chances of having to resolve the same conflicts over and over again.

Here's a pro tip to avoid this issue:

Instead of using `rebase`, consider merging the main branch into your feature branch. This approach allows you to resolve conflicts only once, and subsequent rebase actions will be straightforward.


Rebase and collaboration: The golden rule (of rebasing)

Rebasing and collaboration go hand in hand when it comes to managing commit history. The golden rule of rebasing is simple: never rebase a public branch or any branch that has been pushed to a remote repository and shared with others.

Rebasing involves changing the base of a branch to another commit, which can create conflicts with other team members' work. By never rebasing a branch that has been pushed upstream, you can avoid disrupting your team's workflow and maintain a clean commit history.

Before Rebase:

            A---B---C feature
      D---E---F---G master

Violating the Golden Rule: After Rebase feature:

             A---B---C   feature
           /          \
      D---E            F'--G' master

To re-iterate Git rebase rewrites the commit history of the master branch, making it difficult for others to collaborate and synchronize changes.

When you perform a git rebase on a public shared branch, it creates new commits by altering the original commit history. This means that if someone else has based their work on the original commit history, they will now have to reconcile their changes with the new commit history, which can be a time-consuming and error-prone process.


Interactive git Rebase: Local cleaning up of commits

Interactive Git rebase is a powerful tool that simplifies and streamlines the commit history of your code, making it a great option for local cleaning up of commits. By editing, combining, deleting, or reordering commits, you can create a cleaner, more organized history of your code.

Here are some tips and techniques for using Interactive Git rebase like a pro:

  1. Use the interactive mode of Git rebase to pick and choose the commits you want to keep, combine, edit, delete, or reorder.

  2. Use the fix-up and squash options to combine multiple commits into one, making the history more streamlined.

  3. Use interactive Git rebase in a collaborative environment to ensure a clean and organized commit history.

  4. Use aliases to simplify the process of using interactive Git rebase, making it more efficient and faster.

The true potential of interactive rebasing lies in the clean and relevant project history that it produces. It enables the feature implementation to look seamless and well-planned, with the ideal number of commits. By doing so, it showcases the project's history meaningfully and without unnecessary clutter, making interactive rebasing an invaluable tool for maintaining a project's integrity.


Handle with care - force pushing and its implications (private branches only)

Force-pushing to a shared branch can have serious implications for your team's code history and should always be avoided. However, in the case of private branches, force-pushing can be a helpful tool for managing your commit history like a pro.

When working on private branches, which are not visible to the rest of your team, force-pushing allows you to squash or amend commits, reorganize your commit history, and keep your code base clean and organized.

Keep in mind that force-pushing should still be used with caution, as it can result in lost work and confusion if not executed properly. Always communicate with your team before using force-push.


Do not rebase after creating a pull request (because others look at your 'private' branch, that is now a public branch)

When creating a pull request, it is best to avoid rebasing. This is because rebasing can alter the commit history, which others may have already looked at on your 'private' branch. Once you've created a pull request, your 'private' branch becomes public, and any changes to the commit history can confuse and frustrate reviewers, causing delays in the review process.

Instead, it's important to manage your commit history proactively by:

  1. Making frequent commits with clear and descriptive commit messages.

  2. Using branches for experimental and new feature development.

  3. Using interactive rebases to edit, squash and clean up your commit history before creating a pull request.

With these techniques, you can ensure a clean and streamlined commit history that makes reviewing your code much more manageable.


Always merge pull requests to public branches

When it comes to managing commit history, merging pull requests to public branches is a crucial step to ensure streamlined and efficient code history.

  1. Create a clear and concise commit messages on your feature branch that describe the changes you've made.

  2. Optionally squash commits on your feature branch into a single commit via interactive rebase with a descriptive message to keep your commit history clean and easy to follow.

  3. Use git rebase instead of git merge to keep your commit history linear and avoid unnecessary merge commits.

  4. Use pull requests to review and approve code changes before merging them into shared public branches.

With this, you can ensure that your commit history is consistent, easy to manage, and ultimately, streamlined.


In Conclusion

Prefer a clean linear history without merge commits? Use rebase.

Rebase is an excellent tool for developers who prefer a clean linear history without merge commits, as it helps to streamline code history and management of commit history. Instead of merging changes from a feature branch back into the main branch, rebase moves the feature changes to the main branch and creates a linear history.

Interactive rebase is a favourite among developers to refine a feature branch before merging it into the primary code base. This approach provides an opportunity to remove trivial or outdated commits, and ensure that everything else is organized before committing it to the official project history. Consequently, the entire feature appears as if it was built in a single, meticulously-planned set of commits.

Preserve complete history and play it safe? Use git merge

When it comes to managing commit history of your code, Git merge is an efficient tool for preserving the complete history and playing it safe.

By using Git merge effectively, you can preserve a complete history of your code while ensuring that it remains safe, streamlined, and easy to understand. Pro tip: Before merging, always make sure to thoroughly review code changes and test thoroughly to minimize errors and ensure the stability of your code.


Next up: Git blame and bisect: how to find bugs fast


Happy Coding!
Sean Manwarring
Head of Marketing at Izymes - Visit our Bitbucket Apps




Log in or Sign up to comment
AUG Leaders

Atlassian Community Events