Skip to content

Instantly share code, notes, and snippets.

@amir-saniyan
Last active August 1, 2026 16:42
Show Gist options
  • Select an option

  • Save amir-saniyan/735c3fd4d2b94804ec91e13bd40e3065 to your computer and use it in GitHub Desktop.

Select an option

Save amir-saniyan/735c3fd4d2b94804ec91e13bd40e3065 to your computer and use it in GitHub Desktop.
Modern Git Workflow on GitHub

Modern Git Workflow on GitHub

Based on: GitHub Flow + Conventional Commits + Squash Merge + Semantic Versioning

1. Core Philosophy

  • One permanent branch: main
  • All work happens in short-lived branches
  • No direct push to main
  • Pull Requests are required for all production changes
  • Clean, linear history via Squash and Merge
  • Branches are deleted after merge or rejection
  • Releases are tagged from main
  • Experimental work is isolated from production history

The repository uses a main-first development model:

main
|
+-- short-lived branches
|
+-- merge into main
|
+-- or delete if rejected

2. Branching Model

Naming Conventions

Prefix Purpose Commit Type
feature/ New functionality intended for production feat
bugfix/ Fixing non-critical bugs fix
hotfix/ Critical production fixes fix
experiment/ Research, evaluation, uncertain changes experiment
spike/ Short technical investigation / proof of concept spike
prototype/ Early prototype implementation prototype
chore/ Maintenance, dependencies, cleanup chore
docs/ Documentation updates docs
refactor/ Code restructuring without behavior change refactor
test/ Adding or updating tests test
ci/ CI/CD pipeline changes ci
perf/ Performance improvements perf
build/ Build system changes build
security/ Security-related fixes security
release/ Release stabilization (temporary)

Branch Types

Production Branches

These branches contain changes expected to reach main.

Examples:

feature/login
bugfix/fix-parser
hotfix/security-patch

Lifecycle:

feature branch → push → PR → review → squash merge → main → delete branch

Experimental Branches

Experimental branches are used for work where the final decision is unknown.

Examples:

experiment/viewer-integration
experiment/new-parser
experiment/wasm-threading

Typical use cases:

  • Evaluating a new library
  • Testing a new architecture
  • Performance investigation
  • Technology comparison
  • Proof of concept
  • Temporary prototypes

Experimental branches:

  • May never be merged
  • Do not require a clean commit history
  • Can contain incomplete code
  • Can be deleted at any time

Lifecycle:

experiment branch
|
|
+---- successful
|          |
|          v
|     create feature branch
|          |
|          v
|     PR + squash merge
|
|
+---- rejected
|
v
delete branch

Spike Branches

A spike is a very short technical investigation.

Examples:

spike/test-viewer-performance
spike/evaluate-wasm-memory
spike/test-rust-parser

Purpose:

Answer technical questions quickly:

  • Is this possible?
  • Is the performance acceptable?
  • Does this library fit our architecture?

A spike usually produces:

  • Knowledge
  • Benchmarks
  • Prototype code

It does not necessarily produce production code.

Experiment vs Feature

Use:

feature/

when:

"We believe this belongs in the product."

Use:

experiment/

when:

"We need to learn whether this belongs in the product."

Example:

experiment/viewer-integration

After validation:

feature/viewer

is created with only the required production-quality code.

Branch Naming Rules

  • Use lowercase
  • Use kebab-case
  • Keep names short and descriptive

Good:

feature/file-browser
experiment/viewer-integration
spike/test-reader

Bad:

Feature/NewFileBrowser
my_test_branch
experimentalStuff

3. Repository Setup (Recommended)

Before the team starts, configure these on GitHub:

  • Branch Protection Rule on main (block direct push)
  • Required Reviewers (minimum 1 approval before merge)
  • Required CI checks must pass before merge
  • Auto-delete branches after merge
  • PR Template (.github/PULL_REQUEST_TEMPLATE.md)
  • CODEOWNERS (.github/CODEOWNERS) for automatic reviewer assignment

4. Pull Request Workflow

Production Feature Workflow

1. Create branch from main

git checkout main
git pull

git checkout -b feature/login

2. Commit using Conventional Commits

git commit -m "feat: add login system"

3. Push branch

git push -u origin feature/login

4. Open PR

  • Use Draft PR for incomplete work
  • Mark Ready for Review when complete

5. Review and CI

Requirements:

  • Code review approved
  • Tests passed
  • CI successful

6. Squash and Merge

feature branch
        |
        v
    squash merge
        |
        v
      main

7. Delete branch

The branch is automatically deleted after merge.

5. Experimental Workflow

Experimental branches do not always require PR merge.

Example:

git checkout main
git pull

git checkout -b experiment/viewer-integration

Commit:

git commit -m "experiment: evaluate viewer integration"

Push:

git push -u origin experiment/viewer-integration

Possible outcomes:

Success

Create a production feature:

git checkout main
git checkout -b feature/file-browser

Move only production-ready code.

Failure

Delete the branch:

git push origin --delete experiment/viewer-integration

The experiment remains only in Git history if needed.

6. Hotfix Workflow

For critical production bugs.

main → hotfix/* → PR → squash merge → main → tag

Steps

  1. Branch directly from main:
git checkout main && git pull
git checkout -b hotfix/fix-critical-crash
  1. Apply the fix

  2. Open PR to main (expedited review — minimum 1 reviewer)

  3. Squash and Merge

  4. Tag immediately on main:

git tag v1.4.3
git push origin v1.4.3

7. Release Workflow

Most modern teams release directly from main using tags. Release branches are optional — use them only when stabilization requires multiple coordinated fixes.

Option A: Tag from main ✔ Recommended

feature PR → squash merge → main → tag → release
git tag v1.2.0
git push origin v1.2.0

Option B: Release Branch (For Complex Stabilization)

main → release/v1.2.0 → final fixes → merge back to main → tag → delete
  1. Create release branch from main:
git checkout -b release/v1.2.0
  1. Apply only bugfixes — no new features

  2. Merge back into main:

git checkout main
git merge release/v1.2.0
git push
  1. Tag on main:
git tag v1.2.0
git push origin v1.2.0
  1. Delete release branch:
git branch -d release/v1.2.0
git push origin --delete release/v1.2.0

release/* is temporary. It exists only for stabilization, then it is deleted.

8. Commit Message Convention (Conventional Commits)

Format

type(scope): description

or:

type: description

Rules

  • ✔ lowercase
  • ✔ imperative mood (add, fix, update)
  • ✔ no period at end
  • ❌ no uppercase types
  • ❌ no full sentences

Commit Types

Type Meaning
feat New feature
fix Bug fix
experiment Experimental investigation
spike Technical exploration
prototype Prototype implementation
chore Maintenance
refactor Code restructuring
docs Documentation
test Tests
ci CI/CD
perf Performance
build Build system
security Security fixes

Examples:

feat: add genome browser
fix: handle empty vcf file
experiment: evaluate viewer integration
spike: benchmark wasm parser
chore: update dependencies
refactor: simplify parser interface
docs: update architecture guide

Breaking Changes

feat!: redesign authentication API

BREAKING CHANGE: token format has changed from JWT to opaque token

Commands

git tag v1.2.0
git push origin v1.2.0

9. Tagging & Versioning (SemVer)

Format:

MAJOR.MINOR.PATCH

Rules

Change Type Version Update Example
fix PATCH 1.4.21.4.3
feat MINOR 1.4.21.5.0
Breaking change MAJOR 1.4.22.0.0

10. Changelog (Keep a Changelog)

Reference: https://keepachangelog.com/en/1.1.0/

Example:

## [1.2.0] - 2026-06-12

### Added

- login system via OAuth

### Fixed

- crash on startup with empty config (#102)

### Security

- patched XSS vulnerability in input fields

11. Summary

main
 |
 +-- feature/*
 |       |
 |       +-- PR
 |       +-- squash merge
 |
 +-- bugfix/*
 |
 +-- hotfix/*
 |
 +-- experiment/*
 |       |
 |       +-- convert to feature
 |       +-- or delete
 |
 +-- spike/*
         |
         +-- knowledge gained
         +-- prototype discarded
Practice Recommendation
Branching model GitHub Flow
Permanent branches main only
Feature development feature/*
Research work experiment/*
Technical investigation spike/*
Merge strategy Squash and Merge
Commit format Conventional Commits
Versioning Semantic Versioning
Changelog Keep a Changelog
Release Tag from main (release branch optional)
Branch protection Required on main
PR review Minimum 1 reviewer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment