GitTeam Collaboration Workflow

Setting Up a Team Git Workflow

A well-defined Git workflow is one of the highest-leverage investments a software team can make. It determines how code moves from an individual's laptop to production, how conflicts are resolved, who can review and approve changes, and what the history of the project looks like six months from now. Without a shared workflow, every developer invents their own conventions — leading to confusion, lost work, and broken deployments.

This guide covers everything a team needs: choosing the right workflow model, naming conventions, commit standards, pull-request etiquette, branch protection, onboarding, conflict resolution policy, and a full day-in-the-life walkthrough.

Choosing a Workflow

Three workflows dominate the industry. Each makes different trade-offs between simplicity, release cadence, and the number of long-lived branches.

Workflow

Long-lived branches

Best for

Complexity

GitHub Flow

main only

Continuous deployment, SaaS, web apps

Low

Gitflow

main + develop + support

Versioned software, mobile apps, libraries

High

Trunk-based

main only (short-lived feature branches)

High-velocity teams with strong CI

Medium

GitHub Flow is recommended for most teams. It has one rule: anything on main is deployable. All work happens on short-lived feature branches that merge into main via a pull request. There is no separate develop branch, no release branch ceremony, and no complex merge choreography.

Tip
If your team ships continuously (multiple times per day) and you have good automated test coverage, GitHub Flow is almost certainly the right choice. Only reach for Gitflow if you maintain multiple released versions simultaneously or have a formal QA gate before release.
Branch Naming Conventions

Consistent branch names make it easy to understand the purpose of a branch at a glance, automate CI triggers, and keep dashboards readable. Adopt a prefix-slash-description pattern:

Prefix

Purpose

Example

feature/

New functionality

feature/user-authentication

fix/

Bug fix in development

fix/login-redirect-loop

hotfix/

Urgent production fix

hotfix/payment-null-pointer

release/

Release preparation branch (Gitflow)

release/2.4.0

chore/

Maintenance, dependency updates, tooling

chore/upgrade-react-19

docs/

Documentation only changes

docs/api-authentication

refactor/

Code restructuring without behaviour change

refactor/extract-auth-service

test/

Adding or fixing tests only

test/coverage-payment-module

Rules for branch names:

  • Use lowercase letters and hyphens only — no spaces, underscores, or slashes beyond the prefix.

  • Keep names short but descriptive: feature/oauth-google not feature/add-the-google-oauth-integration-to-the-login-page.

  • Include a ticket/issue number when relevant: feature/AUTH-142-oauth-google.

  • Never use personal names: johns-branch is opaque to everyone else.

  • Delete branches after they are merged.

Commit Message Standards (Conventional Commits)

The Conventional Commits specification is a lightweight convention on top of commit messages that provides a readable history, powers automated changelogs, and enables semantic version bumping. Every commit message follows this structure:

Conventional Commit format

Text
<type>(<optional scope>): <description>

[optional body]

[optional footer(s)]

Type

When to use

Version bump

feat

A new feature visible to users

Minor (1.x.0)

fix

A bug fix

Patch (1.0.x)

docs

Documentation only

None

style

Formatting, whitespace — no logic change

None

refactor

Code change that is neither feat nor fix

None

perf

Performance improvement

Patch

test

Adding or correcting tests

None

build

Build system or external dependency changes

None

ci

CI/CD configuration files and scripts

None

chore

Other changes not modifying src or test files

None

revert

Reverts a previous commit

Patch

A breaking change is indicated by appending ! after the type or by adding BREAKING CHANGE: in the footer:

Good commit messages

Text
feat(auth): add Google OAuth login

Users can now sign in with their Google account via the /login page.
The feature uses the official Google Identity Services library.

Closes #142

---

fix(cart): prevent negative quantity when decrementing

The decrement button was allowing quantities below 1. Added a
Math.max(0, quantity - 1) guard in CartItem.tsx.

Fixes #209

---

feat(api)!: rename /users endpoint to /accounts

BREAKING CHANGE: All clients must update their base URL from
/api/v1/users to /api/v1/accounts. The old path returns 410 Gone.
Note
Enforce commit message standards with a commit-msg hook. Install commitlint with `npm install --save-dev @commitlint/cli @commitlint/config-conventional` and add a `.commitlintrc.json` file to the repository root. Husky can wire the hook automatically.
Pull Request Requirements

A pull request (PR) is the formal mechanism for proposing, reviewing, and merging a change. Consistent PR requirements reduce review overhead and prevent low-quality code from reaching main.

PR description template — add this as .github/pull_request_template.md:

.github/pull_request_template.md

Text
## What

<!-- One sentence: what does this PR do? -->

## Why

<!-- Why is this change needed? Link to issue/ticket if applicable. -->
<!-- Closes #<issue-number> -->

## How to test

<!-- Step-by-step instructions for a reviewer to verify the change works. -->
1. Check out this branch: `git checkout feature/...`
2. Run `npm install && npm run dev`
3. Navigate to ...
4. Expect to see ...

## Screenshots (if applicable)

<!-- Before / After screenshots for UI changes -->

## Checklist

- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] No console.log left in code
- [ ] Accessibility considered
- [ ] Breaking changes noted above

Minimum requirements before requesting review:

  • All CI checks must pass (linting, type-checking, tests).

  • At least one reviewer assigned — preferably the team member most familiar with the affected code.

  • PR is small and focused: one logical change per PR, ideally under 400 lines changed.

  • Self-review performed: the author reads their own diff before tagging reviewers.

  • Description filled out — not just the default template with nothing in it.

Branch Protection Setup

Branch protection rules on GitHub prevent direct pushes to main, enforce review requirements, and block merges when CI is red.

Recommended settings for main on GitHub (Settings → Branches → Add rule):

  • Require a pull request before merging — prevents direct commits.

  • Required approvals: 1 or 2 — 1 for small teams, 2 for critical services.

  • Dismiss stale pull request approvals when new commits are pushed — re-review after any change.

  • Require status checks to pass before merging — select your CI jobs (tests, lint, build).

  • Require branches to be up to date before merging — prevents merge of stale code.

  • Do not allow bypassing the above settings — applies even to administrators.

  • Restrict who can push to matching branches — limit to release managers for hotfix scenarios.

.github/workflows/ci.yml — minimal CI to protect main

YAML
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck
      - run: npm test -- --coverage
Onboarding a New Team Member

A clear onboarding checklist means a new developer can make their first PR on day one without asking where everything is.

Day 1 checklist:

  1. Create a GitHub account and request organisation access from the team lead.

  2. Set up SSH key and add it to GitHub: ssh-keygen -t ed25519 -C "you@example.com" → copy ~/.ssh/id_ed25519.pub to GitHub Settings → SSH keys.

  3. Clone the repository: git clone git@github.com:org/project.git && cd project.

  4. Configure local Git identity: git config user.name "Your Name" and git config user.email "you@company.com".

  5. Install dependencies: npm install (or yarn install / pnpm install).

  6. Run the project locally to confirm it works: npm run dev.

  7. Read CONTRIBUTING.md — this is the single source of truth for workflow, branch naming, and commit style.

  8. Create a test branch to verify you have push access: git checkout -b chore/test-access && git push origin chore/test-access.

  9. Open a "Getting started" PR with a trivial change (fix a typo, add your name to CONTRIBUTORS) to practice the PR process end to end.

  10. Delete the test branch after the PR is merged.

Conflict Resolution Policy

Merge conflicts are inevitable. A written policy prevents arguments and wasted time:

  • The branch author is responsible for resolving conflicts — not the reviewer, not the person who merged first.

  • Rebase your feature branch on main rather than merging main into your branch: git fetch origin && git rebase origin/main. This keeps history linear.

  • For complex conflicts, pair with the author of the conflicting code. Do not guess their intent.

  • When a conflict is in a generated file (lock file, build output), regenerate the file rather than manually editing the conflict markers.

  • Always run tests after resolving conflicts before pushing.

  • If a conflict is unresolvable in a reasonable time, open a discussion in the PR thread rather than blocking indefinitely.

Day-in-the-Life Walkthrough

Here is a complete example of a developer named Alex building the "dark mode toggle" feature using GitHub Flow.

1. Start the day — sync with main

Bash
git checkout main
git pull origin main
# Already up to date.
# From github.com:org/project
#  * branch            main -> FETCH_HEAD

2. Create a feature branch

Bash
git checkout -b feature/dark-mode-toggle
# Switched to a new branch 'feature/dark-mode-toggle'

3. Work, stage, and commit incrementally

Bash
# ... edit src/components/ThemeToggle.tsx ...
git add src/components/ThemeToggle.tsx
git commit -m "feat(ui): add ThemeToggle component"

# ... edit src/context/ThemeContext.tsx ...
git add src/context/ThemeContext.tsx
git commit -m "feat(theme): add ThemeContext with dark/light support"

# ... add tests ...
git add src/components/ThemeToggle.test.tsx
git commit -m "test(ui): add unit tests for ThemeToggle"

4. Before pushing — rebase on latest main

Bash
git fetch origin
git rebase origin/main
# Successfully rebased and updated refs/heads/feature/dark-mode-toggle.

5. Push and open a PR

Bash
git push origin feature/dark-mode-toggle
# Enumerating objects: 7, done.
# Counting objects: 100% (7/7), done.
# Writing objects: 100% (4/4), 1.23 KiB | 1.23 MiB/s, done.
# remote: Create a pull request for 'feature/dark-mode-toggle':
# remote:   https://github.com/org/project/pull/new/feature/dark-mode-toggle

Alex opens the PR, fills in the template, assigns a reviewer, and waits. The reviewer requests one change.

6. Address review feedback

Bash
# Fix the issue the reviewer flagged
git add src/components/ThemeToggle.tsx
git commit -m "fix(ui): use prefers-color-scheme for initial theme"
git push origin feature/dark-mode-toggle

7. PR approved and merged — clean up

Bash
# After the PR is merged on GitHub:
git checkout main
git pull origin main
git branch -d feature/dark-mode-toggle
# Deleted branch feature/dark-mode-toggle (was a3f9c21).
Tip
Configure Git to prune remote-tracking branches automatically: `git config --global fetch.prune true`. Then `git fetch` will clean up references to branches deleted on the remote.
CONTRIBUTING.md Template

Every repository should have a CONTRIBUTING.md in the root. Here is a template your team can adapt:

CONTRIBUTING.md

Text
# Contributing to <Project Name>

Thank you for contributing! Please read this guide before opening an issue
or pull request.

## Development setup

```bash
git clone git@github.com:org/project.git
cd project
npm install
npm run dev          # start local server
npm test             # run tests
npm run lint         # lint & typecheck
```

## Workflow

We use **GitHub Flow**:

1. Branch off `main`: `git checkout -b feature/your-feature`
2. Commit using Conventional Commits (see below).
3. Push and open a pull request against `main`.
4. At least one approval + all CI checks green = ready to merge.
5. Delete your branch after merge.

## Branch naming

| Prefix      | Use for                       |
|-------------|-------------------------------|
| feature/    | New features                  |
| fix/        | Bug fixes                     |
| hotfix/     | Urgent production fixes       |
| chore/      | Maintenance, deps, tooling    |
| docs/       | Documentation                 |
| test/       | Test additions/fixes          |

## Commit messages

We follow the Conventional Commits spec. Format:

```
<type>(<scope>): <description>
```

Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore

Example: `feat(auth): add password reset flow`

## Pull requests

- Keep PRs small and focused — one logical change per PR.
- Fill in the PR template fully.
- Link to the related issue: `Closes #123`.
- All CI checks must pass.
- Request review from at least one team member.

## Code style

Run `npm run lint` before pushing. The project uses ESLint + Prettier.
Configuration is in `.eslintrc.json` and `.prettierrc`.

## Questions?

Open a GitHub Discussion or post in #dev-help on Slack.