Git Workflow
A practical branching strategy for teams: feature branches, pull requests, and clean commit history.
Overview
A Git workflow defines how your team uses branches to manage parallel work, review changes, and keep the main branch stable. The workflow described here — often called “GitHub Flow” — is lightweight, scales from solo developers to large teams, and integrates naturally with CI/CD pipelines.
When to Use
Use this workflow when:
- Working in a team where multiple developers touch the same codebase. See GitHub Actions for CI/CD automation.
- You want every change to be reviewed before it reaches production. See Unit Testing for pre-merge validation.
- Your project deploys continuously from the main branch. See Docker Basics for containerized deployments.
- You need a clear rollback path when something goes wrong. See Feature Flags for instant toggles.
Solution
Branching Model
main ───────────────────────────────────────────►
\
feature/login ──────────► (PR → review → merge)
\
feature/payments ────────► (PR → review → merge)
Daily Commands
# Start a new feature
$ git checkout main
$ git pull origin main
$ git checkout -b feature/description
# Make commits
$ git add .
$ git commit -m "feat: add password reset endpoint"
# Push and open a pull request
$ git push -u origin feature/description
# Open PR on GitHub, request review, wait for CI to pass
# After merge, clean up
$ git checkout main
$ git pull origin main
$ git branch -d feature/description
Keeping a Clean History (optional)
# Before merging, rebase onto latest main
$ git fetch origin
$ git rebase origin/main
# If you have messy local commits, squash them
$ git rebase -i HEAD~3
# Change "pick" to "squash" for commits you want to combine
Commit Message Convention (Conventional Commits)
feat: add user authentication
fix: resolve race condition in checkout
docs: update API reference for v2
refactor: extract payment service
Explanation
mainis always deployable: only merge code that passes tests and review.- Feature branches isolate work: each feature, bugfix, or experiment lives in its own branch.
- Pull requests enforce quality: code review catches bugs, shares knowledge, and keeps standards consistent.
- Rebasing vs. merging: rebasing rewrites your branch on top of
mainfor a linear history; merging preserves the exact sequence of events. Use rebase for personal cleanup, merge for team history.
Variants
| Model | Best For | Complexity |
|---|---|---|
| GitHub Flow | Continuous deployment, small teams | Low |
| Git Flow | Scheduled releases, QA cycles | Medium |
| Trunk-based | Monorepos, very fast CI | Low |
| Release branches | Long-term support versions | Medium |
What Works
- Keep branches short-lived: a branch open for weeks accumulates merge conflicts and stale code. Aim for days, not weeks.
- Write meaningful commit messages: explain why, not just what. Future you (and your teammates) will thank you.
- Review your own PR first: read the diff before requesting reviewers. You will catch obvious issues.
- Automate with CI: run lint, tests, and security scans on every pull request before anyone reviews.
- Protect main: require PR reviews, passing CI, and up-to-date branches before merging into
main.
Common Mistakes
- Long-running branches: the longer a branch lives, the harder it is to merge. Rebase frequently.
- Committing to main directly: even in a solo project, using branches keeps your history clean and rollback easy.
- Giant pull requests: PRs with hundreds of files are impossible to review well. Split large capabilities into stacked PRs.
- Ignoring merge conflicts: resolving conflicts hastily without understanding both sides introduces bugs.
- Messy commit history: “fix”, “fix again”, “actually fix” makes
git blameuseless. Squash or amend before pushing.
Performance Tips
- Use shallow clones for CI. Reduce clone time by fetching only the latest commit:
$ git clone --depth 1 https://github.com/org/repo.git
# For a specific branch:
$ git clone --depth 1 --branch main https://github.com/org/repo.git
- Use
git sparse-checkoutfor monorepos. Check out only the directories you need:
$ git clone --no-checkout https://github.com/org/monorepo.git
$ cd monorepo
$ git sparse-checkout init --cone
$ git sparse-checkout set packages/api packages/shared
$ git checkout main
- Enable
fsmonitorfor faster status checks. Git uses the OS file watcher to detect changes:
$ git config core.fsmonitor true
$ git config core.untrackedcache true
- Use
git gcto optimize repository size. Run periodically to compress objects:
$ git gc --aggressive --prune=now
- Use
git worktreefor parallel work. Work on multiple branches simultaneously without cloning:
$ git worktree add ../repo-hotfix main
$ cd ../repo-hotfix
# Now you're on main in a separate directory
# Make hotfix changes while your feature branch stays open in the original Frequently Asked Questions
Should I use merge or rebase?
Use rebase to keep your feature branch up to date with main locally. Use merge (or squash-merge) when integrating the feature into main via a pull request. Never rebase branches that other people are working on.
How often should I commit?
Commit whenever you reach a logical checkpoint — a working test, a completed function, a fixed bug. Frequent commits make reverting and reviewing easier.
What if I commit a secret (password, API key) to Git?
Rotate the secret immediately — it is now in Git history. Use tools like git-filter-repo or BFG Repo-Cleaner to remove it from history, then force-push. Prevention beats cleanup: use pre-commit hooks with secret scanning.
Related Resources
Docker Basics
How to containerize an application, write a Dockerfile, and run containers with Docker Compose.
RecipeUnit Testing
How to write fast, deterministic unit tests with mocks and assertions in Python, JavaScript, and Java.
RecipeGitHub Actions CI/CD
How to build and deploy with GitHub Actions using workflows, matrices, caching, and secrets.
RecipeClean Git Commit History with Interactive Rebase
Squash, reorder, edit, and split commits with git rebase interactive. Covers pick, squash, fixup, reword, drop, and conflict resolution.
DocPull Request Template
A thorough pull request template to standardize code reviews and improve merge quality.
RecipeCron Jobs
How to schedule and manage recurring tasks using cron syntax across Linux, Python, and Node.js.