GitHub Workflows

Purpose

GitHub Workflows describes the social and process layer on top of Git: how teams branch, review, merge, and release code using GitHub features. The dominant patterns are GitHub Flow (simple, continuous delivery) and trunk-based development (advanced, high-frequency integration). Distinct from GitHub Actions which covers the automation/CI platform.

Architecture

GitHub Flow (default for most projects)

main  ────●─────────────────────────●──────────────────────►
           \                       /
  feature   ●──●──●  (open PR)  ●─●  (merge after review)
  1. Branch from maingit checkout -b feat/my-feature
  2. Commit small, focused changes
  3. Open PR → CI runs → reviewers approve
  4. Merge to main (squash, merge commit, or rebase)
  5. Delete branch; deploy from main

Trunk-Based Development

main  ────●──●──●──●──●──●──●──►    (commits every day, feature flags hide WIP)
  • Everyone integrates to main (or trunk) at least once per day
  • Feature flags control exposure, not long-lived branches
  • Requires strong CI and good test coverage
  • Scales well for large teams with high velocity

Release Branching (for versioned software)

main  ──●──●──●──●──●──●──────►
         \
 release  ●──● (cherry-pick hotfixes) ──► tag v1.0

For libraries, CLI tools, or products requiring versioned releases. Hotfixes are cherry-picked to both the release branch and main.

Implementation Notes

Pull Request Best Practices

Author checklist:

  • ≤ 400 lines changed per PR (smaller is more reviewable)
  • PR description states what changed and why (not how)
  • Link to issue or ticket
  • Include screenshots for UI changes
  • Self-review the diff before requesting review

Reviewer checklist:

  • Read the PR description first
  • Pull and run locally for non-trivial changes
  • Approve only when you could defend the code in production
  • Request changes rather than approving-with-comments if blocking issues exist

Branch Protection Rules

Configure under Repo Settings → Branches → Add Rule:

  • Require a pull request before merging — prevents direct pushes to main
  • Require status checks to pass — CI must be green
  • Require approvals — ≥1 or ≥2 reviewers
  • Dismiss stale reviews when new commits are pushed
  • Require linear history — enforces squash or rebase merges

Merge Strategies

StrategyEffectWhen to use
Merge commitPreserves all commits + merge nodeAudit trail important
Squash mergeAll commits collapsed to oneClean main history, feature branches
Rebase mergeReplays commits on top of mainLinear history, no merge commits

Most teams use squash merge for feature branches; merge commit for release branches.

GitHub CLI

# Create a PR
gh pr create --title "Add feature X" --body "Closes #42" --reviewer @alice
 
# Check out a PR locally
gh pr checkout 42
 
# List open PRs
gh pr list --assignee @me
 
# View CI status
gh pr checks
 
# Merge a PR
gh pr merge 42 --squash --delete-branch

Code Owners

.github/CODEOWNERS — auto-requests review from specific owners when matching files change:

# Syntax: pattern   owners
*                   @global-owner
/src/auth/          @security-team
*.tf                @infra-team @devops-lead
docs/               @docs-team

Dependabot for Automated Dependency Updates

.github/dependabot.yml:

version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    reviewers: ["alice"]
    labels: ["dependencies"]

Dependabot opens PRs to bump outdated dependencies. Merge them to keep your supply chain fresh.

Trade-offs

PatternProCon
GitHub FlowSimple, low overheadHard for teams needing stable release branches
Trunk-basedFast integration, small conflictsRequires feature flags and disciplined CI
Release branchingStable release managementLong-lived branches, frequent merge conflicts
Squash mergeClean historyLoses individual commit context
Rebase mergeLinear historyRewrites commit SHAs (confusing in large teams)

References