3 methods for keeping histories clean and organized

In this series of articles, I’m going to show you how to get clean and maintainable git histories. In the first part, we look at different methods. If these methods are followed, the history remains clear, facilitates code reviews, debugging and can serve as documentation:

  1. Meaningful commit messages
    A clear description of the change and its motivation
  2. Cohesive commits
    Only changes that belong together should be included in a single commit
  3. Avoid temporary commits
    WIP, temporary or debug commits should not be merged to keep the history clean

Meaningful commit messages

Everythings starts with a clear commit message. It should briefly summarize what was changed and why. Conventional Commits offer us a reliable format for commit messages, enhancing the clarity and comprehensibility of source code histories. A commit message should include:

  • Type: The type of change (e.g., fix, feat).
  • Scope (optional): The affected area of the project.
  • Description: A brief description of the change.
  • Body (optional): Additional details about the change.
  • Footer (optional): Metadata, e.g., references to issues.

Here is an example of such a commit message:

feat(auth): add JWT authentication

This commit introduces JSON Web Token (JWT) based authentication to the login module.

BREAKING CHANGE: The login API now requires a token for authentication.

Cohesive commits

A commit should be atomic, containing logically related changes that should not be split up. Each commit should represent a standalone change, whether it’s a bug fix, a feature enhancement, or a code refactoring. This practice simplifies change tracking and finding errors more quickly. It provides a clear overview of the modifications made and the reasons behind them, also streamlining the code review process. By isolating each change, reviewers can concentrate on specific modifications without feeling overwhelmed by a large number of changes. Moreover, in case of issues, reverting changes becomes significantly more straightforward, minimizing disruptions to the overall project.

Let’s take the previous example and explain the commits in more detail:

Commit 1: feat(auth): setup JWT library and utility class
Commit 2: feat(auth): configure security with JWT filter
Commit 3: feat(auth): modify login API to return JWT token
Commit 4: test(auth): add unit tests for JWT authentication
Commit 5: docs(auth): update README with authentication instructions
  • Commit 1 adds the JWT library and creating the utility class
  • Commit 2 includes a JWT Filter into the security configuration
  • Commit 3 focuses on the specific change to the API
  • Commit 4 is dedicated to tests to ensure that the new functionality is fully covered
  • Commit 5 contains only documentation changes

Aim to create real cohesive commits, not just small, chronological commits. The purpose of commits is to explain what changed and why, not to document every step. This leads to a cleaner Git history, helps to improve code quality and maintainability.

Avoid temporary commits

While in the process of development and debugging, it’s important to be mindful of the impact of WIP (Work in Progress) and debug commits on the clarity of a code repository. These types of commits can introduce steps that do not reflect the final implementation, leading to complications in tracking progress on features or bug fixes.

Take, for example, a common debug commit where a developer adds println statements to monitor variable behavior during code execution. It is essential to clean up these debugging statements once the debugging phase is complete.

Below are some commit samples that are not suitable for merging:

Commit 1: feat(user): first version UserService
Commit 2: refactor(user): UserService - Tests not working
Commit 3: debug(auth): added printlns to check flow
  • Commit 1  Incomplete, unclear state – do not merge
  • Commit 2  Must be cleaned up or squashed before merging
  • Commit 3 Helpful for debugging – remove

To maintain a clear and detailed project history, it is advisable to rewrite the commit history for consolidating work-in-progress commits, eliminating temporary and debug commits prior to merging, ensuring that only important and production-ready updates are integrated into the main branch.

Conclusion

These 3 methods help to structure and maintain project histories. This includes clearly defined commit units, meaningful commit messages and that only production-relevant changes are merged into your primary branch. Just like book authors revise drafts before publishing, consider cleaning up commit history before sharing it.

So stay tuned for the second part, where we delve into techniques for cleaning up and consolidating commits.

Links

Conventional Commit https://www.conventionalcommits.org/en/v1.0.0/#summary

Photo by Markus Spiske on Unsplash

Consent Management Platform von Real Cookie Banner