跪拜 Guibai
← All articles
Backend · Git · Developer

Six Branches, Five Paths, Eight Rules: The Git Workflow That Ended All-Night Merge Conflicts

By 挖掘狂人 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

The double-merge rule and the one-branch-one-environment mapping are the two practical checks that stop the most common release fires. Teams that only fix main and forget develop pay for it with a rerun of the same bug, and anyone who deploys the wrong branch to an environment spends hours verifying which code is live.

Summary

A Git collaboration overhaul from a Chinese team cuts merge conflict marathons by fixing every path code can take. The system runs six branches: main, develop, feature, test, release, and hotfix, each with a single source and a single merge destination. Five merge paths are canonical, from daily feature work to emergency hotfixes, and each is laid out in concrete git commands. The key enforcement: every hotfix must land in both main and develop, or the bug resurfaces next release. That rule came from a real incident where a fix to main never reached the dev line, and the bug returned two weeks later.

The team also ties each branch to exactly one environment: develop maps to DEV, release to FAT, main to PRO, and feature branches get no environment at all. That prevents half-finished work from being mistaken for a releasable version. Commit messages follow a seven-type convention (feat, fix, docs, style, refactor, perf, test) with a module scope, so the log becomes a searchable asset and changelogs can be auto-generated. Eight enforced rules back the model: branch protection on main and release, mandatory MR review plus CI, a 3-day lifespan cap for feature branches, --no-ff merges, tagged releases, double-merge for hotfixes, pull --rebase before push, and a no-new-features rule on release branches. The article ends with a two-step rollout plan: enable branch protection and require commit type prefixes first, then add the rest gradually.

Takeaways
— Six branches: main, develop, feature, test, release, hotfix; each has one source and one merge destination.
— Five fixed merge paths: feature->develop, develop->test, test->release->main->develop, main->hotfix->main+develop, and revert for rollback.
— Hotfixes must be merged to both main and develop; a missing develop merge resurrects the bug in the next release.
— Feature branches have no deployment environment; forbidding access prevents half-finished work from being accepted as a release.
— Commit format is <type>(<scope>): <subject>, with seven types: feat, fix, docs, style, refactor, perf, test.
— Branch protection on main and release prohibits direct pushes even by admins.
— All merges use --no-ff to preserve branch topology.
— Feature branches live at most 3 days; larger work is split into smaller iterations.
— Every release gets an annotated tag like v1.4.0.
— Before pushing, run pull --rebase to minimize merge commits.
— Release branches only accept bug fixes, not new features.
— Rollback uses git revert, never reset --hard on a remote main.
— Start with two changes first: enable main branch protection and force commit type prefixes.
Conclusions

Requiring feature branches to have no environment is a strong anti-footgun rule: the moment a half-finished feature is visible to testers or PMs, it becomes a potential release candidate and invalidates acceptance.

The hotfix double-merge is the most common failure point; many teams merge to prod and forget the dev branch, so the bug silently returns in a later release.

A middle-ground six-branch model beats both a minimal main+feature and full git-flow for small teams, because it gives structure without ceremony.

The eight rules are all enforceable in tooling; wikis and verbal agreements don't work, which is why the author made every rule a CI or MR gate.

Concepts & terms
UAT
User Acceptance Testing, the final sign-off environment where product owners and testers verify a release before it goes to production.
FAT
Functional Acceptance Testing, an intermediate environment that validates the feature set before UAT.
--no-ff
A git merge flag that forces a merge commit even when a fast-forward is possible, preserving the branch topology for later tracing.
Semantic versioning
A versioning scheme where major.minor.patch increments signal breaking changes, new features, and bug fixes respectively; the article maps feat to a minor bump and fix to a patch bump.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗