Most git workflow writing assumes a team of twenty or more engineers, and imports the ceremony that scale actually needs, long-lived feature branches, mandatory multi-reviewer approval, release branches, into a team of two people who talk to each other constantly. Most of that ceremony doesn’t add safety at two people. It adds friction, and friction at a two-person company has a real cost: it’s time not spent finding out whether anyone wants what you’re building.
Trunk-based, basically, and short branches
Branches that live hours, not days, merging to main constantly. With two people, the risk profile is inverted from what long-lived-branch workflows assume: the risk of a branch drifting out of sync with what your co-founder just changed is higher than the risk of a half-finished feature sitting behind a flag. If a feature genuinely needs more than a day, it goes behind a flag and merges incrementally, rather than living on a branch that both of you eventually have to reconcile by hand.
Code review at two people is often theater, so aim it deliberately
Requiring review on every single change when there are only two engineers usually isn’t catching bugs, you already discussed the feature over lunch, you already know what the other person is building. Treating review as a universal bug-catching gate at this size mostly produces rubber-stamp approvals that create a false sense of safety. What review is actually good for at this size is a second pair of eyes on the specific places a quiet mistake is expensive: anything touching payments, anything touching auth, anything that runs a data migration against real user data. Require review there, deliberately, and skip the ceremony everywhere else.
Commit messages you’ll actually thank yourself for
Not fix bug, what changed and why it changed. Six months from now, git blame on a strange-looking line is the only documentation that will still exist, since neither of you will remember the specific conversation where you decided to handle an edge case a particular way. A commit message that explains the reasoning, not just the diff, is the cheapest form of institutional memory a two-person team can leave for its future self, or for the third and fourth engineers who show up later with no access to the conversation that produced the code.
The one rule worth enforcing mechanically
Discipline doesn’t scale, even across two people, especially under deadline pressure. The one thing worth making impossible rather than discouraged: nothing merges to main with a failing build or failing tests, enforced through a required CI check on the branch, not a personal habit. At two people there’s no one else who’s going to catch a broken build before a user does, and a five-minute CI check is a much cheaper failure mode than finding out in production.
# .github/workflows/ci.yml
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint
- run: npm run build
- run: npm test
# branch protection: require this check to pass before merging to mainThe actual takeaway
The goal of a git workflow at this size isn’t process for its own sake, and it isn’t importing a workflow built for a company ten times your size either. It’s making sure the corners you cut, and you should be cutting some, are the ones you chose on purpose, not the ones that slipped through because nothing was actually checking. Short branches, review aimed at the genuinely expensive mistakes, commit messages written for your future self, and one CI gate that can’t be skipped under pressure: that’s most of what actually matters before the team is big enough to need anything more.