Skip to main content

πŸ‘₯ Team Workflows

In class you were a team of one. The moment a second person touches your repository, whether a classmate, a client, or future-you on a second laptop, it helps to agree on how work flows into main. This page covers the habits and GitHub features teams use to do that calmly.

🧭 Good news first

The workflow you used in Lesson 6 (branch β†’ push β†’ pull request β†’ Deploy Preview β†’ merge) is the workflow most small teams use. Everything here builds on it; nothing replaces it.

On This Page

🌊 GitHub Flow

GitHub Flow has one long-lived branch, main, which is always working and always deployable. Every change, however small, happens on a short-lived branch and reaches main through a pull request.

gitGraph commit id: "Launch site" branch fix-nav-links checkout fix-nav-links commit id: "Fix nav links" checkout main merge fix-nav-links id: "PR #1" branch add-gallery checkout add-gallery commit id: "Add gallery page" commit id: "Compress photos" checkout main merge add-gallery id: "PR #2"
  1. Start from an up-to-date main: git switch main, git pull.
  2. Branch with a descriptive name: git switch -c add-gallery.
  3. Commit in small steps and push the branch early: git push -u origin add-gallery.
  4. Open a pull request as soon as you want feedback. It can be a draft.
  5. Review and check: teammates comment, the Netlify Deploy Preview shows the real result, automated checks run.
  6. Merge, then delete the branch. Netlify deploys main. Everyone runs git switch main + git pull before their next branch.

πŸ’‘ Deploy previews are free; production deploys aren't

On Netlify's credit-based free plan, deploy previews don't use credits but every production deploy (every merge to main) does. Grouping related small fixes into one pull request is kinder to your monthly allowance than merging ten one-line PRs.

🀝 Collaborators & Forks

Collaborators (people you trust)

Repository β†’ Settings β†’ Collaborators β†’ Add people. Once they accept the email invitation they can clone, push branches, and merge pull requests. This is the right choice for a classmate on a group project or a co-owner of a site.

Forks (everyone else)

Anyone can Fork a public repository into their own account, push to their copy, and open a pull request back to yours. You decide what gets merged. This is how open source works; Practice Project 6 walks you through it.

Organizations (free for public work) let a group own repositories together and manage people in teams. Useful once you have more than a couple of shared repos.

πŸ›‘οΈ Protecting main

"Main is always deployable" is easier to keep when GitHub enforces it. Go to Settings β†’ Rules β†’ Rulesets β†’ New ruleset β†’ New branch ruleset (older repositories may show Settings β†’ Branches β†’ Add branch protection rule instead), target the default branch, and turn on:

  • Require a pull request before merging: nobody, including you, can push straight to main. Optionally require one or more approvals.
  • Require status checks to pass: the PR can't be merged until checks (like the HTML check below, or the Netlify deploy) are green.
  • Block force pushes: history on main can't be rewritten.

On GitHub's free plan these rules apply to public repositories; enforcing them on private repositories needs a paid plan. Wording and menus move occasionally, so if a label differs, look for "Rules" or "Branches" in Settings.

πŸ” Pull Requests & Code Review

flowchart LR A["Open PR
(or draft)"] --> B["Checks run +
Deploy Preview"] B --> C{"Review"} C -->|"Request changes"| D["Push more commits
to the same branch"] D --> B C -->|"Approve"| E["Merge"] E --> F["Delete branch"]

Writing a PR people want to review

  • A clear title in the same style as a commit message: "Add photo gallery page".
  • What and why in a few sentences. Screenshots or the Deploy Preview link help a lot for visual changes.
  • How to check it: "Open /gallery.html on the preview and resize to phone width."
  • Link the issue: writing Closes #12 in the description closes issue 12 automatically when the PR is merged into main.
  • Keep it small. A PR that does one thing gets a thoughtful review in minutes; a 40-file PR gets "looks good πŸ‘" and hidden bugs.

Reviewing

Open the Files changed tab. Click the + beside any line to comment on it, or select several lines. When you're done, click Review changes (the label may read "Submit review") and choose Comment, Approve, or Request changes. The author answers by pushing new commits to the same branch; the PR updates itself.

For reviewers

  • Does it do what the description says?
  • Does the Deploy Preview look right on phone and desktop?
  • Is anything missing: alt text, links, a mobile style?
  • Ask questions rather than issue orders: "What do you think about…?"
  • Say what's good, too.

For authors

  • Review your own diff before asking anyone else.
  • Reply to every comment, even if just "Done".
  • Remember comments are about the code, not about you.
  • Disagreeing is fine; explain your reasoning.
  • Thank your reviewer.

The three merge buttons

OptionWhat lands on mainGood for
Create a merge commitAll the branch's commits plus a merge commit (what you did in Lesson 6)Keeping the full story
Squash and mergeOne single commit containing the whole PRBranches with many "wip"/"fix typo" commits
Rebase and mergeThe branch's commits replayed onto main, no merge commitTeams who want a straight-line history

Teams usually pick one and stick to it. After a squash merge, delete your local branch with git branch -D, because Git can't tell it was merged (the commits on main are different ones).

πŸ”„ Staying in Sync

Most team friction comes from working on an out-of-date copy. Three habits prevent nearly all of it:

  1. Pull before you branch. Always git switch main + git pull first.
  2. Keep branches short-lived. A branch merged within a day or two rarely conflicts; one left open for a month almost always does.
  3. Bring main into a long-running branch when main has moved on, so you deal with conflicts early and on your own terms:
git switch main
git pull
git switch add-gallery
git merge main
# resolve any conflicts, commit, then:
git push

GitHub offers the same thing as an Update branch button on the pull request when main has moved ahead.

⚠️ If git pull says "Need to specify how to reconcile divergent branches"

Your Git hasn't been told whether to merge or rebase when both sides have new commits. Run git config --global pull.rebase false once to always merge (what this class uses), then pull again. Git for Windows usually sets this for you during install.

πŸ“ Conventions

Commit messages

Everything from class still applies: imperative mood, say what and why, one change per commit. Some teams add a structured prefix called Conventional Commits so tools can build changelogs automatically:

<type>(<optional scope>): <short summary>

<optional body: what changed and why>

<optional footer, e.g. Closes #12>
feat(gallery): add lightbox to photo grid
fix(nav): correct link to contact page
docs: explain local setup in README
style(css): reformat colors section
chore: remove unused images

Common types are feat (a new feature), fix (a bug fix), docs, style (formatting only), refactor, test, and chore. Use this only if your team agrees to. A plain, clear message is always fine.

Branch names

KindPatternExample
New featurefeature/<short-description>feature/photo-gallery
Bug fixfix/<short-description>fix/broken-contact-link
With an issue numberfix/<issue>-<description>fix/12-mobile-menu
Docs / contentdocs/<short-description>docs/readme-setup

Lowercase, hyphens instead of spaces, and short enough to type. The prefix is optional; consistency is what matters.

Shared shortcuts (aliases)

git config --global alias.st "status"
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.last "log -1 --stat"

Now git lg draws the branch graph and git last summarizes your latest commit. Aliases live in your own config, so teammates each set up their own.

πŸ€– Automated Checks (GitHub Actions)

Continuous integration (CI) means a robot runs checks on every push and pull request, so problems show up before they reach main. Your Netlify Deploy Preview is already a simple version: if the build fails, the PR shows a red βœ—. GitHub Actions lets you add your own checks with a small YAML file in the repository.

flowchart LR A["Push or open PR"] --> B["GitHub Actions
runs your workflow"] B --> C{"Checks pass?"} C -->|"Yes βœ“"| D["PR can be merged"] C -->|"No βœ—"| E["Fix, commit, push again"] E --> B

For example, to check every HTML page for mistakes (unclosed tags, missing alt text, duplicate IDs), create .github/workflows/check-html.yml in VS Code:

name: Check HTML

on:
  pull_request:
  push:
    branches: [main]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "lts/*"
      - run: npx --yes html-validate "**/*.html"

and a .htmlvalidate.json in the repository root that picks the rule set:

{
  "extends": ["html-validate:recommended"]
}

Commit both files and open a pull request. A Checks section appears on the PR, and the Actions tab shows every run with its log. The recommended rules are strict; if they flag things you're happy with, the html-validate documentation explains how to switch individual rules off.

πŸ’‘ Version numbers in uses:

The @v4 after each action is its major version. Actions get new major versions every year or two; the action's page on GitHub Marketplace always shows the current one, and GitHub warns you in the run log when a version is getting old.

πŸ—ΊοΈ Other Branching Models

You'll read about other workflows online. They're answers to different problems, not "more advanced" versions of GitHub Flow.

Git Flow

Designed for software shipped in numbered releases (desktop apps, libraries). Work happens on develop; release/* branches stabilize a version; main only receives finished releases (tagged v1.1, v1.2…); urgent hotfix/* branches start from main and merge back into both.

gitGraph commit tag: "v1.0" branch develop checkout develop commit id: "Start v1.1 work" branch feature/search checkout feature/search commit id: "Add search" checkout develop merge feature/search branch release/1.1 checkout release/1.1 commit id: "Fix release bugs" checkout main merge release/1.1 tag: "v1.1" checkout develop merge release/1.1

Trunk-based development

Everyone merges tiny changes into main (the "trunk") at least daily, relying heavily on automated tests and "feature flags" to hide unfinished work. Common at large tech companies.

GitHub FlowGit FlowTrunk-based
Long-lived branchesmainmain + developmain
ReleasesEvery merge deploysScheduled, versionedContinuous
Branch lifetimeHours to daysDays to weeksHours
Best fitWebsites, small teamsVersioned softwareLarge teams with strong CI
Learning curveGentleSteepModerate (needs good tests)

For a website deployed by Netlify, GitHub Flow is almost always the right choice.

πŸ” Secrets & Security

Keep secrets out of Git

Anything pushed to a public repository can be copied within minutes, and even deleting it later doesn't remove it from history or from other people's clones. API keys, passwords, and tokens belong in environment variables (Netlify has Site configuration β†’ Environment variables) and in files listed in .gitignore:

# .gitignore
.env
.env.*
*.pem
*.key

GitHub's push protection blocks pushes that contain many well-known kinds of secret, and it's on by default for public repositories. Treat it as a seatbelt, not a plan.

🚨 If you do push a secret

Revoke or rotate it first: generate a new key and disable the old one on the service that issued it. Only then worry about cleaning the history. Rewriting history can't un-leak something that's already been seen.

Accounts

  • Turn on two-factor authentication (GitHub requires it for most people who contribute code).
  • Use HTTPS with Git Credential Manager or gh auth login, as in Lesson 5. If you ever create a personal access token, give it the smallest permissions and an expiry date.
  • Review Settings β†’ Collaborators now and then and remove people who no longer need access.

Signed commits (optional)

Anyone can put any name in user.name. Signing proves a commit really came from you, and GitHub shows a Verified badge. (Commits you make in GitHub's web editor are signed automatically.) The simplest method uses an SSH key:

ssh-keygen -t ed25519 -C "you@example.com"
git config --global gpg.format ssh
git config --global user.signingkey /path/to/.ssh/id_ed25519.pub
git config --global commit.gpgsign true

Replace the path with where ssh-keygen saved your key (it tells you). Then on GitHub go to Settings β†’ SSH and GPG keys β†’ New SSH key, choose Key type: Signing Key, and paste the contents of the .pub file. GitHub's "Signing commits" documentation covers GPG keys as well.

🩺 Team Troubleshooting

SituationWhat to do
Push rejected: (fetch first) or (non-fast-forward) Someone else pushed first. git pull, resolve any conflict, git push. Don't force push.
Conflict in an image or other binary file Git can't merge pictures line by line; you pick one. Keep yours with git restore --ours <file> or theirs with git restore --theirs <file>, then git add <file> and git commit. (Older guides write git checkout --ours, which does the same thing.)
"You are in 'detached HEAD' state" You checked out a commit rather than a branch. git switch main to go back, or git switch -c <new-branch> first if you made commits you want to keep.
I committed to main but meant to use a branch (not pushed yet) git switch -c my-branch takes the commit with you onto a new branch, and you can push that for a PR. Tidying main afterwards involves git reset; see Advanced Git before trying it.
My PR says "This branch has conflicts that must be resolved" Bring main into your branch locally (see Staying in Sync), resolve, push. Or use GitHub's Resolve conflicts button for simple text conflicts.

🌱 Where you are now

You already know the core of team Git: branch, commit, push, open a PR, review, merge, pull. The rest is agreement and habit, and every team writes its own version. When you join one, ask how they work, read their CONTRIBUTING.md if there is one, and you'll recognize almost everything. When you're ready for more power tools, head to Advanced Git.