Skip to content

Collaboration Workflows

Git is flexible enough to support many collaboration models. The right workflow depends on your team size, release cadence, and how much process you want. This guide covers the major workflow patterns, how pull requests fit in, and how to choose the right model for your situation.


Centralized Workflow

The simplest model: everyone pushes to main. No feature branches, no pull requests. Each developer pulls, makes changes, and pushes directly.

git pull origin main
# ... make changes ...
git add . && git commit -m "Add new feature"
git push origin main

When it works: Small teams (2-3 people) working on different parts of the codebase with minimal overlap. Quick prototypes and internal tools.

When it breaks: As the team grows, push conflicts increase. There's no code review before changes hit main. One bad push breaks everyone.


Feature Branch Workflow

The most common workflow in modern development. Each change gets its own branch, work happens in isolation, and code merges into main through a review process.

git switch -c feature/user-search
# ... develop the feature ...
git push -u origin feature/user-search
# Open a pull request / merge request
# Team reviews, approves, merges

Key principles:

  • main is always deployable
  • All work happens on branches
  • Branches are short-lived (days, not months)
  • Changes merge through reviewed pull requests
  • Branches are deleted after merging

Gitflow

Gitflow is a structured branching model designed for projects with scheduled releases. It defines specific branch roles:

Branch Purpose Lifetime
main Production-ready code, every commit is a release Permanent
develop Integration branch for features Permanent
feature/* Individual features Short (merge into develop)
release/* Release preparation, bug fixes, versioning Short (merge into main and develop)
hotfix/* Urgent production fixes Short (merge into main and develop)
gitGraph
   commit id: "v1.0" tag: "v1.0"
   branch develop
   commit id: "dev-1"
   branch feature/search
   commit id: "search-1"
   commit id: "search-2"
   checkout develop
   merge feature/search id: "merge-search"
   branch release/1.1
   commit id: "bump-version"
   commit id: "fix-typo"
   checkout main
   merge release/1.1 id: "v1.1" tag: "v1.1"
   checkout develop
   merge release/1.1 id: "sync-develop"

When it works: Projects with formal release schedules, multiple environments (staging, production), and regulatory requirements for release tracking.

When it breaks: Teams practicing continuous deployment. The overhead of maintaining develop, creating release branches, and double-merging is unnecessary when you ship from main directly. The original author of Gitflow has acknowledged this - for web applications with continuous delivery, simpler models are better.


Trunk-Based Development

The opposite philosophy from Gitflow. All developers commit to a single branch (main / trunk), branches are extremely short-lived (hours, not days), and feature flags control what's visible to users.

gitGraph
   commit id: "A"
   commit id: "B"
   branch short-lived
   commit id: "C"
   checkout main
   merge short-lived id: "D"
   commit id: "E"
   commit id: "F"
   branch another
   commit id: "G"
   checkout main
   merge another id: "H"

Key principles:

  • Branches last hours, not days
  • Everyone merges to main multiple times per day
  • Feature flags gate incomplete features
  • Automated tests run on every commit to main
  • Continuous integration catches conflicts immediately

When it works: Teams with strong CI/CD, comprehensive automated tests, and the discipline to keep branches tiny. Google, Facebook, and many high-velocity teams use this.

When it breaks: Teams without good test coverage or CI. Without automated quality gates, rapid main-line commits can break production frequently.


Forking Workflow

The standard model for open-source contributions. Contributors don't have push access to the original repository. Instead:

  1. Fork the repository (creates a copy under your account)
  2. Clone your fork
  3. Add the original repo as upstream
  4. Create feature branches on your fork
  5. Push to your fork
  6. Open a pull request from your fork to the original
flowchart LR
    subgraph Upstream["Original Repository"]
        UM["main"]
    end

    subgraph Origin["Your Fork"]
        OM["main"]
        FB["feature/fix"]
    end

    subgraph Local["Your Machine"]
        LM["main"]
        LF["feature/fix"]
    end

    UM -->|"fork"| OM
    OM -->|"git clone"| LM
    LF -->|"git push origin"| FB
    FB -->|"Pull Request"| UM
    UM -->|"git fetch upstream"| LM

This workflow protects the original repository. The maintainer reviews every contribution before it enters the codebase. The contributor doesn't need any special permissions.


Pull Requests / Merge Requests

A pull request (GitHub, Bitbucket) or merge request (GitLab) is a platform feature - not a Git concept - that wraps the merge process with review, discussion, CI checks, and approval.

What a PR Contains

  • The source branch and target branch
  • A title and description
  • The diff of all changes
  • A timeline of commits, comments, and reviews
  • CI/CD check results
  • Approval status

Code Review Best Practices

For authors:

  • Keep PRs small and focused (under 400 lines of diff is ideal)
  • Write a clear description explaining what and why
  • Reference related issues
  • Self-review before requesting review
  • Respond to feedback constructively

For reviewers:

  • Review promptly (within one business day)
  • Focus on correctness, clarity, and maintainability
  • Distinguish between blocking issues and suggestions
  • Ask questions rather than making demands
  • Approve when "good enough" - don't block on style preferences

Branch Protection

Most platforms support branch protection rules for shared branches:

  • Require pull request reviews before merging (minimum number of approvals)
  • Require status checks (CI must pass)
  • Require up-to-date branches (must be rebased/merged with main)
  • Restrict who can push (prevent direct pushes to main)
  • Require signed commits
  • Prohibit force pushes

Release Management

Semantic Versioning

Semantic versioning (SemVer) uses three numbers: MAJOR.MINOR.PATCH:

  • MAJOR: Breaking changes (incompatible API changes)
  • MINOR: New features (backward-compatible)
  • PATCH: Bug fixes (backward-compatible)

Tagging Releases

# Create an annotated tag for a release
git tag -a v2.1.0 -m "Release 2.1.0: Add user search, fix login timeout"

# Push tags to remote
git push origin v2.1.0
# or push all tags
git push origin --tags

Release Branches

When you need to stabilize a release while development continues:

# Create release branch
git switch -c release/2.1 main

# Bug fixes go on the release branch
git commit -m "Fix edge case in search pagination"

# When ready, merge into main and tag
git switch main
git merge release/2.1
git tag -a v2.1.0 -m "Release 2.1.0"

# Merge back into develop (if using Gitflow)
git switch develop
git merge release/2.1

Monorepos vs Polyrepos

Monorepo Polyrepo
Structure All projects in one repository Each project in its own repository
Dependencies Shared code is directly importable Shared code is versioned and published
Atomic changes One commit can change multiple projects Cross-project changes require coordinated releases
CI/CD Must scope builds to affected code Each repo has its own pipeline
Scale Needs Git optimization (sparse checkout, etc.) Each repo stays small
Examples Google, Meta, Microsoft (Windows) Most open-source projects, microservices

The Monorepos and Scaling Git guide covers the Git-specific challenges and solutions for monorepos.


Choosing a Workflow

Team Size Release Model Recommended Workflow
1-3 Continuous Feature branch (simple) or trunk-based
4-10 Continuous Feature branch with PR reviews
4-10 Scheduled releases Gitflow or modified feature branch
10+ Continuous Trunk-based with feature flags
Open source Maintainer-gated Forking workflow

There's no universally correct workflow. Start simple (feature branches with PRs), and add structure (release branches, hotfix process) only when the team's needs demand it.


Exercise


Further Reading


Previous: Transfer Protocols and Plumbing | Next: GitHub, GitLab, and Bitbucket | Back to Index

Comments