Sharing a feature branch between developers Jump to heading

Most feature branches belong to one person, and their workflow — rebase freely, force-push, squash fixups — assumes it. When two people work on the same branch, those habits collide. One rebases and force-pushes, and the other’s next pull produces a tangle of duplicated commits. One pushes while the other is mid-rebase, and a plain --force silently discards the first person’s work. None of this needs a different branching model; it needs a few explicit agreements and settings that make the dangerous operations safe or impossible. This page sets those up for two or three people sharing a branch, within feature branch isolation.

When to use this approach Jump to heading

  • Two or more people commit to the same feature branch — pairing, a hand-over, or a large feature split across a small team.
  • Someone’s commits have disappeared after a colleague’s force-push.
  • git pull on a shared branch keeps producing merge commits or duplicated commits.
  • The branch will live for more than a day or two; for long-lived shared branches, also see keeping a long-lived branch in sync with main.

Step 1 — Agree who may rewrite history, and when Jump to heading

The core rule: on a shared branch, nobody rewrites history that others have fetched without telling them first. In practice teams pick one of two policies.

Two policies for a shared branchUnder an append-only policy, nobody rebases or amends pushed commits; everyone pulls with rebase for their local work only, and the branch is cleaned up once before merging. Under a designated-owner policy, one person may rewrite the branch at agreed times, announced in advance, and others reset afterwards.Append-onlyDesignated ownerrebase pushed commitsneverowner only, announcedothers after rewriten/areset to new tiphistory before mergecleaned once at the endclean throughoutrisk of lost workvery lowlow with leaseappend-only is simplest — choose it unless the branch must stay tidy for review throughout

Write the choice in the pull request description, so anyone joining the branch knows.

Step 2 — Pull with rebase for your local commits only Jump to heading

To avoid “Merge branch ‘feature/x’ of origin into feature/x” commits, rebase your unpushed commits onto the shared tip when pulling. This rewrites only your local, unshared work.

git config --global pull.rebase true
git config --global rebase.autoStash true
git pull                 # replays your unpushed commits on top of what your colleague pushed

The details and edge cases of this setting are in configuring git pull --rebase safely for a team.

# Verification: no merge commits from pulls on the shared branch
git log --merges --oneline origin/main..origin/feature/export-scheduling | grep -c "of github.com" || true

Step 3 — Never plain --force; use a lease with inclusion check Jump to heading

If a force-push is needed — under the designated-owner policy — --force-with-lease refuses if the remote branch moved since you last fetched. --force-if-includes (Git 2.30+) adds a second check: your local branch must already include the remote tip you are about to overwrite, which catches the case where a background fetch updated your lease without you ever looking at the new commits.

git config --global alias.pushf 'push --force-with-lease --force-if-includes'
git pushf
How the lease protects a colleague's pushAlice and Bob both have the branch at commit C. Bob pushes D. Alice, who rebased locally without fetching, force-pushes with a lease expecting C. The server sees the branch is at D, not C, and rejects the push, so Bob's commit is not lost. Alice fetches, rebases onto D and pushes again.Aliceremote branchBobpush D (branch was C)force-with-lease, expect Crejected: branch is Dfetch, rebase onto Dpush againplain --force would have accepted Alice's push and silently dropped D

⚠️ SAFETY WARNING: git push --force on a shared branch can silently delete a colleague’s commits. If it happens, the lost commits are still in the colleague’s local reflog and usually on the server for a while; recover them as in recovering from an accidental force-push. Configure the alias above and stop using plain --force entirely.

Step 4 — Recover cleanly after someone rewrites the branch Jump to heading

When the branch owner announces a rewrite, everyone else resets their local branch to the new tip — keeping any unpushed work by rebasing it onto the new history, not by merging the old history back in.

git fetch origin
# If you have no unpushed commits:
git switch feature/export-scheduling && git reset --hard origin/feature/export-scheduling
# If you do: replay only your own commits onto the rewritten branch
git rebase --onto origin/feature/export-scheduling "$(git merge-base --fork-point origin/feature/export-scheduling)"

--fork-point uses the remote-tracking reflog to find where your local work diverged from the old remote history, so only your commits are replayed. The general --onto technique is in rebasing onto a new base with --onto.

Step 5 — Split the branch when people stop overlapping Jump to heading

If two people sharing a branch are actually working on separable parts, give each a branch based on the shared one and merge them back — or stack them, so each part can be reviewed on its own. Shared branches work best for a short period of tight collaboration.

git switch -c feature/export-scheduling-ui feature/export-scheduling
git switch -c feature/export-scheduling-api feature/export-scheduling
Keep sharing, or split?If both people touch the same files and need each other's changes constantly, keep one shared branch with append-only rules. If they work on separable parts, split into branches off the shared one. If one part depends on the other, stack the branches so each can be reviewed separately.How do the two people's changes relate?same files, constant overlapKeep sharedappend-only rulesseparable partsSplit branchesmerge back laterone builds on the otherStack branchesreview in ordersharing is a tool for close collaboration, not a default

Stacking is covered in stacked pull requests without a dedicated tool.

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Can the server enforce append-only on a feature branch? Jump to heading

Yes — apply a ruleset blocking force-pushes to the branch, or to a prefix such as shared/*. Most teams reserve that for long-lived shared branches rather than every feature.

Who should clean up history before merging? Jump to heading

Under append-only, one person does it once, after announcing it and when everyone else has pushed. Squash merging avoids the question entirely, at the cost of losing per-commit history.

What if both people need to amend the same commit? Jump to heading

That is the sign the branch has become one person’s job for the moment. Let one person finish that part, push, and hand back.