← Stackzilla Blog
Git Workflows That Survive Contact with a Real Team
Published May 9, 2026
· 6 min read
· Git, GitHub, version control, CI/CD, development workflow, DevOps
The Git workflow you pick shapes how often you deal with merge conflicts, how fast you can deploy, and how easy it is to track down what changed and why. These are not small things.
Git is one of the most universally used tools in software development and one of the least formally taught. Most developers learned Git by doing — picking up commands as needed, absorbing branching conventions from whatever team they joined first, and developing habits that may or may not serve them well as teams and codebases grow.
The branching and merging strategy your team uses shapes how frequently you deal with merge conflicts, how fast your deployment cycle runs, how easy it is to isolate and investigate bugs, and how readable your project history is six months later. These are not minor concerns.
**The Main Models**
Three branching strategies dominate production team workflows. Understanding what each one assumes about how you ship is the starting point for choosing between them.
Gitflow was the influential model for much of the 2010s. It organizes work around long-lived branches: a main branch representing production, a develop branch integrating finished features, release branches cut from develop for testing and release preparation, hotfix branches off main for urgent production fixes, and feature branches off develop for individual pieces of work.
Gitflow was designed for scheduled releases — software that ships every few weeks or months after a formal testing period. The branch structure enforces a release process that maps to that cadence. For teams operating this way, it works. For teams that deploy continuously or want to, the overhead of maintaining develop and release branches actively works against fast iteration. The merge complexity grows proportionally with team size.
Trunk-based development is the model high-performing teams have largely converged on. All developers work from short-lived feature branches — ideally merged to main within a day or two, certainly within a week. Main is always deployable. Releases happen from main, either continuously or on a regular cadence. The discipline this requires is higher: work-in-progress must be hidden behind feature flags if it is not ready for users, and the CI pipeline must be fast and reliable enough that developers get feedback quickly.
The payoff is a history that is readable, a deployment model that scales, and a dramatically reduced merge conflict burden. When branches live for days rather than weeks, they diverge from the main branch by hours of work rather than by entire sprints.
GitHub Flow is a simplified implementation of trunk-based development with an explicit pull request step: branch from main, do the work, open a pull request, get it reviewed, merge it. For most product teams, this is the right amount of structure — enough to enforce code review, not so much that the process creates bottlenecks.
**Pull Request Culture**
The branching model is only as effective as the pull request habits around it. Pull requests that sit open for three days create exactly the kind of branch divergence that trunk-based development is designed to prevent. Teams that ship quickly review pull requests within hours, not days.
Making this work consistently requires deliberate decisions about team norms. Some teams designate review windows — times of day when engineers are expected to prioritize pending reviews. Others use automated reminders. Others simply make it a norm that shipping is blocked until reviews happen, creating the incentive structure that keeps things moving.
Pull request templates that make the scope and testing status of a change explicit reduce the back-and-forth in reviews. CI checks that run fast — under ten minutes for the feedback loop to close — make it practical to review and merge frequently.
**Commit Message Standards**
How commits are written affects more than aesthetics. A clean commit history makes it possible to identify when and why a change was made, which is valuable when debugging production issues or onboarding new team members.
Conventional Commits has emerged as the standard for teams who want readable histories and automated tooling. The format specifies a type prefix (feat for new features, fix for bug fixes, chore for maintenance, docs for documentation, refactor for structural changes, test for test additions) followed by a short description. A commit that introduces a new API endpoint might read: feat(api): add rate limiting to authentication endpoints.
Tools built on Conventional Commits — semantic-release, conventional-changelog, and others — can generate release notes and determine version numbers automatically from a clean commit history, which removes manual overhead from the release process.
**Monorepos and Multi-Package Workflows**
As applications have grown into multiple services, shared libraries, and interdependent packages, monorepos have become more common — particularly in JavaScript ecosystems where teams maintain both frontend and backend code alongside shared types, utilities, and component libraries.
Nx and Turborepo are the two dominant tools for managing JavaScript monorepos. Both provide smart build caching: if you change a package, only that package and the packages that depend on it need to be rebuilt. Turborepo focuses on simplicity and speed; Nx provides a more feature-complete platform with code generation, dependency graph visualization, and a plugin ecosystem.
The decision between them usually comes down to how much structure you want. Turborepo gets you to a working monorepo faster. Nx gives you more tools as the monorepo grows in complexity.
**Merge Strategies: Merge Commits vs Squash vs Rebase**
When merging a pull request, most Git hosting platforms offer three options: a standard merge commit, a squash merge that collapses the branch into a single commit, or a rebase that replays the branch commits on top of main.
Squash merging produces the cleanest main branch history — each pull request appears as a single, well-described commit — at the cost of losing the granular commit history from the branch. For most product teams, this trade-off favors squash merging. The main branch history is the one people navigate when debugging, and a readable per-feature history is more useful than granular per-commit history.
Rebase keeps the granular commits but requires that they are individually well-formed and meaningful, which is rarely the case for work-in-progress commits. It is the right choice for open-source libraries where commit-level history has documentation value, not for most product teams.
**The Honest Take**
For most teams in 2026, GitHub Flow — short-lived branches, pull requests, fast review, squash merge to main — is the right workflow. It is simple enough to be followed consistently, rigorous enough to enforce code review, and compatible with continuous deployment. Gitflow is the right answer if your shipping cadence genuinely requires it and you have the team discipline to operate it correctly. Trunk-based development without pull requests is an option for very high-trust, very senior teams. The workflow that gets followed consistently beats the workflow that is theoretically optimal but creates enough friction that people route around it.
Read the full article on Stackzilla →