Git Workflows for CI
Git workflows for CI define which git events start pipelines, how long branches live, and whether production deploys from tags, merge commits, or trunk HEAD.
Introduction
Git workflows for CI define which git events start pipelines, how long branches live, and whether production deploys from tags, merge commits, or trunk HEAD. Staff engineers map Git Flow, GitHub Flow, trunk-based development, merge queues, and branch protection to explicit CI triggers — not "run CI on push" without naming the branch class.
The story
A 120-engineer fintech team ran Git Flow with develop and release/* branches but only wired CI to main. Hotfixes on release/4.2 merged without tests; a payment regression reached prod because the release branch had no required checks. The fix was not "more Jenkins" — it was a trigger matrix: PR → full CI, merge to protected branches → artifact + staging, tag v* → prod promotion.
Understanding the topic
Every workflow model implies a CI trigger contract. The contract answers: which refs fire which jobs, whether fork PRs get secrets, and how release trains map to tags.
- Git Flow: long-lived
develop+release/*+hotfix/*. CI triggers: PR todevelop(integration), PR torelease/*(RC gate), tag onmainafter hotfix merge (prod). - GitHub Flow: short-lived feature branches off
main. CI triggers:pull_request(full verify),pushtomain(build artifact + deploy staging), optionalworkflow_dispatchfor prod. - Trunk-Based Development (TBD): everyone commits to trunk (or ≤1-day branches). CI triggers: every push to
main(fast feedback), feature flags hide incomplete work; release tags cut from green trunk SHAs. - Merge Queues: when branch protection requires up-to-date branches, the queue merges serially into a temporary integration branch and runs CI before landing on
main— trigger is queue entry, not raw push. - Branch Protection: rules enforce required status checks, reviews, signed commits — CI must expose check names that match protection rules exactly.
Internal architecture
Workflow → CI trigger mapping — how each model connects git events to pipeline stages:
Git Flowfeature/* --PR--> develop --> CI: unit + lintrelease/* --PR--> main --> CI: full + staging deployhotfix/* --PR--> main+develop --> CI: smoke + security scantag v* on main --> CD: prod promoteGitHub Flowfeature/* --PR--> main --> CI: full matrixmerge main --> CI: build + push image + stagingworkflow_dispatch --> CD: prod (approval gate)Trunk-Basedpush main (small commits) --> CI: fast (<10 min) + deploy trunktag v* (release train) --> CD: prod from same artifact digestMerge QueuePR labeled "merge queue" --> CI on merge_group refgreen + merged --> push main triggers deploy pipelineBranch Protectionrequired checks: ci/build, ci/test, ci/scanmerge blocked until all green on latest merge-base
Visual explanation
Two diagrams show where Git Workflows for CI lives in the delivery path and how teams implement it in production.
Step-by-step explanation
- Inventory current branches: list long-lived refs (
develop,main,release/*) and average branch age from git log. - Draft a trigger matrix spreadsheet: rows = branch patterns, columns = CI jobs (lint, unit, integration, scan, deploy).
- Configure GitHub branch protection on
mainwith required check names matching workflow job outputs exactly. - Add
on: pull_requestandon: push: branches: [main](or merge queuemerge_group) to workflow YAML. - Validate: open a PR, confirm checks appear; merge, confirm artifact job runs; tag, confirm prod workflow receives digest — not a rebuild.
Production implementation
GitHub Actions trigger matrix for GitHub Flow + merge queue + branch protection:
- Use
merge_groupevent when GitHub merge queue is enabled — without it, queued merges skip CI. - Name jobs consistently; branch protection references job names or check runs, not workflow file names.
- For Git Flow release branches, duplicate workflow with
on: pull_request: branches: ['release/**']and stricter integration tests.
# .github/workflows/ci.ymlname: CIon:pull_request:branches: [main]push:branches: [main]merge_group:branches: [main]concurrency:group: ci-${{ github.ref }}cancel-in-progress: truejobs:build-test:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with: { node-version: 20, cache: npm }- run: npm ci && npm test- run: npm run buildsecurity-scan:needs: build-testruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- run: npm audit --audit-level=high# Branch protection: require "build-test" and "security-scan"
Execution workflow
Document branch taxonomy
List every long-lived and ephemeral branch pattern and its owner team.
Real-world use
Google's internal monorepo uses trunk-based development with TAP (Test Automation Platform) on every changelist. GitHub documented merge queues after customers hit "green PR + broken main" from merge skew. GitLab Flow adds environment branches (staging, production) — CI triggers differ per environment branch push.
Enterprise use cases
Shopify-scale teams often run trunk-based with merge queues and 200+ required checks split by path filters. Git Flow persists in regulated release-train orgs (quarterly SOX releases) where release/* branches get RC CI distinct from feature PR CI.
- Merge queue + TBD: Meta-style stacked diffs land via queue; CI runs on synthetic merge commit before trunk moves.
- Git Flow + compliance: release branch PR requires QA sign-off check + SBOM upload before tag triggers prod.
- GitHub Flow + SaaS: every merge to main deploys staging; prod is manual environment approval on same artifact digest.
Production case study
A B2B payments company (80 engineers) migrated from Git Flow to GitHub Flow + merge queue over one quarter. Release cadence went from bi-weekly trains to daily trunk deploys with feature flags.
- Before: CI only on
develop;mainmerges were untested manual cherry-picks. - Trigger redesign: PR → full CI; merge queue → integration; push main → artifact + staging; tag → prod.
- Branch protection: 2 reviews, 4 required checks, signed commits, no direct push.
- Outcome: change failure rate 22% → 6%; median PR wait dropped 4h → 45m after queue tuning.
Trade-offs
- Git Flow: clear release isolation; cost is branch proliferation and complex CI trigger sprawl.
- GitHub Flow: simple mental model; requires discipline on short branches and feature flags for incomplete work.
- Trunk-based: fastest integration feedback; demands excellent CI speed, flags, and merge queue at scale.
- Merge queues: eliminate skew merges; add latency (serial merges) and require CI budget for synthetic integration runs.
Security implications
Workflow choice directly affects supply-chain exposure — fork PR workflows must not leak secrets, and protected branches must block force-push bypass.
pull_request_targeton fork PRs runs with base repo secrets — use only with strict path filters and approval gates.- Branch protection "Include administrators" prevents emergency bypass of CI on
main. - Signed commits + required reviews pair with CI: a green build on unsigned commit should still fail policy.
- Tag protection rules prevent arbitrary
v*tags from triggering prod without release-manager role.
Scalability analysis
At hundreds of PRs/day, trigger design determines CI cost and developer wait time.
- Merge queues serialize merges — size queue depth vs CI capacity; stale queue entries waste runner minutes.
- Git Flow release branches multiply long-lived refs — each needs CI budget or drifts untested.
- Path filters on
pull_requestreduce noise but require CODEOWNERS alignment for bypass risk. - Concurrency groups (
cancel-in-progress) save minutes on feature branches but can hide flaky race tests.
Staff engineer insights
- Draw the trigger matrix before writing YAML — teams that start with tools end up with dead checks on unused branches.
- Merge queue is not optional above ~30 concurrent PRs on one trunk if you require branches up to date.
- Git Flow can coexist with trunk for platform vs product repos — don't force one religion org-wide.
- Required check names must match what developers see in PR UI; rename a job and you silently disable protection.
Best practices
- One trigger matrix doc in the repo README or ADR — updated when workflows change.
- Prefer
pull_requestoverpushon feature branches to avoid duplicate runs on every commit push. - Use merge queue when requiring "branch up to date" on high-velocity trunk.
- Tag prod releases from CI-built artifacts; never rebuild on tag event.
Common mistakes
- Enabling merge queue without
merge_groupworkflow trigger — merges land untested. - Required check names referencing old job IDs after workflow refactor — protection becomes theater.
- Running full deploy pipeline on every PR push — burns budget and teaches ignore-red-build culture.
Advanced interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1AdvancedQuestionHow would you map Git Flow branches to CI triggers for a SOX-regulated quarterly release?+
Answer
Follow-up
2AdvancedQuestionWhen does a merge queue replace 'require branches up to date'?+
Answer
Follow-up
3AdvancedQuestionDesign CI triggers for trunk-based development with feature flags.+
Answer
Follow-up
4AdvancedQuestionA fork PR needs CI but must not access prod secrets — what's your workflow design?+
Answer
Follow-up
5AdvancedQuestionBranch protection shows green but prod broke — what failed?+
Answer
Follow-up
Hands-on exercise
Build a trigger matrix for a repo using GitHub Flow + merge queue. Implement workflows and branch protection in a test repo.
- Deliberately fail a check — confirm merge blocked.
- Enable merge queue — confirm
merge_groupworkflow runs. - Document trigger matrix in TRIGGER_MATRIX.md.
# Create test repo and protection (gh CLI)gh repo create cicd-trigger-lab --public --clonecd cicd-trigger-lab# Add ci.yml (from productionImplementation), then:gh api repos/{owner}/cicd-trigger-lab/branches/main/protection \-f required_status_checks[strict]=true \-f required_status_checks[checks][]=context=build-test \-f required_pull_request_reviews[required_approving_review_count]=1# Open PR, verify checks, enable merge queue in repo settings, merge
Summary
You can map Git Flow, GitHub Flow, trunk-based development, merge queues, and branch protection to concrete CI triggers — PR tiers, merge integration, trunk deploy, and tag promotion. Design the matrix before YAML; audit check names against protection rules.