Using version control is an essential part of modern software development and using it efficiently should be part of every developer’s tool kit. Knowing the basic rules makes it even more useful. Here are some best practices that help you on your way.
- Commit logical changesets (atomic commits)
- Commit Early, Commit Often
- Write Reasonable Commit Messages
- Don’t Commit Generated Sources
- Don’t Commit Half-Done Work
- Test Before You Commit
- Use Branches
- Agree on a Workflow
Commit logical changesets (atomic commits)
A commit should be a wrapper for related changes. Make sure your change reflects a single purpose: the fixing of a specific bug, the addition of a new feature, or some particular task. Small commits make it easier for other developers to understand the changes and roll them back if something went wrong.
Your commit will create a new revision number which can forever be used as a “name” for the change. You can mention this revision number in bug databases, or use it as an argument to merge should you want to undo the change or port it to another branch. Git makes it easy to create very granular commits.
So if you do many changes to multiple logical components at the same time, commit them in separate parts. That way it’s easier to follow changes and their history. So working with features A, B and C and fixing bugs 1, 2 and 3 should make at least 6 commits.
Commit Early, Commit Often
It is recommended to commit code to version control often which keeps your commits small and, again, helps you commit only related changes. It also allows you to share your code more frequently with others.
It’s easier for everyone to integrate changes regularly and avoid having merge conflicts. Having a few large commits and sharing them rarely, in contrast, makes it hard to solve conflicts.
“If the code isn’t checked into source control, it doesn’t exist.”
Write Reasonable Commit Messages
Always write some reasonable comment on your commit. It should be short and descriptive and tell what was changed and why.
Begin your message with a short summary of your changes (up to 50 characters as a guideline). Separate it from the following body by including a blank line.
It is also useful to add some prefix to your message like Fix or Add, depending on what kind of changes you did. Use the imperative, present tense (“change”, not “changed” or “changes”) to be consistent with generated messages from commands like git merge.
If fixing some bug or making some feature and it has a JIRA ticket, add the ticket identifier as a prefix.
For example: “ISSUE-123 Fix bugs in the dropdown component for selecting items.” or “ISSUE-1234 Fix bad allocations in image processing routines”
Not like this: “Fixed some bugs.”
The body of your message should provide detailed answers to the following questions: What was the motivation for the change? How does it differ from the previous implementation?
“If the changes you made are not important enough to comment on, they probably are not worth committing either.”
Don’t Commit Generated Sources
Don’t commit files which are generated dynamically or which are user dependent. Like target folder or IDEA’s .iml files or Eclipse’s .settings and .project files. They change depending on what the user likes and don’t relate to the project’s code.
Also, the project’s binary files and Javadocs are files that don’t belong to version control.
Don’t Commit Half-Done Work
You should only commit code when it’s completed. Split the feature’s implementation into logical chunks and remember to commit early and often. Use branches or consider using Git’s Stash feature if you need a clean working copy (to check out a branch, pull in changes, etc.).
On the other hand, you should never leave the office without committing your changes to a branch (on remote repository).
“It’s better to have a broken build in your local working repository on a branch than a working build on your broken hard drive.”
Test Before You Commit
You should only commit code which is tested and passes tests. And this includes code formatting with linters. Write tests and run tests to make sure the feature or bug fix really is completed and has no side effects (as far as one can tell).
Having your code tested is even more important when it comes to pushing/sharing your code with others.
Branching is one of Git’s most powerful features – and this is not by accident: quick and easy branching was a central requirement from day one. Branches are the perfect tool to help you avoid mixing up different lines of development.
You should use branches extensively in your development workflows: for new features, bug fixes and ideas.
Agree on a Workflow
Git lets you pick from a lot of different workflows: long-running branches, topic branches, merge or rebase, git-flow.
Which one you choose depends on a couple of factors: your project, your overall development and deployment workflows and (maybe most importantly) on your and your teammates’ personal preferences. However you choose to work, just make sure to agree on a common workflow that everyone follows.
Atlassian has done a good article of comparing workflows to suit your needs and covers centralized, feature Branch, git flow and forking workflows.
Using version control is usually and fortunately acknowledged best practice and part of software development. By using even a couple of the above practices makes working with the code much more pleasant. Adopting at least “Commit logical changesets” and “Reasonable Commit Messages” helps a lot.