DEV Community

Ali Sherief
Ali Sherief

Posted on

Git branches best practices

While I'm getting code samples for the next part of my MomentJS series ready, I decided to write a short interlude post on how to create branches in Git that match your project's workflow.

Most of you probably know how to make branches, link remotes to them and push commits to them, but are you familiar with the naming conventions for each branch in your repository? If you are working on a medium or large-sized project, you need to have multiple branches in your git repository for managing your work. Here are some of the different groups of branches people create:

  • A branch for every feature you're working on, which when finished, is merged to master.
  • A branch for each release you make (only works if you don't have many releases)
  • A branch for each bugfix you're working on, merged to master when completed
  • Branches for each pull request slated to be merged, while you test each of them.

You don't have to follow all of these examples, or any of them for that matter. You need to decide which kind of branches are best for your project. But the main point I'm trying to make by displaying these examples is that you can't do all of these at once on a single branch. If you only commit everything on a signle branch, then when you're working on a feature and an unfinished part of it has been synced to the repository, someone might notify you about a high-priority bug, and now you're stuck because the feature completion can't be rushed.

Another drawback of committing everything to one branch is that it makes it harder to isolate the feature or bug that you're running a bisection test (git bisect) on. If there is unexpected behavior in your program, how do you know whether it's the code of a feature or the code of a bugfix that's causing the problem? Technically you can still find out which of them it is, but the task is needlessly harder than when you bisect a branch that's about a single bugfix or feature.

For these reasons, I will show what other teams are naming their branches and what they are using them for, and hopefully you will find a style that fits your project.

Image from nvie.com
(Note: image from nvie.com)

The master branch

Obviously you must have this branch in order to do anything in git, but this branch is reserved for large numbers of commits squashed/rebased together that make a new version number. As a result, all commits in the master branch have a version tag.

Release branches

An alternative to committing entire releases at once on master is to put each release in its own branch, and use those branches only for bugfixes and security patches, while the master branch can reflect the latest development state, eliminating the need for a separate catch-all develop branch.

This quickly becomes infeasible if you have dozens of releases though, so if you do have that many, then put the releases in tags on the master branch instead.

You should name your branches as the template release-VERSION NUMBER, and if it is a pre-release, make sure that you add the appropriate pre-release indicator (alpha, beta, rc1, rc2, etc.) at the end.

Feature and bugfix branches

Also collectively known as topic branches, create one of these for each feature you're working on. The biggest advantage of having one feature per branch is that many project maintainers require only one feature at a time to be submitted in pull requests, and in this case, the one feature per branch paradigm accommodates this perfectly.

You can also create topic branches for each bugfix you are working on. It works the same way as making a branch for a feature, except that these branches usually have a smaller number of commits. git log --graph --all --oneline is a handy way to visualize how many commits are in your topic branch.

In any case, when you're ready to merge the branch to master, make sure you rebase the branch so that you do not end up committing dozens of commits at once to master, bloating the repository. git rebase -i will flatten all of your commits to a single large commit, and it has a user interface that guides you through the process.

Don't merge between two topic branches. It shows that the features/bugfixes are interconnected and that they are better off as one branch.

You should name your branches as the template [GITHUB ISSUE/PR NUMBER] DESCRIPTION. That way, people can easily know what feature or bugfix this branch is implementing by looking at its name, and there is a corresponding issue or PR number that they can use to look up detailed information about the feature or bugfix. These branches are to be deleted after it's merged to master.

Atomic-sized features and bugfixes

Ultimately, topic branches need to be small. If they start getting too large, then that's a sign you're trying to fix too much in one topic and it needs to be split into multiple branches.

Also, check what you are explaining in the commit message details. If you are writing about several points, then chances are the commit is trying to implement multiple features or bugfixes at once.

A develop branch

Whether you need this depends on whether you want people to get the latest release of your software by cloning the master branch. If you do then you'll need to stage all of your pre-release development on a different branch.

Workflows for agile teams

Due to the nature of how agile teams continuously release new versions of their software, release branches and even version numbers are unsuitable for those projects. However, each software release needs to have a tag so that it can be cloned easily. A simply convention agile teams can use to tag their releases is using the current date and time. The releases can then be tested by QA teams at each tag, and from there marked as good or bad.

  • First you need to make an alias to quickly tag by date/time: git config alias.datetag '!git tagdate "+%Y%m%d%H%M"' This is not absolutely required, it just enables you to type git datetag which is much easier than typing the full command.
  • Now, each time you run git datetag, it will create a tag with the specific date and time as its name, nothing else, no prefix. This assumes that you set up your workflow so that the master branch (or whatever branch you are using to stage releases) only gets commits that are entire releases, so that a release tag can be applicable to every commit. If you go this route, you should probably use a branch other than master for this purpose so that you can pass its name to third party integrations like TeamCity.

And we're done

Let me know if you have any other tips for managing git workflows with many branches, I would love to hear them.


Sources:
http://dymitruk.com/blog/2012/02/05/branch-per-feature/
http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html
https://nvie.com/posts/a-successful-git-branching-model/
https://gitirc.eu/gitworkflows.html

Top comments (0)