Git Workflow for Solo Devs and Small Teams: Keep It Simple

Git Workflow for Solo Devs and Small Teams: Keep It Simple
Brandon Perfetti

Technical PM + Software Engineer

Topics:Git workflowTrunk-based developmentFeature branches
Tech:Git

Stop treating Git as formal engineering bureaucracy. For most solo developers and small teams, GitFlow and elaborate branching strategies add overhead without delivering proportional value. This guide is an opinionated, practical plan: use trunk-based development plus short-lived feature branches, write commit messages that explain intent, keep pull requests small and fast, and rely on simple CI gates. Below are concrete rules, commands, and templates you can copy and use today.

Why GitFlow is Overkill (and What to Use Instead)

GitFlow introduces many branches (develop, release, hotfix, feature) and rules meant to coordinate large teams and complex release calendars. For solo devs or teams <10 people the cost is coordination friction: long-lived branches, complicated merges, and delay before changes reach production.

Trunk-based development is simpler and faster: keep a single main branch (call it main or trunk) that is always deployable, and use short-lived feature branches to develop changes. Merge frequently so integration happens early and conflicts are small.

Key trade-off: prefer frequent small merges to long-running isolation. If you need long-lived work, use feature flags, not permanent branches.

  • Rule 1: main is always releasable. No feature branch should be the source of truth for production readiness.
  • Rule 2: feature branches live for hours or a few days, not weeks.
  • Rule 3: use CI to gate merges to main (tests pass, lint).

Branch Naming and Lifespan: Keep it Predictable

Use an explicit but short naming convention to know intent at a glance. Example: feature/issue-123-description, fix/issue-124, chore/docs. This helps with searching and quick context.

Set a lightweight rule for lifespan: aim to merge any branch within 72 hours. If the change will take longer, split it into smaller branches or use a feature flag.

Commands to create and work on a branch:

git checkout -b feature/issue-123-short-description

During development, keep your branch up to date with main frequently. For small teams prefer rebasing your branch onto latest main before merging to keep history linear:

git fetch origin

git rebase origin/main

Resolve conflicts, then push with force-with-lease:

git push --force-with-lease origin feature/issue-123-short-description

  • Naming example: feature/456-add-payments
  • Lifespan target: <72 hours; if longer, split work or use flags
  • Update branch by rebasing onto origin/main to reduce merge noise

Commit Messages That Actually Help

Commit messages are the fastest way to understand a change later. Use an opinionated, short style that communicates intent and scope. A minimal template that scales well: type(scope): short summary

Recommended types: feat, fix, chore, docs, refactor, test. Scope is optional but useful for larger repos (api, ui, payments). Examples:

feat(payments): add Stripe payment intent creation

fix(auth): return 401 for expired tokens

chore(deps): bump lodash to 4.17.21

Practical habits:

1) Keep each commit atomic—one logical change per commit. Use interactive staging (git add -p) to split work.

2) Use the body of the commit to explain why if the change is not obvious. Start the body with a blank line and write 1-3 sentences.

3) When cleaning up history before merging, use interactive rebase to squash WIP commits into meaningful units: git rebase -i origin/main

  • Commit template: type(scope): short summary
  • Use git add -p to create atomic commits
  • If necessary, include a 1-3 sentence explanation in the commit body
  • Squash WIP commits via interactive rebase before merging

Pull Requests and Reviews: Lightweight, Fast, and Useful

Pull requests are not status meetings. Make PRs small, focused, and easy to review. If a change is larger than 300 lines of diff, split it or review by component. Small teams should avoid multi-stage approval gates that block progress.

Suggested PR rules for small teams:

• Require CI pass and one approval to merge. For critical repos, add a second reviewer, but default to one.

• Limit review time—request review and expect feedback in 24-48 hours during workdays. If urgent, use pair programming or request an expedited review.

• Use a PR template checklist to speed up reviews. Example checklist:

- [ ] Tests added or updated

- [ ] Lint passes

- [ ] Migration backward-compatible

- [ ] Performance impact considered

• Use draft PRs to advertise work in progress and invite early feedback without blocking main.

Good PR descriptions include: the problem, what changed, how to test locally, and migration notes (if any). Keep the body concise and actionable.

  • PR size target: <300 lines of diff
  • Merge criteria: CI green + 1 approval
  • Use PR checklist to reduce review back-and-forth
  • Draft PRs are great for early feedback

Merging Strategies and Release Practices

For small teams, prefer either fast-forward merges or squash merges. Fast-forward keeps a linear history if you always rebase before merging. Squash merges collapse the branch into one clean commit — useful for preserving a tidy main history without enforcing rebases.

Suggested policy:

• If your developers are comfortable with rebase: require rebasing onto origin/main and allow fast-forward merges.

• If not: allow squash merges; the PR description and commit message become the canonical summary.

Tag releases simply: use annotated tags with semantic versioning. Example:

git tag -a v1.2.0 -m 'chore(release): v1.2.0 — payments improvements'

git push origin v1.2.0

Hotfixes: create a small fix branch from main, run CI, merge back, and tag a patch release. No need for a separate long-lived hotfix branch unless you have a release branch model.

CI and deployment: keep the gate minimal — run tests, lint, and critical integration checks. For deploys, prefer continuous deployment from main when possible. If you must have releases, use tagged builds as your release artifacts.

  • Prefer fast-forward (with rebase) or squash merges
  • Use annotated tags for releases: git tag -a vX.Y.Z -m 'message'
  • Hotfix flow: small branch from main -> CI -> merge -> tag
  • Gate merges with CI that verifies correctness, not every possible metric

Handling Long-running Work, Feature Flags, and Emergencies

If a feature cannot be completed in a few days, do not keep a branch alive for weeks. Instead split into smaller mergeable pieces or use feature flags to land partial work safely on main. This reduces integration risk and keeps main deployable.

Feature flag best practices:

• Ship behind a flag defaulting to off.

• Keep flag lifecycle short. Remove flags once feature is stable.

• Use simple boolean flags or a basic rollout mechanism; avoid over-engineering.

Emergency fixes: tag and document the emergency process. For emergencies, create a fix branch from main, prioritize CI and test runs, and merge after verification. Keep the flow identical to normal merges to avoid special-casing.

  • Split long work into smaller, mergeable pieces
  • Use feature flags for incomplete features pushed to main
  • Remove flags after stability — avoid flag sprawl
  • Emergency flow should mirror normal flow to reduce cognitive load

Conclusion

Simplicity is a force multiplier for small teams. Replace heavy branching rituals with trunk-based development, short-lived feature branches, meaningful commit messages, and efficient PR practices. Use CI as a simple gate (tests + lint), keep PRs small, and favor fast merges. These rules reduce friction, accelerate delivery, and keep your history comprehensible. You don't need complex branching models to ship reliably — you need discipline and a few pragmatic rules everyone follows.

Action Checklist

  1. Adopt the branch name convention: feature/..., fix/..., chore/...
  2. Add a commit message guideline and a git commit template using the type(scope): short summary format
  3. Create a simple PR template with a testing checklist and merge criteria
  4. Configure branch protection on main to require CI and one approval
  5. Decide on a merge strategy (rebase+fast-forward or squash) and document it
  6. Introduce basic feature flagging for long-running work and set a flag removal policy
  7. Run a one-week experiment: enforce the new rules and measure whether PR cycle time decreases