The purpose of this article is to create a manual to git with a set of rules and strategies that we share to boost productivity and avoid confusion.
Git is software for tracking changes in any set of files, it is mainly used for coordinating work among programmers collaboratively developing source code during software development. Generally speaking, Git is a distributed version control system (DVCS), or peer-to-peer version control system, as opposed to centralized systems like Subversion.
When you install git on your machine you can create your first git repository or reinitialize an existing one by simply running the
git initcommand in a directory of your choice, this will create a
.git directory where Git stores all of the data/metadata. Now if you run
git init then you can get an inspection of the repository. It won’t display much at this stage
$ git status
On branch masterNo commits yetnothing to commit
But we get the following information, first, the branch we are on
masterby default, second the commits history, and last the changes to commit. The output presents the status of the working tree (also called the working directory) as well as the status of the index (also called staging area).
A Git project consists of three major sections/areas: the working directory, the staging area, and the git directory. The working directory is where we add, delete, and edit files think of it as your workspace that has the current state of files. Then, the changes are staged (or indexed) in the staging area think of it as a place where you temporarily wanna save your work. After you commit your changes, the snapshot of the changes will be saved into the git directory (locally).
We previously mentioned that the default branch is
master when we first initiate the Git repository. First, let’s understand what a branch means.
In Git branches allow developers to isolate their work from others by creating new branches from the original codebase. A branch is an independent line of development. It works as a pointer to your next commit. Whenever a new branch is created, Git creates a new pointer while keeping the original code base untouched. You can arbitrate your changes to the branch of your choice, and you can also switch/checkout over from one branch to the other. The creating, naming, and relationship between branches can be customized to your preferences but when working in a huge team of developers, confusion is likely to happen and the code maintenance team suffers numerous confusions and complications. This is why we consider creating a branching strategy, it represents a conversion or set of rules that specify when branches get created. It helps teams and developers by describing the naming guidelines of branches and what branches represent and do.
We consider two broad categories of Git branches:
- Regular branches (or main branches): these branches are available permanently in the repository, the naming convention of regular branches is easy and straightforward, we can mention
- Temporary branches (or support branches): these branches are created by team members and they serve a purpose and once purpose fulfilled they can be deleted, we can mention
One of the known branching strategies is GitFlow. Gitflow is a branching model for Git, created by Vincent Driessen. It has attracted a lot of attention because it is very well suited to collaboration and scaling the development team. This is the model we are going to rely on to create our branching strategy.
At the core, the main branches are:
- master: the master branch is the origin, and we consider origin/master to be the main branch where the source code of HEAD always reflects a production-ready state.
- develop: We consider origin/develop to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the integration branch.
Next to the main branches, the Gitflow model uses a variety of supporting branches to aid parallel development between team members, ease tracking of features, prepare for production releases, and to assist in quickly fixing live production problems.
Feature branches: Feature branches (or sometimes called topic branches) are used to develop new features for the upcoming or a distant future release. When starting the development of a feature, the target release in which this feature will be incorporated may well be unknown at that point. The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop.
May branch off from: develop
Must merge back into: develop
Branch naming convention: anything except master, develop, release-*, or hotfix-*
Release branches: Release branches support the preparation of a new production release. They allow for minor bug fixes and preparing meta-data for a release (version number, build dates, etc.). By doing all of this work on a release branch, the develop branch is cleared to receive features for the next big release. The key moment to branch off a new release branch from develop is when develop (almost) reflects the desired state of the new release. At least all features that are targeted for the release-to-be-built must be merged in to develop at this point. All features targeted at future releases may not — they must wait until after the release branch is branched off.
May branch off from: develop
Must merge back into: develop and master
Branch naming convention: release-*
Hotfix branches: Hotfix branches are very much like release branches in that they are also meant to prepare for a new production release, albeit unplanned. They arise from the necessity to act immediately upon an undesired state of a live production version. When a critical bug in a production version must be resolved immediately, a hotfix branch may be branched off from the corresponding tag on the master branch that marks the production version. The essence is that the work of team members (on the develop branch) can continue, while another person is preparing a quick production fix.
May branch off from: master
Must merge back into: develop and master
Branch naming convention: hotfix-*
Adapting Gitflow to the deployment environment
We generally have three deployment environments where the project is deployed and executed: development (recette or r7 in French), pre-production, and production tier. The correspondence of Gitflow with these environments is as follow:
- Development: this is the environment in which the developers get to test and see their code running altogether, that’s why use the develop branch.
- Pre-production: this environment presents the before-production state in which we have a stable tested version of the application, so for this environment, we use one of the release branches.
- Production: this is also the client environment, is the recent stable version of the application and we only upload make changes in the final phase of the development of a feature or features. We use the master branch for this environment.
Below is how we generally use each environment:
Naming conversions of supporting branches
There are multiple choices of naming that can be used to name the supporting branches, it can be hyphens, slashes, or underscores to separate words, we can use dates or issue trackers ID. To have a consensus we created the following rules:
- We separate the branch's name from the rest of the naming with a slash (hotfix/, feature/, release/).
- In the case of features branches, we add the scope of the feature right after the slash for example feature/authentification.
- In the case of issue tracker software (like mantis), we can add the ID of the issue to the name of the branches of feature or hotfix, for example, hotfix/mantis.7589.
- We can also use the date as a reference to the release branches as release/YYYY.MM.DD if we have multiple consecutive versions.
The perfect commit
A commit message can greatly help developers track and understand the commits. It can save a lot of time if written well. The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of.
A perfect commit message should be structured as follows:
<type>[optional scope]: <description>
There are exist nine types of commits:
- build: when changes affect the system of build or external dependencies (npm, make, pip … ).
- ci: when changes concern files and scripts of the continuous integration (Travis, Ansible …).
- feat: when new functionality is being added.
- fix: when a bug is being fixed.
- perf: when performances are being improved.
- style: changes that improve the code by add no functional or semantic improvement (indentation, spaces, names of variables, comments …).
- docs: the changes in the documentation of the code (wiki, README …).
- test: the add or change of tests of the code.
The scope represents the part/module of the application, it helps us identify the part of the application that was affected. In the context of e-commerce applications, we can have scopes like product, card, or checkout … However it is facultative to specify the scope because we can have the scope in the branch’s name.
The description is a summary of the changes added. we generally limit it to 50 characters.
Bonus: Git commands cheat sheet
In this paragraph, we list some of the most used Git commands