git version control30 min

GitHub Flow

A lightweight branching workflow for collaboration and continuous delivery

0/9Not Started

Why This Matters

Knowing Git commands is only half the story. The other half is knowing how to use them in a team workflow. GitHub Flow is the most popular workflow for modern software teams: create a branch, make commits, open a pull request, get a code review, pass CI checks, and merge to main. It is simple enough for two-person startups and scales to thousands of contributors.

Pull requests are where collaboration happens. They are not just a merge mechanism -- they are a discussion forum, a review tool, and a quality gate all in one. Reviewers read your code, leave comments, request changes, and approve the work before it reaches the main branch. Automated CI checks run your tests, linters, and build scripts on every push to the PR branch, catching bugs before humans even look at the code.

Understanding this workflow is critical because virtually every company that uses Git also uses pull requests. Whether you contribute to open source, work at a startup, or join a large engineering team, GitHub Flow (or a close variant) will be your daily process.

Define Terms

Visual Model

mainStable branch
Create Branchfeature-xyz
Add CommitsPush to remote
Open PRPropose merge
Code ReviewDiscuss changes
CI ChecksTests and lint
Merge to MainSquash or merge
branch off
develop
push + PR
request review
trigger CI
approved
passing

The full process at a glance. Click Start tour to walk through each step.

GitHub Flow: branch, commit, PR, review, CI, merge. The main branch is always deployable.

Code Example

Code
// GitHub Flow in practice (terminal commands)

// 1. Start from latest main
// $ git checkout main
// $ git pull origin main

// 2. Create a feature branch
// $ git checkout -b feature-user-auth

// 3. Make changes and commit
// $ git add src/auth.js
// $ git commit -m "Add user authentication module"
// $ git add src/auth.test.js
// $ git commit -m "Add tests for auth module"

// 4. Push to remote
// $ git push -u origin feature-user-auth

// 5. Create a PR (using GitHub CLI)
// $ gh pr create --title "Add user authentication" \
//     --body "Implements login and signup flow"

// 6. After review and CI pass, merge the PR
// $ gh pr merge --squash

// 7. Clean up
// $ git checkout main
// $ git pull origin main
// $ git branch -d feature-user-auth

// Simulating PR state machine in JavaScript
class PullRequest {
  constructor(title, sourceBranch, targetBranch) {
    this.title = title;
    this.source = sourceBranch;
    this.target = targetBranch;
    this.state = "open";
    this.reviews = [];
    this.ciStatus = "pending";
  }

  addReview(reviewer, decision) {
    if (this.state !== "open") {
      throw new Error("PR is not open");
    }
    this.reviews.push({ reviewer, decision });
  }

  setCiStatus(status) {
    this.ciStatus = status;  // "passing" or "failing"
  }

  canMerge() {
    const hasApproval = this.reviews.some(
      r => r.decision === "approved"
    );
    return (
      this.state === "open" &&
      hasApproval &&
      this.ciStatus === "passing"
    );
  }

  merge() {
    if (!this.canMerge()) {
      throw new Error("Cannot merge: needs approval and passing CI");
    }
    this.state = "merged";
    return this.source + " merged into " + this.target;
  }
}

const pr = new PullRequest("Add auth", "feature-auth", "main");
pr.addReview("alice", "approved");
pr.setCiStatus("passing");
console.log(pr.canMerge());
console.log(pr.merge());

Interactive Experiment

Try these exercises with a real GitHub repository:

  • Create a branch, push it to GitHub, and open a pull request using either the GitHub web UI or gh pr create. Look at the "Files changed" tab to see the diff view.
  • Add a teammate as a reviewer (or review your own PR on a personal project). Leave inline comments on specific lines of code.
  • Set up a simple GitHub Action that runs your tests on every push. Open a PR and watch the CI check appear. Make a test fail and see the red X.
  • Try merging with "Squash and merge" versus "Create a merge commit" -- notice the difference in the commit history on main.

Quick Quiz

Coding Challenge

PR Review State Machine

Build a `PullRequest` class that models the PR lifecycle. Constructor takes (title, source, target) and starts in state 'open'. Methods: `addReview(reviewer, decision)` where decision is 'approved' or 'changes_requested' (throw 'PR is not open' if state is not open), `setCiStatus(status)` where status is 'passing' or 'failing', `canMerge()` returns true only if state is open AND at least one review is approved AND ciStatus is 'passing', `merge()` sets state to 'merged' and returns '<source> merged into <target>' (throw 'Cannot merge' if canMerge is false), and `getState()` returns the current state string.

Loading editor...

Real-World Usage

GitHub Flow is the dominant workflow in the industry:

  • GitHub itself uses GitHub Flow internally -- every change to GitHub.com goes through a PR with review and CI.
  • Vercel, Netlify, and Railway deploy preview environments for every PR branch, so reviewers can test changes live before merging.
  • Open source projects like React, Next.js, and VS Code require all contributions via pull requests with multiple reviewers and extensive CI pipelines.
  • Branch protection rules on GitHub enforce that PRs cannot be merged without a minimum number of approvals, passing status checks, and up-to-date branches.
  • Squash merging is popular because it collapses a messy feature branch into a single clean commit on main, keeping the history readable.

Connections