In software development, version control systems like Git are essential for managing changes to the codebase. At ShareWis, we have a good Git workflow. It has many steps, but with some automation tools, it is still comfortable to use. After setting up a good Git workflow, we need to define what makes a good commit and a good pull request.
For pull requests, it’s best if they don’t include too many changes. Avoid having too many files with hundreds of lines of changes. Ideally, a pull request should have only one commit. We will discuss more details about good pull requests in a future post. So, what is left to work effectively when collaborating as a team is to have a good commit. In this article, we will talk about the characteristics of a good commit.
But why is a good commit important?
- For engineering team, good commit practices lead to better collaboration, easier debugging, and more maintainable code. Additionally, well-crafted commits can greatly enhance the understanding of the project’s history and facilitate smoother code reviews.
Characteristics of a good commit
- Atomic Changes
- A good commit should be atomic, meaning it should represent a single logical change. This makes it easier to understand and revert if necessary.
- Atomic changes contain only one feature, refactor, fix, etc.
- Clear and Descriptive Messages
- The commit message should clearly describe what the commit does. This helps team members understand the changes without having to read the code.
- For ShareWis projects, the commit message—specifically, the first line (treated as the commit title)—should contain the JIRA ticket ID, such as SWWB-XXX or FDT-YYY. This practice aids in easy tracking and cherry-picking of commits.
Good commits with Title:
Commit 1: SWWB-6685 - Refactor PaymentService: Course Subscription by Stripe Part
Commit 2: SWWB-6685 - Add new StripeService::CourseSubscriptionPurchase
This new service handles the Course Subscription Purchase using PaymentIntent, allowing for transaction “rollback” if a failure occurs.
Commit 3: SWWB-6685 - Add RSpec Tests to StripeService::CourseSubscriptionPurchase
- Properly Scoped Changes
- Changes in a commit should be properly scoped and not too large. Avoid mixing unrelated changes in a single commit.
Writing Effective Commit Messages
Structure of a Commit Message
- A well-structured commit message typically includes a short summary (50 characters or less), followed by a more detailed description if necessary.
Example:
SWWB-XXX - Add user authentication to the application
- Implemented login functionality
- Added user registration
- Integrated with the existing user model
Examples of Good and Bad Commit Messages
- Good:
FDT-XXX - Fix bug in user authentication
- Bad:
Fixed stuff
- Good:
Tips for Writing Clear Messages
- Use imperative mood (e.g., “Add feature” instead of “Added feature”).
- Be concise but descriptive.
- Explain the “why” if the reason for the change isn’t obvious.
Best Practices for Making Commits
- When to Commit
- Commit frequently but only when a logical piece of work is complete.
- Ensure that your code still works after every commit. If a commit breaks some tests, fix the issues and amend the commit.
- Also ensure your commit passed the Rubocop checks (or any other Linters for JS, Python, …), if violated some Rubocop rules, fix them and amend the commit. In the future, alongside Rubocop, we may add some other useful plugins to enhance our code quality and reliability such as Brakeman (security vulnerabilities checks), bundler-audit (Checks for vulnerable versions of gems), bullet (N+1 queries, …), Reek (detect code smells), rails_best_practices, …
- How Often to Commit
- Make small, frequent commits. This makes it easier to track changes and find specific modifications in the project history.
- Handling Large Changes
- Break down large changes into smaller, manageable commits. This keeps the project history clean and understandable.
Recommended Git Workflow
- To maintain a clean and effective Git history, it’s crucial to follow a disciplined workflow. Instead of using
git commit -A
, which stages all changes at once, take the time to review each change individually. After finishing your implementation or fix, go through the changes carefully, checking each chunk to ensure it is correct and necessary. This review process helps catch mistakes early and ensures that each commit is meaningful and well-structured. - Using Git GUI tools like GitKraken, SourceTree, the built-in tools of VS Code, or in my case, I’m using Sublime Merge. Using these Git GUI tools can make this process easier. They provide a visual interface for reviewing changes, staging them selectively, and writing detailed commit messages. By staging changes in small, logical chunks, you create a clearer history that is easier for others to understand and review. This practice also aligns with the principle of making atomic commits, where each commit represents a single logical change.
- Adopting this careful approach to staging and committing not only improves code quality but also enhances team collaboration. It ensures that every commit is deliberate and that the project’s history remains clean and informative.
In conclusion, following good commit practices is important for keeping our codebase clean and efficient. By making small, clear changes and writing good commit messages, we help our team work better together. Each commit should keep the code working to avoid problems later. These habits make code reviews and debugging easier and improve the overall quality of our code. At ShareWis, using these best practices in our Git workflow will help us work more effectively as a team and keep our code at a high standard. Good commits are the foundation of a healthy codebase and a productive development environment. Let’s make every commit count and keep our projects running smoothly.