Skip to main content
Git is designed to support a wide variety of development workflows. This guide covers recommended workflow patterns and strategies for using Git effectively in team environments.

Separate Changes into Logical Commits

As a general rule, you should try to split your changes into small logical steps, and commit each of them. This makes the review process much easier and the history much more useful for later inspection.
1

Make small, focused commits

Each commit should represent a single logical change that passes tests and works independently of later commits.
2

Split work from the beginning

It’s always easier to squash a few commits together than to split one big commit into several. Don’t be afraid of making too small or imperfect steps along the way.
3

Use interactive rebase to refine

You can always go back and edit commits with git rebase --interactive before you publish them:
git rebase -i HEAD~3  # Edit last 3 commits
Use git stash push --keep-index to run the test suite independent of other uncommitted changes. This helps verify that each commit works in isolation.

Managing Branches

Branches are the foundation of effective Git workflows. Understanding how to manage them properly is crucial for team collaboration.

Topic Branches

Use topic branches for every feature, bugfix, or experiment:
1

Create a branch for each topic

Make a side branch for every topic (feature, bugfix, refactoring). Fork it off from the oldest integration branch that you will eventually want to merge it into.
git switch -c feature/user-authentication main
2

Work independently

Develop your changes on the topic branch without affecting the main branches.
# Make changes
git add .
git commit -m "Add user login functionality"
3

Merge when ready

To get the feature into an integration branch, simply merge it:
git switch main
git merge feature/user-authentication

Branch Management Rules

Merge upwards: Always commit your fixes to the oldest supported branch that requires them, then periodically merge the integration branches upwards into each other.
# Fix in maintenance branch
git switch maint
git commit -m "Fix critical bug"

# Merge upwards
git switch main
git merge maint
Do not merge to downstream except with a good reason: upstream API changes affect your branch, your branch no longer merges to upstream cleanly, etc. Habitually merging an integration branch into your topics clutters history.
Avoid rebasing merged branches: Once a topic has been merged elsewhere, it should not be rebased. Rebasing published history can cause significant problems for collaborators.

Common Workflow Patterns

Feature Branch Workflow

The feature branch workflow is ideal for teams of any size:
1

Create a feature branch

git switch -c feature/new-feature main
2

Develop and commit changes

# Work on your feature
git add file1.js file2.js
git commit -m "Implement first part of feature"

# Continue working
git add file3.js
git commit -m "Complete feature implementation"
3

Keep branch updated (optional)

If main has moved forward and you need recent changes:
git switch main
git pull
git switch feature/new-feature
git merge main  # Or: git rebase main
4

Push and create pull request

git push -u origin feature/new-feature
# Then create a pull request through your Git hosting service

GitFlow Workflow

GitFlow uses multiple long-lived branches with specific roles:
  • main: Production-ready code
  • develop: Integration branch for features
  • feature/*: New features (branch from develop)
  • release/*: Release preparation (branch from develop)
  • hotfix/*: Emergency fixes (branch from main)
# Start a new feature
git switch -c feature/user-profile develop

# Work on feature
git commit -am "Add profile page"

# Finish feature
git switch develop
git merge --no-ff feature/user-profile
git branch -d feature/user-profile

# Create a release
git switch -c release/1.2.0 develop
# ... make release-specific changes
git switch main
git merge --no-ff release/1.2.0
git tag -a v1.2.0
git switch develop
git merge --no-ff release/1.2.0
git branch -d release/1.2.0

Forking Workflow

Common in open-source projects where contributors don’t have direct push access:
1

Fork the repository

Create a personal copy of the repository through your Git hosting service.
2

Clone your fork

git clone https://github.com/your-username/project.git
cd project
git remote add upstream https://github.com/original/project.git
3

Create a feature branch

git switch -c feature/my-contribution
# Make changes and commit
4

Keep your fork synchronized

git fetch upstream
git switch main
git merge upstream/main
git push origin main
5

Submit a pull request

Push your feature branch to your fork and create a pull request to the upstream repository.
git push origin feature/my-contribution

Integration Branches

Larger projects often use multiple integration branches for staged feature graduation:
  • maint: Maintenance releases for the last stable version
  • main/master: The next release
  • next: Testing branch for topics being tested for stability
  • seen: Integration branch for things not quite ready yet
Each branch is usually a direct descendant of the one above it. Features enter at an unstable branch and “graduate” to main once considered stable.

Throw-away Integration

To test the interaction of several topics without committing to the merge:
git switch -c test-integration main
git merge topic1
git merge topic2
git merge topic3
# Test the combined changes

# If satisfied, merge topics individually into main
git switch main
git merge topic1
git merge topic2
Never base any work on throw-away integration branches! These branches should be deleted after testing.

Distributed Workflows

Merge Workflow

The merge workflow uses branches to share complete history between repositories:
# Publishing changes
git push origin feature-branch

# Staying up to date
git fetch origin
git merge origin/main

# Pulling others' changes (as maintainer)
git pull https://github.com/contributor/repo feature-branch

Patch Workflow

The patch workflow uses email to share changes:
1

Create patches from commits

git format-patch -M upstream..topic
2

Send patches via email

git send-email --to=maintainer@project.org *.patch
3

Apply received patches (as maintainer)

git am < 0001-patch-file.patch
Use git am -3 for three-way merge if conflicts occur.
4

Update patches when requested

git pull --rebase upstream main
git format-patch -M upstream..topic

Release Management

Creating a Release

1

Verify main is a superset of maint

git log main..maint  # Should show no commits
2

Tag the release

git tag -s -m "Version 1.0.0" v1.0.0 main
3

Push the tag

git push origin v1.0.0

Maintenance Branch Management

After a feature release, update maintenance branches:
# Create maintenance branch for previous release
git branch maint-1.0 maint

# Fast-forward maint to new release
git switch maint
git merge --ff-only main
Consider using git request-pull to create formatted pull request summaries:
git request-pull upstream/main origin feature-branch

Choosing the Right Workflow

Consider these factors when selecting a workflow:
  • Team size: Smaller teams can use simpler workflows
  • Release cadence: Frequent releases benefit from streamlined processes
  • Collaboration model: Centralized vs. distributed
  • Project maturity: Established projects may need more structure
  • Deployment strategy: Continuous deployment vs. scheduled releases
Don’t blindly follow any workflow. Value good reasons for your actions higher than rigid rules. Adapt workflows to your team’s needs.