8 Git Best Practices
Sunday, February 28, 2021 • 4 minutes to read
The purpose of version control systems is to keep a history of a file’s changes or a very complex system consisting of thousands of files. That is it. Nothing more. When you are using it on your own, you could use it as you want, as long as it still serves its purpose and you could recall a specific version in history. However, when using distributed version control systems (DVCS), like Git, you should decide on some best practices, especially when using it as a team.
You could ask why to bother. Distributed VCS in contrary to local and centralized VCS, allow you to fetch the history of any remote repository and push it to any remote (bare) repository you want. While using DVCS, you have to remember that:
- you should not rewrite someone else history
- anyone could see and “use” your history
- you will be collaborating with others
This list by no means is the only and the right way of using Git. Please take it as a list of points you need to look at and take care of.
Decide which workflow you will use.
It does not matter whatever branching workflow you choose. It may be some long-running branches, topic branches, git-flow, gitworkflow, or something completely different. The most important is that you and your collaborators decide on one and stick to it. You should all know how the workflow works and what are its advantages and flaws.
Never commit directly to your main branch.
The previous point should already resolve this problem as I do not know any workflow which allows this, but I cannot stress this enough. It will always be a problem if you and your team commit to the master branch. Using branches is very cheap in distributed systems. Use branches and leave your main branch as a merge-only.
Do not change published history.
This is probably the worst thing you could do. Never, ever rebase or in any other way alter someone’s history or your published history. It breaks the only purpose of using version control systems. If the history is published and someone could use it, it must stay as it is.
Keep your working branches clean and readable.
This is somehow related to the previous point. Never publish your branch if it is not ready. Rebase your working branch often, use stashes, alter your branch history, or squash commits if necessary. Remember to do it before you publish your branch. It is no longer your branch after you do it, and you should not alter its history.
Commit only related changes.
Commit often and small. Commits should be atomic if possible. Your commits could, of course, have dozens of lines and change a lot of files, but all changes should be related. If you fix a bug, do not also commit some refactoring or coding style changes. Do not commit not finished changes. Use stashes and commit the least amount of lines that make sense together.
Write meaningful commit messages.
Start your commit message with a one-line (up to 50 characters) change’s description. In most cases, it would be enough but if necessary, add one empty line and then write more details. Make sure what you write makes sense and that your heading is clear enough if somebody is reviewing the history as one-liners. Also, write in the imperative tense. Do not write something like “Fixing bug”, “Updated”, or “Some more changes”. Use commit.style as a good starting point how your commit should look like.
Think about your messages as if somebody would read them in the following way: when applied, this commit will message. It should look like “when applied, this commit will fix the return value” or “when applied, this commit will add feature X”. It should not look like “when applied, this commit will changing the behavior of X” or “when applied, this commit will assorted grammar and typo fixes”. It makes a difference.
Do not commit any generated or configuration files.
Do not include in your repository and files which could be auto-generated or have any configuration values, especially API keys or passwords. Do not also commit vendor files. It includes but is not limited to node modules, NuGet packages, composer vendor files, or any other files you should manage using any of the dependency managers available for your technology stack. However, you should add and keep a history of
Test your code before you commit.
Run static code analysis tools if you use them. You could check the list of static code analysis tools for PHP, which I described a while ago. Run your automatic tests and test your changes manually. There is no reason to commit changes that you think works, and a couple of minutes later, revert the commit or make another one with another change.