Skip to main content
{/}codefunc
WorkflowJuly 7, 2026 · 8 min read

Git Workflow for Frontend Teams: Branches, Commits, and Collaboration Patterns

A practical guide to Git for frontend developers — branching strategies, commit conventions, pull request workflows, and the commands you'll use daily on product teams.

By codefunc

gitgithubversion-controlcollaborationfrontendworkflow

Git is version control. It tracks changes to files over time, lets multiple developers work on the same codebase, and provides a history you can search, blame, bisect, and revert. For frontend teams, Git is where code review happens, where CI runs, and where the record of every shipped feature lives. Understanding Git workflow — not just commands — is what makes collaboration smooth.

Bottom line: Commit small, commit often. Branch for features. Rebase or merge consistently. Write commit messages that explain why, not just what. Pull requests are conversations, not just merge gates. A clean Git history is documentation that never goes stale.

Git fundamentals

The three states

State Location Description
Working directory Your files Current edits, untracked changes
Staging area Index Changes ready to commit
Repository .git folder Committed history
# See current state
git status

# Move changes through states
git add file.tsx        # working → staging
git commit -m "message" # staging → repository
git push origin branch  # local repo → remote repo

Essential commands

Command Purpose
git clone <url> Copy remote repo locally
git pull Fetch and merge remote changes
git push Upload local commits to remote
git branch List, create, delete branches
git checkout / git switch Switch branches
git merge Combine branches
git rebase Replay commits on new base
git stash Temporarily save uncommitted changes
git log View commit history
git diff Compare changes

Branching strategies

Feature branches

The most common pattern for product teams:

main (production)
  └── feature/add-json-formatter
  └── feature/update-header-nav
  └── fix/contrast-checker-edge-case
  1. Create a branch from main
  2. Make changes, commit
  3. Open pull request
  4. Review, approve, merge
  5. Delete branch
# Create and switch to new branch
git checkout -b feature/add-json-formatter

# Or with git switch (newer)
git switch -c feature/add-json-formatter

Branch naming conventions

Prefix Use for
feature/ New functionality
fix/ Bug fixes
refactor/ Code restructuring
docs/ Documentation changes
chore/ Build, config, tooling
test/ Test additions or fixes

Include ticket numbers when your team uses them:

feature/PROJ-123-user-auth
fix/PROJ-456-mobile-nav-overflow

Trunk-based development

For teams that ship continuously:

  • main is always deployable
  • Feature branches live hours, not days
  • Small commits, frequent merges
  • Feature flags hide incomplete work
# Short-lived branch
git checkout -b feature/button-variant
# ... small change ...
git push -u origin feature/button-variant
# ... open PR, review, merge same day ...

Git Flow (less common now)

Longer release cycles with develop, release/*, hotfix/* branches. Adds ceremony. Most web teams have moved to simpler patterns with CI/CD.

Commits that communicate

Commit message format

<type>: <subject>

[optional body]

[optional footer]

Subject line:

  • Imperative mood ("Add feature" not "Added feature")
  • 50 characters max
  • No period at end

Body:

  • Why, not just what
  • Wrap at 72 characters
  • Separate from subject with blank line

Examples

# Simple change
git commit -m "Fix contrast ratio calculation for transparent backgrounds"

# With body
git commit -m "Add keyboard navigation to command palette

Users can now navigate results with arrow keys and select with Enter.
Focus management returns to trigger element on close.

Closes #234"

Conventional commits

A specification for machine-readable commit messages:

feat: add dark mode toggle
fix: prevent XSS in markdown preview
docs: update API response examples
refactor: extract validation logic to shared module
test: add unit tests for cron parser
chore: update dependencies

Tools can generate changelogs from conventional commits.

What makes a good commit

Guideline Reason
Atomic One logical change per commit
Complete Tests pass, lint passes
Explained Future you will forget why
Reviewable Small enough to understand in PR

Bad commit history:

wip
fix
fix again
actually fix
cleanup

Good commit history:

Add base64 encoding logic with edge case handling
Add UI components for base64 tool
Wire up encoder to transform tool pattern
Add unit tests for base64 encode/decode

Pull request workflow

Before opening a PR

# Make sure you're up to date
git fetch origin
git rebase origin/main

# Run quality checks locally
npm run lint
npm test
npm run build

# Push your branch
git push -u origin feature/your-branch

PR description template

## What

Brief description of the change.

## Why

Context: what problem does this solve?

## How

Implementation approach, if not obvious.

## Testing

How to verify the change works.

## Screenshots

If UI changed.

Review workflow

  1. Author opens PR with description
  2. Reviewers leave comments on code
  3. Author responds, makes changes, pushes
  4. Reviewers approve when satisfied
  5. Author or maintainer merges

Responding to review feedback

# Make requested changes
git add .
git commit -m "Address review: extract helper function"

# Or amend last commit if small fix
git add .
git commit --amend --no-edit
git push --force-with-lease

Use --force-with-lease instead of --force — it fails if someone else pushed to the branch.

Merge vs rebase

Merge commit

git checkout main
git merge feature/new-tool

Creates a merge commit preserving branch history. Pros: complete history. Cons: cluttered log.

Rebase and merge

git checkout feature/new-tool
git rebase main
git checkout main
git merge feature/new-tool --ff-only

Replays your commits on top of main. Pros: linear history. Cons: rewrites commits (don't rebase shared branches).

Squash merge

Combines all branch commits into one on merge. Common on GitHub PRs.

Pros: clean main history. Cons: loses granular commits.

Team decision

Pick one strategy and document it. Mixed approaches create confusing history.

Strategy Best for
Merge commits Preserving detailed branch history
Rebase + fast-forward Linear history purists
Squash merge Clean main, detailed work in PR

Handling conflicts

When Git can't auto-merge:

# During merge
git merge feature/branch
# CONFLICT: file.tsx

# Open conflicted files, look for markers
<<<<<<< HEAD
  current code
=======
  incoming code
>>>>>>> feature/branch

# Edit to resolve, then
git add file.tsx
git commit

Conflict prevention

  • Pull/rebase frequently
  • Communicate about shared files
  • Keep branches short-lived
  • Split large changes into smaller PRs

Useful Git commands

Undo and fix

# Unstage files
git reset HEAD file.tsx

# Discard working directory changes
git checkout -- file.tsx

# Amend last commit
git commit --amend

# Undo last commit, keep changes
git reset --soft HEAD~1

# Undo last commit, discard changes
git reset --hard HEAD~1

History exploration

# Pretty log
git log --oneline --graph --all

# Search commits
git log --grep="fix contrast"

# Who changed this line
git blame file.tsx

# Find commit that introduced bug
git bisect start
git bisect bad HEAD
git bisect good v1.0.0

Stashing work

# Save current changes
git stash

# List stashes
git stash list

# Apply most recent stash
git stash pop

# Apply specific stash
git stash apply stash@{2}

Cherry-pick

Copy a specific commit to current branch:

git cherry-pick abc1234

Useful for applying a fix to multiple branches.

Repository hygiene

.gitignore

Keep generated files, dependencies, and secrets out of the repo:

node_modules/
.next/
out/
dist/
.env
.env.local
*.log
.DS_Store

Generate a proper .gitignore for your stack with the Gitignore Generator.

.env templates

Never commit .env files with secrets. Instead:

# .env.example (committed)
DATABASE_URL=
API_KEY=
NEXT_PUBLIC_SITE_URL=

# .env.local (gitignored, real values)
DATABASE_URL=postgres://...

Generate environment templates with the Env Template Generator.

Sensitive data accidents

If you accidentally commit secrets:

  1. Rotate the credentials immediately
  2. Remove from history with git filter-branch or BFG Repo-Cleaner
  3. Force push (coordinate with team)
  4. Check GitHub's secret scanning alerts

Prevention is easier than cleanup.

CI/CD integration

Git triggers your pipeline:

# .github/workflows/ci.yml
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build

Branch protection

Configure on GitHub/GitLab:

  • Require PR reviews before merge
  • Require status checks to pass
  • Require linear history (no merge commits)
  • Restrict who can push to main

Team conventions checklist

Document and agree on:

  • Branch naming pattern
  • Commit message format
  • Merge strategy (merge/rebase/squash)
  • Required reviewers count
  • CI checks that block merge
  • Who merges PRs (author or reviewer)
  • How to handle urgent hotfixes

Comparing changes

When reviewing PRs or debugging, you often need to compare text. For quick file comparisons outside Git, use the Text Diff tool to paste and compare any two text blocks — config files, API responses, or generated output.

Practical takeaway

Git workflow is about communication as much as version control. Branch for isolation. Commit atomically with clear messages. Review code in PRs. Merge consistently. Keep main deployable. Use .gitignore and .env.example to keep the repo clean. When you inherit a project, git log tells you its story — make sure your commits add to that story clearly.

Sources

Try it on codefunc

Related articles

3

Search tools

Find a developer tool