DEV Community

David Johnson
David Johnson

Posted on • Originally published at davidisnotnull.Medium on

A decade of using git has taught me to keep a tidy house

My strategy to help look after your git

Image description

If you’re in the world of software development, then you’ll likely have come across this thing called “source control”.

I’m not going to delve into too much detail on what source control is, that’s not why you’re here. This is about my experience using one type of source control called git (as you can probably guess from the title).

I wrote this after one of my tenures as a Tech Lead in a digital agency. I was weary of seeing the word “fix” as the commit message, of having almost a hundred branches in some repositories, and being completely unable of working out what features or fixes had been included as part of a commit.

I’m putting the strategy below in the hope that it may help others who find themselves in a similar boat.

So Ctrl+C, Ctrl+V to your heart’s content.

Git Strategy

Wherever possible, these guidelines will include a specific justification for each strategy choice. Unjustified guidelines must be either justified or removed.

Whereas these styles draw mostly from the experience of the author, it also includes ideas from Vincent Dresden.

Fixing problems in this branching strategy

Unless otherwise stated, this branching strategy is not optional, nor is it up for interpretation.

  • If a guideline is not sufficiently clear, recommend a clearer formulation
  • If you don’t like a guideline, try to get it changed or removed; don’t just ignore it. Others might not be aware that you are special and not subject to the same rules as everyone else

Branching

Main Branches

At the base of our branching strategy are two evergreen branches —main, and _deve_lop.

Main, as the name suggests, is our stable branch, and reflects the latest delivered development changes that currently exist in the wild on our production environment. It should not be interacted with in our day-to-day development.

Develop should always represent the code that is being worked on, ready for the next release. It’s from this branch that we should be creating our feature and release candidate branches.

Both of these branches must be locked so that force pushes cannot be made to them (cue star wars pun), and standard pushes can only be made via approved pull requests.

Release Candidates

These branches contain code that has passed testing and is ready to be rolled out in the next release.

Release branches should be named release/

Where the release-identifier will be the name that we’ve given to this release in whatever task management tool we’re using.

As soon as the release candidate is ready to deploy to production, we raise a pull request to merge the release candidate into the main branch.

Feature Branches

A feature branch comes under the guise of Supporting Branches. These are used to allow for parallel development and to make tracking features easier.

Feature branches should be named feature/

Often, we will find ourselves using some sort of task management software, such as Jira. In this case, we need to be naming our feature branches with the identifier of the ticket, followed by a brief description of the what the feature contains. An example could be feature/DSB-545-marketing-preferences-service.

Highlander’s Law

If you’re old enough to remember that film with Christopher Lambert and Sean Connery, then you’ll probably guess what this is going to be…

There can be only one

Clearly, we aren’t lopping people’s heads off to cure ourselves of immortality. In this context, Highlander’s Law means that there should only ever be one feature branch for a particular story.

Never should we see two feature branches created by developers for the same feature. Not only is it deeply confusing for the poor bastard who has to put together a release candidate, but it’s really shoddy practise. One feature branch per feature please.

Hotfix Branches

A hotfix branch is branched from main, and should only be used to fix issues that are found in production. Due to the priority nature of hotfixes, they fall outside of the usual release cycle.

Hotfix branches should be named hotfix/

Once the code in a hotfix branch has been tested and verified, then we raise a pull request to merge the code into the main branch and release to production.

Managing code push/pulls

Fetch before you push

If someone else has been working on the same feature or hotfix branch as the one you’re about to push, make sure you do a fetch to ensure that you’re local copy is in line with what’s out there on the remote.

You can also turbo charge this process by doing some pruning at the same time:

git fetch origin --prune
Enter fullscreen mode Exit fullscreen mode

Rebase, don’t merge

If you’ve checked out a branch and, after doing a fetch, noticed that your local branch is a few commits behind what’s in the remote, don’t merge the remote into your local - rebase it. That way, you’re guaranteed to get a clean copy of what’s on the remote, including the commit history.

Pushing code

This one is simple:

NEVER push broken code to the remote repo

No one wants to fix your borked attempt at software development, so don’t do it. If it’s broken, it stays in local until you’ve fixed it.

Branch Retention

In order to keep the number of branches down to a minimum, it is important to do a little bit of housekeeping after each release to get rid of anything that’s no longer needed. This we call pruning.

Trust me, there’s nothing worse than opening a repository to see it has a hundred branches. Most of which are stale or no longer relevant.

Pruning

After each release, we must perform a branch pruning exercise. The rules of branch pruning are as follows:

  • If the release candidate branch is greater than 2 releases ago, then we need to delete it
  • If a feature branch has been merged into the current release branch, and it is 0 commits in front of develop, then we need to delete it
  • If we have merged a hotfix branch into master and it has been deployed to live after testing, then we need to delete the hotfix branch

Boglin Branches

If you grew up in the eighties or early nineties, you might remember something called a Boglin. It was like a gremlin, but lived in a swamp.

Boglin branches are those that are greater than 60 days old and are any number of commits in front of develop.

They also live in a swamp, of stale code. We have to ask ourselves, if a code change is greater than 60 days old, do we still need it? If we do need it, can we bring it into the upcoming release candidate?

If we don’t need it, prune it.

If we do need it, then there are two questions that need to be asked:

  • Why was it left idle for so long?
  • Can we get it tested and potentially bug fixed in time within the current sprint or release cycle?

Commit Messages

A well crafted git commit message is the best way to convey the context of a change to other developers, and your future self. Be kind to your future self, and adhere to the following rules for commit messages.

As an aside, I’m sick of seeing the word fix as a commit message. Stop it.

The rules of commit messages

Separate the subject from the body

Referring to the git commit manual:

Though not required, it’s a good idea to begin the commit message with a single short (less than 50 character) line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git. For example, Git-format-patch(1) turns a commit into email, and it uses the title on the Subject line and the rest of the commit in the body.

Proper casing on a commit message

I don’t think I need to explain any more than the heading for this section — make sure you capitalise the first word on the subject of the git commit, e.g.

Resolve merge conflicts from branch hotfix/BUG-1448

Do not end the subject line with a period

Trailing punctuation is not necessary on commit messages. Remember, space is precious when we are trying to keep within a 50 character limit.

Use the imperative mood in the subject line

Imperative mood simply means “spoken or written as if giving a command or instruction”. For example:

  • Tidy your room
  • Take out the bins
  • Do your laundry

Being British, we don’t like being outwardly direct or impolite. It’s perfect for commit subject lines, however. One reason for this is that git uses the imperative whenever it creates a git commit on your behalf, and computers aren’t renowned for their politeness (in some cases, neither are developers).

For example, whenever we do a merge using the git command line, we get:

Merging branch ‘feature/FEA-1234-new-navigation’

When you write in the imperative, all you’re doing is following git’s inbuilt conventions. The following are poor examples of subject messages:

  • Fixed bug with X
  • More fixes for broken stuff
  • Sexy new API methods
  • Changing structure of Y

No. This is what we call writing in the indicative mood. Being indicative is all about reporting facts, which is not what a commit subject should be — as counterintuitive as that sounds.

A properly formed git commit subject line should always be able to complete the following sentence:

If applied, this commit will [your git subject line here]

The following are good examples of commit subject lines:

  • If applied, this commit will remove deprecated methods
  • If applied, this commit will resolve merge conflicts
  • If applied, this commit will merge pull request #101 from feature/branch

You can see how our first few commit messages won’t work in the above format:

  • If applied, this commit will fixed bug with X
  • If applied, this commit will more fixes for broken stuff
  • If applied, this commit will sexy new API methods

Use the body to explain “what and why” versus “how”

When we’re looking at commit messages, we aren’t interested so much in how the change has been made, but the reasons for making the change.#

Here’s an example of a what I would deem a good commit body message:

Add CPU arch filter scheduler support

In a mixed environment of running different CPU architectures,

one would not want to run an ARM instance on a X86_64 host and

vice versa.

This scheduler filter option will prevent instances running

on a host that it is not intended for.

The libvirt driver queries the guest capabilities of the

host and stores the guest arches in the permitted_instances_types

list in the cpu_info dict of the host.

The Xen equivalent will be done later in another commit.

The arch filter will compare the instance arch against

the permitted_instances_types of a host

and filter out invalid hosts.

Also adds ARM as a valid arch to the filter.

The ArchFilter is not turned on by default.

Tagging Commits

When the code in a particular commit is released to either a test or production environment, we need to tag it. Otherwise, it’s easy to lose track of what code is sitting on what server.

My recommendation for this is to use the environment name, followed by a hyphen, followed by the date of the release in YYYYmmdd format. For example, this tag:

production-20230421
Enter fullscreen mode Exit fullscreen mode

Indicates that the code for this commit is on production, and was deployed on 21st April 2023.

Top comments (0)