Skip to content

Instantly share code, notes, and snippets.

@digitaljhelms
Last active December 20, 2024 19:57
Show Gist options
  • Save digitaljhelms/4287848 to your computer and use it in GitHub Desktop.
Save digitaljhelms/4287848 to your computer and use it in GitHub Desktop.
Git/GitHub branching standards & conventions

Branching

Quick Legend

Instance Branch Description, Instructions, Notes
Stable stable Accepts merges from Working and Hotfixes
Working master Accepts merges from Features/Issues and Hotfixes
Features/Issues topic-* Always branch off HEAD of Working
Hotfix hotfix-* Always branch off Stable

Main Branches

The main repository will always hold two evergreen branches:

  • master
  • stable

The main branch should be considered origin/master and will be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. As a developer, you will be branching and merging from master.

Consider origin/stable to always represent the latest code deployed to production. During day to day development, the stable branch will not be interacted with.

When the source code in the master branch is stable and has been deployed, all of the changes will be merged into stable and tagged with a release number. How this is done in detail will be discussed later.

Supporting Branches

Supporting branches are used to aid parallel development between team members, ease tracking of features, and to assist in quickly fixing live production problems. Unlike the main branches, these branches always have a limited life time, since they will be removed eventually.

The different types of branches we may use are:

  • Feature branches
  • Bug branches
  • Hotfix branches

Each of these branches have a specific purpose and are bound to strict rules as to which branches may be their originating branch and which branches must be their merge targets. Each branch and its usage is explained below.

Feature Branches

Feature branches are used when developing a new feature or enhancement which has the potential of a development lifespan longer than a single deployment. When starting development, the deployment in which this feature will be released may not be known. No matter when the feature branch will be finished, it will always be merged back into the master branch.

During the lifespan of the feature development, the lead should watch the master branch (network tool or branch tool in GitHub) to see if there have been commits since the feature was branched. Any and all changes to master should be merged into the feature before merging back to master; this can be done at various times during the project or at the end, but time to handle merge conflicts should be accounted for.

<tbd number> represents the project to which Project Management will be tracked.

  • Must branch from: master
  • Must merge back into: master
  • Branch naming convention: feature-<tbd number>

Working with a feature branch

If the branch does not exist yet (check with the Lead), create the branch locally and then push to GitHub. A feature branch should always be 'publicly' available. That is, development should never exist in just one developer's local branch.

$ git checkout -b feature-id master                 // creates a local branch for the new feature
$ git push origin feature-id                        // makes the new feature remotely available

Periodically, changes made to master (if any) should be merged back into your feature branch.

$ git merge master                                  // merges changes from master into feature branch

When development on the feature is complete, the lead (or engineer in charge) should merge changes into master and then make sure the remote branch is deleted.

$ git checkout master                               // change to the master branch  
$ git merge --no-ff feature-id                      // makes sure to create a commit object during merge
$ git push origin master                            // push merge changes
$ git push origin :feature-id                       // deletes the remote branch

Bug Branches

Bug branches differ from feature branches only semantically. Bug branches will be created when there is a bug on the live site that should be fixed and merged into the next deployment. For that reason, a bug branch typically will not last longer than one deployment cycle. Additionally, bug branches are used to explicitly track the difference between bug development and feature development. No matter when the bug branch will be finished, it will always be merged back into master.

Although likelihood will be less, during the lifespan of the bug development, the lead should watch the master branch (network tool or branch tool in GitHub) to see if there have been commits since the bug was branched. Any and all changes to master should be merged into the bug before merging back to master; this can be done at various times during the project or at the end, but time to handle merge conflicts should be accounted for.

<tbd number> represents the Basecamp project to which Project Management will be tracked.

  • Must branch from: master
  • Must merge back into: master
  • Branch naming convention: bug-<tbd number>

Working with a bug branch

If the branch does not exist yet (check with the Lead), create the branch locally and then push to GitHub. A bug branch should always be 'publicly' available. That is, development should never exist in just one developer's local branch.

$ git checkout -b bug-id master                     // creates a local branch for the new bug
$ git push origin bug-id                            // makes the new bug remotely available

Periodically, changes made to master (if any) should be merged back into your bug branch.

$ git merge master                                  // merges changes from master into bug branch

When development on the bug is complete, [the Lead] should merge changes into master and then make sure the remote branch is deleted.

$ git checkout master                               // change to the master branch  
$ git merge --no-ff bug-id                          // makes sure to create a commit object during merge
$ git push origin master                            // push merge changes
$ git push origin :bug-id                           // deletes the remote branch

Hotfix Branches

A hotfix branch comes from the need to act immediately upon an undesired state of a live production version. Additionally, because of the urgency, a hotfix is not required to be be pushed during a scheduled deployment. Due to these requirements, a hotfix branch is always branched from a tagged stable branch. This is done for two reasons:

  • Development on the master branch can continue while the hotfix is being addressed.
  • A tagged stable branch still represents what is in production. At the point in time where a hotfix is needed, there could have been multiple commits to master which would then no longer represent production.

<tbd number> represents the Basecamp project to which Project Management will be tracked.

  • Must branch from: tagged stable
  • Must merge back into: master and stable
  • Branch naming convention: hotfix-<tbd number>

Working with a hotfix branch

If the branch does not exist yet (check with the Lead), create the branch locally and then push to GitHub. A hotfix branch should always be 'publicly' available. That is, development should never exist in just one developer's local branch.

$ git checkout -b hotfix-id stable                  // creates a local branch for the new hotfix
$ git push origin hotfix-id                         // makes the new hotfix remotely available

When development on the hotfix is complete, [the Lead] should merge changes into stable and then update the tag.

$ git checkout stable                               // change to the stable branch
$ git merge --no-ff hotfix-id                       // forces creation of commit object during merge
$ git tag -a <tag>                                  // tags the fix
$ git push origin stable --tags                     // push tag changes

Merge changes into master so not to lose the hotfix and then delete the remote hotfix branch.

$ git checkout master                               // change to the master branch
$ git merge --no-ff hotfix-id                       // forces creation of commit object during merge
$ git push origin master                            // push merge changes
$ git push origin :hotfix-id                        // deletes the remote branch

Workflow Diagram

Git Branching Model
gitflow-model.src.key

Other Material

@digitaljhelms
Copy link
Author

@dvgcode if you read both, you'll find obvious differences, and the diagram is quite different; the strategy here uses master as the working branch, and does not use "release branches". Thanks for the feedback, though.

@shx99717
Copy link

thanks, it explains in detail about the branching model, great work.

@pavel-rossinsky
Copy link

Nicely explained, thank you!

@minop1205
Copy link

minop1205 commented May 3, 2020

Thank you. it's a great post!
I translated to japanese and adoptioned it to my branching rules.
https://gist.github.com/minop1205/b87a1f5ffab6d8af28a66aca64378171

@rokuingh
Copy link

Any plans to update master to main/default/primary?

@manoellribeiro
Copy link

manoellribeiro commented Sep 29, 2020

Thank you, it really helped me!!

@tahiralvi
Copy link

the diagram is really helpful to understand the working phenomena.

@mrdulin
Copy link

mrdulin commented Feb 2, 2021

How can I name it if the branch is for adding more unit tests?

@allenlooplee
Copy link

Thanks for sharing. Gonna use this as a starting point to manage my branches.

@mustafadalga
Copy link

Understandable resource, thank you!

@halws
Copy link

halws commented Mar 7, 2021

@digitaljhelms Could you please update model image's url, because it's unavailable now?

@dragongling
Copy link

Why features are named as topic-* in Quick Legend, but feature-* everywhere else?

@halws
Copy link

halws commented Mar 24, 2021

@dragongling

Why features are named as topic-* in Quick Legend, but
feature-* everywhere else?

Word 'topic' here has two meanings:

If branch is for new feature then 'topic' is 'feature', for example [feature]-new-auth

If branch is for bug fix then 'topic' is 'bug', for example [bug]-missed-email-input (without [] of course)

At least this is how we use it🙂

@dragongling
Copy link

@halws thanks!

@digitaljhelms
Copy link
Author

@digitaljhelms Could you please update model image's url, because it's unavailable now?

@halws done, sorry about that... I was linking the diagram & Keynote source to a cloud storage service that I deactivated because I never used it; forgot it was hosting the files for this gist. 🤦‍♂️

@digitaljhelms
Copy link
Author

digitaljhelms commented Mar 25, 2021

Additionally, I updated the tagging approach to reflect proper semantics (1.0 → 1.1 for hotfix) and I corrected the arrow direction for the first 1.0 tag (was master ← stable, now master → stable).

@RajeshChouhan21
Copy link

As per the Industry standard, Who should merge the code to the Master branch

  1. Development team Lead
  2. Release Management team
  3. Manager
  4. suggest if any other

@digitaljhelms
Copy link
Author

@RajeshChouhan21 this gist is not intended to cover branch ownership permissions or development workflows, those things you should determine based on your project, team, needs, et al.

@iq220
Copy link

iq220 commented Sep 8, 2021

Build once deploy many. I can’t get my head around which branch automated builds should come from. If done on dev branch then it means master is never built from unless breaking the build once work flow . Suggestions or maybe what I am missing?

@egberts
Copy link

egberts commented Sep 20, 2021

Does not help when Guthub GH CLI tool leaves us in a wonky state when we do a “gh repo create XXXX” to create an empty repository and forces us to name the “master” branch.

And worse off, leaves us headless no-GUI server admin, with wonky PAT re-integration.

Cannot even create a PAT in GUI-less land (using links or curl).

once we populated the repo with files, we get a mysterious “Error 128” at the time of “git push” or “gh repo sync” after first git commit.

Screw this multiple but unintuitive breakages. Github is now read-only to me. Moving on to Gitlab.

@Estifanos-Neway
Copy link

Very helpful, thank you.

@renatocfrancisco
Copy link

main >>>> master

@dragongling
Copy link

@renatocfrancisco IMO it's better to rename "main" or "master" to more meaningful name immediately, I usually name it "develop"

@digitaljhelms
Copy link
Author

@renatocfrancisco @dragongling IMHO feel free to debate master branch name semantics elsewhere, I loathe the topic.

@digitaljhelms
Copy link
Author

digitaljhelms commented Nov 30, 2022

Build once deploy many. I can’t get my head around which branch automated builds should come from. If done on dev branch then it means master is never built from unless breaking the build once work flow . Suggestions or maybe what I am missing?

@iq220 the "build once deploy many" paradigm aligns more to Gitflow, both being a more antiquated approach to CI/CD IMO; this strategy probably won't work for that kind of build/release workflow.

FWIW, though antiquated I reluctantly still work on very large projects/teams (100's of developers, multi-national online real estates) that employ the "build once deploy many" paradigm and Gitflow strategy, so they're not dead by any means, just not nearly as flexible or expedient as more modern strats (and even the strat in this gist isn't as good as it could be, maybe I'll write another gist about that).

@bipon68
Copy link

bipon68 commented Dec 6, 2022

Nice explanation, thank you!

@pg
Copy link

pg commented Apr 21, 2023

Thanks for the concise, clear explanation.

@Ishu-999
Copy link

Thanks for the best and clear explanation. 🙏

@ollienicholson
Copy link

Much appreciated!

@InsaneLuv
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment