A practical, detailed guide to Git branching strategy, issue creation and merging

A practical, detailed guide to Git branching strategy, issue creation and merging


I would like to ask for an explanation about git best practices. Like git branching, naming branches etc

Sidenote- why does all this matter & why should I care about issues, git and branching?

Have you ever..

  • Not had enough information about an issue/bug?

  • Struggled to find a link to something? Don't have enough context?

  • Scared of a merge conflict? Confused about rebasing?

  • Not sure which issue the pull request is fixing?

Projects without standard procedures around issue creation and connecting that to git branching don't succeed, they eventually
grind to a halt and are left burning time & money away with 'issue management synchronisation tooling'.

None of these tools are needed. Tools cannot save you, the following disciplines can, and everyone can do it- it just relies on these effective communication strategies.


0. Always start with an issue, not code

Contributions, changes, feature requests, & bug reports, must start with creating an issue, even if a tiny change. This gives you an issue number to use later on, and helps you & others quickly understand which issue a branch and commits relate to.

A branch, commits, (and the eventual pull request) are easily related to their issue(s) because you should name branches according to the issue number, and make commits
referencing the issue number (e.g. 123-fix-css-margin-footer). Such linking is mandatory because a reviewer must be able to relate the new code to the issue being fixed.

See also: Always start with an issue.

Here's a walk through of the entire process:

In this scenario you're about to work on a new issue, an issue has been created, and the issue number is 123.

You read the issue. If anything is unclear, such as a blank issue with a very vague title- then do not proceed to coding.

Instead, fail the issue as 'needs more information', and go find that information if you don't have it- it's everyone's responsibility to create clear issues.

If this seems extreme, consider the alternative- you proceed, not truly understanding the issue, code something for a few hours (days?) only to find the issue is:

  • no longer needed
  • a different problem to what was assumed
  • tldr: Don't assume something you can check, and update issues when new information comes to light

If a sufficient issue is written, time to start branching!

1. Always branch off of the main branch

You'll likely have been busy working on a different issue, and it's likely other people have contributed changes to the main
branch whilst you were doing other work. You need to keep fetching & applying those changes to your local main branch. You
need to develop the habit of doing this often because the longer / further you stay behind the more irrelevant / out of date your
main branch is.

Question: What is trunk what is main and what is master anyway?

Answer: They're all the same- whichever branch holds your deployed code. In some
companies this might be called prod , main, master- they're just names, the key
point is to always branch off of the main branch when you start new work on a new issue, because that's where the latest code is. Some people like the word trunk because it comes from the idea of a tree trunk 🌳, and all tree branches come out of the main trunk. The key point is that you only ever create new branches off of the top of the trunk, which has the latest code (trees grow up).

Because your main branch may be out of date, update it with the latest code:

  1. Fetch the latest changes from main: git fetch
  2. Checkout to main branch: git checkout main
  3. git fetch origin fetches all changes into your local .git folder , but it does not change your files yet.
  4. git pull origin/main (this does change your files and brings them up to date with main)

    Note you could do git rebase origin/main here also

  5. Create a new branch for the issue, using the number git checkout -b -name-of-issue e.g:

    git checkout -b 123-fix-css-margin-footer

    The above creates a new branch, off of the main branch. Remember, you're currently on the main branch, which is good because it contains the most up to date code because you just fetched and pulled

2. Push your blank issue branch & raise a PR right away (what?!)

Go to GitHub/GitLab/etc and raise a pull request for your new issue branch, which has no new code in it- yes really.

But why push a blank branch?

Pushing a blank branch should start your continuous integration (CI) pipelines and tests- which should all pass.

It is very valuable to start a new issue branch, raise a new PR and observe all checks pass before adding code because it establishes a baseline of all green in your CI & tests βœ…βœ…βœ….

If you see red at this point, this is a stop the production line moment- of course you can keep coding if someone else is investigating the CI build failures (but have you told them?).

git push origin 123-fix-css-margin-footer

Don't fall into the trap of coding away for days/weeks without pushing. If you work in a team, and you have a team lead- they'll be better informed if they have the possibility of seeing your code early in the process, and may even realise a different solution with you, saving you hours of your valuable time getting wasted.

Even if you don't work in a team- give yourself the early feedback that nothings wrong initially, and all your tests + CI pipelines are passing on this new branch.

It's not okay to release to production with CI build failures in testing, and ultimately that will need resolving before your PR may be merged.

2.5. Write a test to re-create the issue

Where reasonable, write a test which captures the issue. The test should fail to show the bug exists (and may give you a good idea of what might be the cause).

Keep pushing- at this point, you should see your beautiful pull request CI tests go from green βœ… to red ❌ because your test should be failing.

3. Code the fix/feature on this new branch- pushing little and often

Do your investigations/coding, creating small commits which reference the issue e.g. if you updated index.html file

git add template.html (or whichever files you changed)
# Commit your change
git commit -m "#123 wip css bug in footer"

When you use the "#" in a commit message, GitHub/GitLab/etc automatically shows a link to the related issue on GitHub/GitLab/etc issue. This is very useful for seeing the issue/code relationship. No fancy/expensive plugins needed.

When you say git commit -m "Fix #<issue-number> my comment about the code ", the issue gets closed automatically if the commit is merged into main on most systems (Git, Gitlab etc), (which saves time no longer needing to check 'is this issue closed?' etc).

4. Keep your issue branch up to date with main as you go

It's tempting to code away on your issue, forgetting that other code may get merged into main from another issue. You'll want to say up to date with those upstream changes.

tldr: Keep git fetching & pulling changes from main into your issue branch to stay up to date. This saves you time and pain in the long run because you learn about potentially breaking changes your fix will need to account for.

git pull origin/main (applies those changes to your current branch)

Pushing your issue branch:

git push origin 123-fix-css-margin-footer

5. Release the fix/feature, finally!

You'll know when you're ready to consider if you're done because you're:

  • Pushing little and often
  • Your CI checks should move from failing ❌ to passing βœ… again
    • That is, the new test you wrote, if present, should be passing

Since you've already raised a pull request, all that's left to do is ask for a final review & merge!


Should I delete my branch?

No. There is no need to delete the branch remotely because branches are copy on write (very tiny file size) but locally you might want to delete them if you have hundreds or don't want to see them anymore (git branch -d)

Tip: It's normally a bad idea to delete a branch 10mins after raising a pull request, because you might need to add things later on. You can always get the branch back, it takes seconds, but it's a hassle. Just keep the branch locally, it's not causing any problems, it's helping you because you might want to go back to it in a few weeks.

Should I force push?

Never use force push if your working with others on a branch, it may destroy their work, and you'll have to dig through git reflog to get things back if possible. If you're not 100% sure, don't ever use force push. It's rarely what you want to do.

What about tagging multiple branches with a release 'tag?

No. The point is that branches are short lived. There is no long lived 'tagged' release branch. production (the latest commit to main) is the released version. If you are selling your software to multiple different customers who self install- then then this process is not sufficient (because you don't control their release process) but if you do, don't pin yourself to long long-lived tagged releases. Don't cherry pick into a 'release' branch- prod if the release branch already, and your pull request reviews, CI/CD process should have checks & balances in place to operate in that way.

See also above: A source-control branching model, where developers collaborate on code in a single branch called β€˜trunk’ *, resist any pressure to create other long-lived development branches by employing documented techniques. They therefore avoid merge hell, do not break the build, and live happily ever after.
Collect recurring payments with Subscribie - Try Now