5 things I learnt in 2020 for productive git collaboration.
Tags: github, git, codenewbie
Published: 2020-12-26 19:32:28

Until last year, I used git quite recklessly, writing bad commit messages and never taking a pause to think about the code and the manner in which it was being pushed. Things changed as I collaborated more and more with other developers for projects and after working with agile teams for over a year now, here are 5 things I have learned form my experience:

## 1. Keep your PR's "Atomic"
Let’s say you are working on designing the layout of your web app, and you were tasked with a simple bug fix in the same component. Though it is tempting to commit both the changes and to raise a PR together, our layout changes and the bugfix should go as separate PRs. By doing that you are creating an organized log of commits, which makes it easy for other developers to read and maintain the code base. It will also help your code reviewers, who can glance through the commit history and find what they are looking at easily. 

You should also be aware of what you are committing in your repository, and not just do `git add .` blindly every time and put it up in your PR.

## 2. Use branch workflows
Try to create and follow a git workflow within the team, the main advantage of doing so is that you will be keeping your development process organized and improving the overall code quality. A good git workflow ensures a clean state of branches at all times.

In my current project, we follow the feature-based git workflow and have 4 types of branch, each for a specific purpose:
1. master: "The golden copy" of the source code.

2. develop: The stable branch from where new branches are cut. How is this different from master? The master branch stores the official release history, and the develop branch serves as an integration branch for the features.

3. feature:  When we start working on a new feature, we cut off a feature branch for it from develop branch. For example, if we start working on a login page for a web app, we can create a branch as `feature-login`.
This helps in tracking the progress of user stories/defects in an agile development environment and also keeps your features separated in commit logs.

4. release: For every release, a new branch is cut and maintained. Why? Because the new additional features of v2.0, should not be present in v1.0. It is cut from develop branch when the release is production ready.

## 3. Mark incomplete commits with "WIP"
If you are not finished with the feature you have been working on by the end of the day, make a temporary commit with “WIP” appended to the message. This signifies that your commit is a “Work in progress”. When finished, one can squash all the commits in a single one and create the PR.

## 4. Give meaningful commit messages:
When you are ready with your changes and ready to make a commit, do your best to make it a meaningful one by giving a proper message. Before crafting a commit message, take a minute and put yourself in the shoes of your fellow developers seeing this change for the first time. Would you understand what code has changed in this commit? Would you know why the code changed?
Your commit message is supposed to convey these messages. I follow this pattern: 
```javascript
"[feature/defect id] - type: description"
```
The general types of commits one can encounter are as follow:
* feat - a new feature
* fix - a bug fix
* docs - changes in documentation
* style - everything related to styling
* refactor - code changes that neither fixes a bug or adds a feature
* test - everything related to testing

## 5. Write unit tests
One thing that I always ignored while learning programming was unit testing. If a developer performs proper unit testing, his defect density can drop significantly.
Writing unit tests forces us to consider how well the production code is designed in order to make it suitable for running our tests. It will also help you to code from a different perspective, encouraging you to consider corner cases and error conditions in the implementation. Most importantly, it identifies defects at early stages and also helps in safely refactor your code later, since tests can be re-run quickly to validate that behavior has not changed.