Testing a feature branch against the latest main Jump to heading
A feature branch’s tests pass against the main it was created from. That main is days or weeks old. Since then, others have changed shared code, renamed functions, updated dependencies. Whether your branch still works once merged depends on what main looks like now — and the only way to know is to test the combination. Merging main into the branch every day answers it but clutters the branch’s history and is irreversible if the result is confusing. A throwaway merge — build the combination, test it, throw it away — answers the question without touching the branch. CI can do the same automatically on every push. This page shows both, within feature branch isolation.
When to use this approach Jump to heading
- Your branch has been open for more than a day or two while main kept moving.
- You want to know whether the branch will work after merging, before asking for review.
- You prefer to keep the branch free of “merge main into feature” commits until it is ready.
- Your CI tests branch heads rather than merge results; the fix is described in catching semantic conflicts in CI.
Step 1 — Build a throwaway merge in a separate worktree Jump to heading
Use a temporary worktree so your working copy and branch are untouched. Merge the latest main into a detached HEAD there, and run the tests.
git fetch origin
git worktree add --detach ../merge-check feature/export-scheduling
cd ../merge-check
git merge --no-edit origin/main || { echo "conflicts — see git status"; exit 1; }
make test
cd - && git worktree remove --force ../merge-check Worktrees for this kind of side task are covered in running long builds in a separate worktree.
Step 2 — Check for conflicts without a build Jump to heading
Sometimes you only want to know whether the merge is clean. git merge-tree --write-tree answers that in memory, without any worktree.
git fetch origin
if git merge-tree --write-tree --name-only --no-messages origin/main feature/export-scheduling >/tmp/mt; then
echo "merges cleanly with today's main"
else
echo "conflicts in:"; tail -n +2 /tmp/mt
fi The full set of previewing techniques is in previewing merges with git merge-tree.
Step 3 — Let CI test the merge result on every push Jump to heading
Forges compute a merge of each pull request into its base and expose it as a ref; CI can test that instead of the branch head. On GitHub, pull_request workflows do this by default; GitLab calls them merged results pipelines.
on: pull_request # actions/checkout uses refs/pull/<n>/merge by default
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: git log -1 --format='testing %h with parents %p' # two parents: the merge
- run: make test The merge ref is recomputed when the branch is pushed, not when main moves. A green check from yesterday may be stale today; re-run the workflow, or rely on a merge queue to test the final combination.
Step 4 — Decide when to actually integrate main Jump to heading
Testing the combination tells you whether integrating will hurt; it does not integrate. When the branch is ready for review, or when tests against main start failing in ways that need code changes on the branch, bring main in for real — by rebase or merge, depending on team policy.
# Rebase onto the latest main (rewrites the branch; force-push with lease)
git rebase origin/main && git push --force-with-lease
# Or merge main in (keeps history, adds a merge commit)
git merge origin/main && git push The trade-offs are covered in rebasing a feature branch before merge.
Step 5 — Make the check a daily habit for long branches Jump to heading
For branches that stay open longer than a few days, run the throwaway merge on a schedule and post the result, so problems show up the day main introduces them.
# Nightly: test every open feature branch against main, report failures
for b in $(git for-each-ref --format='%(refname:lstrip=3)' 'refs/remotes/origin/feat/*' 'refs/remotes/origin/fix/*'); do
git merge-tree --write-tree --no-messages origin/main "origin/$b" >/dev/null 2>&1 \
|| echo "CONFLICT $b"
done Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Does a throwaway merge leave anything behind? Jump to heading
The temporary merge commit exists only in the worktree and becomes unreachable when the worktree is removed; garbage collection cleans it up later. Your branch and working copy are unchanged.
Why not just rebase every morning? Jump to heading
Rebasing rewrites the branch, forcing collaborators to reset and invalidating review comments tied to commits. A throwaway merge gives the same information without those costs, so you rebase only when needed.
What if the throwaway merge conflicts? Jump to heading
That tells you integrating will need work. You can resolve it in the worktree to see how hard it is — with rerere enabled, the resolution is remembered for when you integrate for real, as described in rerere for long-lived topic branches.
Related Jump to heading
- Feature Branch Isolation — the parent topic.
- Keeping a Long-Lived Branch in Sync with Main — when integration becomes routine.
- Measuring Branch Age Against Conflict Risk — why testing early matters.
- Reviewing a Pull Request in a Second Worktree — the same worktree technique for reviewers.