Git: The perfect gitflow
Tags: git, beginners, tutorial, programming
Published: 2024-06-06 17:20:16

![henriqueleite42 GitFlow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/333pe61xp2s254brhrcl.png)

## Introduction

When we start to work with git, it's hard to understand how do you should work with branches correctly to avoid conflicts, have a nice and organized history and a project that it's easy to deploy and rollback if necessary.

In this article, I'll explain the best _gitflow_ that exists and why each of these parts are there.

## The core concepts

To worik with gitflow we must understand 2 core concepts: branches and merging strategies.

There are 3 types of branches:
- The main "branches"
- The feature branches
- The task branches

And 3 types of merge strategies:
- Merge
- Squash
- Rebase

## Branches

You can think of Git as a Tree, it has it's trunk and it's branches.

They are "copies" of the main system, so you can do all the changes that you want without altering the main content, so you can revert these changes, apply them other branches, and do a lot of cool stuff with it.

### The main "branches"

I recommend to have only one main branch on your repository, and not a `develop` and `production` branches. Why? Because branches are  **BRANCHES**! Ramifications of something that can (but shouldn't) follow different paths of the original, and not something to save a persistent state and never change again.

I 100% against using branches for `production` or release versions (branches like `v1.0.0` and similar), we have many other ways (correct ways!) to do it and we should avoid this workaround.

Git has support for [release tags](https://dev.to/neshaz/a-tutorial-for-tagging-releases-in-git-147e), which are pretty good to name your releases and know when something goes to production. They are kinda editable too, in case you need it, but it's always best to have immutable releases and release a fix if needed.

You also can use [Releases](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) in GitHub, that are very helpful to have a zip file with all your code, and also has lot's of integrations and automations.

So, to summarize:
- I recommend the use of **ONE** main branch, and for being a old timer, I call it `master`, but you can call it `main` if you prefer.
- In this article, I'll be using GitHub Releases, but if you use other remote repository, you can understand it as git tags.

### The feature branches

When we work in a [True Agile](https://dev.to/henriqueleite42/the-right-development-flow-better-than-agile-871) environment, we have features planned that must be implemented, like a feature to allow the user to create an account, in Scrum, they call these things "User Stories".

At the beginning of every cycle (or "sprint" if you use Scrum), it's created a new branch from the main branch with the pattern:

```c
// Pattern
feature/<ID in lowercase>/<description in lowercase>

// Example
feature/ant-1/create-account
```

This branch is created from the main branch and will group all the changes of this feature. After everything that the feature needs is merged and tested, the branch will be merged back to the main branch.

### The task branches

Task branches are sort-lived branches that apply specific changes needed to create that feature, like small pieces of that feature.

They can be understood as "Jira Tickets" or "Issues".

They are created from the FEATURE branches and merged on them.

```c
// Pattern
task/<ID in lowercase>/<description in lowercase>

// Example
task/ant-2/password-adapter
```

### Other branches and their prefixes

As you could have noticed in the previous topics, feature and task branches have different prefixes, but follow the same patterns.

Every other branch that isn't the main branch will have some kind of prefix, and the existent prefixes are:
```c
# Same level as feature branches
hotfix
feature
refact

# Same level as task branches
task
fix
refact
chore
cicd
```

You already know `feature` and `task`, but let know the other ones.

`hotfix`: Created to fix something urgently, usually things broken from the previous release that needs to be fixed in order to publish a new release because rollback is not an option.

`refact`: Changing a feature that already exists in the system, without affecting its behavior. The `refact` branch in the same level as a `feature` branch is used in order to refact a big portion of your system, a core feature, like user account creation, and not to refact a for loop.

`fix`: A bugfix that will follow the right flow of development, will be tested before merged, and will be merged with all the other things of the feature (what may take a while).

`refact`: The `refact` branch in the same level as a `task` branch is used in order to refact small portions of your code, affecting its behavior or not. These branches must be part of a feature, and can change things like your internal API to send messages to topics, improve the performance of a for loop, etc.

`chore`: Update in a comment, a development script, README, things that doesn't affect the code.

`cicd`: Updates in the pipelines, configurations for deploying.

## Merge strategies

Here I'll give a quick resume about the topic, but you can learn more in the [official documentation](https://git-scm.com/docs/git-merge).

The thing that we will focus on is: **squashing before merging**:
- Every task should have 1 commit when merging to a feature, so you **MUST ALWAYS** squash your commits before merging.
- Every feature should have 1 commit when merging to the main branch, so you **MUST ALWAYS** squash your commits before merging.

GitHub automatically squashes your commits for you if you configure it right:

![GitHub Pull Request config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86r20oz8k16qp3ddwybf.png)

But you can also do it with the CLI, see [the docs](https://git-scm.com/docs/git-merge#Documentation/git-merge.txt---squash).

## Extra tips

### Commit message pattern

I use [A simplified version of Clean Arch](https://dev.to/henriqueleite42/a-simplified-version-of-clean-arch-10i5) for my projects, from this i get the **layers**, and the pattern that i use for the commit messages is:
```c
// Pattern
<prefix>(<scope in lowercase>): <short description in lowercase>

// Examples
task(adapters): add foo adapter
fix(usecases): fix user creation
chore(docs): add details to readme
cicd(deploy): change deploy method
```

`hotfix`, `feature`, `refact`, `task`, `fix` use the [layers](https://henriqueleite42.hashnode.dev/a-simplified-version-of-clean-arch#heading-the-core-concepts) as the **scope**.

On the frontend web, you can use the names of the folders under `src` as the **scope**.

`chore` can use `docs`, `comments` or `naming` as the **scope**.

`cicd` can use `deploy`, `review` or `tests` as the **scope**.

Commits that fix PR comments doesn't need a special pattern since they will be squashed, you can use just `fix pr comments` or some message that you can kinda understand.

### Small teams

If you are working in a small team, there's no need to have [feature branches](#the-feature-branches), you can work directly with [task branches](#the-task-branches), this will decrease the complexity of your system.

## Advantages of this GitFlow

### A nice and clean commit history

In your main branch you will be able to see all the features that your software have and the evolution of it.

In your PR history, you will be able to see all the feature branches (this history is even better if you use the right labels to filter your PRs!), and all the branches and changes related to them.

### Standard

Everyone works in the same way because all of you have a standard to follow. It's easier to recognize patterns and understand the way that all teams work with git.

## GitFlow using [the best gitconfig](https://dev.to/henriqueleite42/git-config-5e35)

When using [the best gitconfig](https://dev.to/henriqueleite42/git-config-5e35), it's very, very easy to work with git:

```sh
# At the start of the cycle
git ckm
git cb feature/ant-1/create-account

# To start a task
git ck feature/ant-1/create-account
git pl
git cb task/ant-2/password-adapter

# When task finished
git acips task\(adapters\): add password adapter

# If you need to do any adjusts on your commit (even after the PR is created) you can run
git acaps task\(adapters\): add password adapter

# If there's comments on your PR and you need to fix them, create anoter commit
git acips fix pr comments

# Create the PR and it's done!
# To create another task, just start from "To start a task"
``` 

## Conclusion

Thanks for reading, I think that this article has everything that you need to know to be able to work with Git. If you have any thoughts, please feel free to share them with us in the comments! 😄