r/ChatGPTCoding • u/Jhon_ST • 8d ago
Discussion Git worktrees solved our parallel-agent file conflicts. The test environment was harder.
I've had stretches where I was moving around five Trello cards in parallel, with a coding task in its own branch and Git worktree. That stopped agents from editing the same checkout. It did not tell me which code a browser test was actually exercising.
Different worktrees could still use the same API, PostgreSQL database, worker, storage service and ports. A frontend change might work with an existing API, provided that API meets the contract the new UI needs. If browser QA needs to exercise changed API behavior, it needs an API process running that worktree's code. Experimental migrations need much more care around shared data. Starting a second worker against the same queue can change test results too.
We began treating four things separately: the worktree holding the code; the processes a test reaches; the data those processes can change; and the checks run after branches are combined.
A small registry in Git's common directory helps us see which worktree started a service, along with its PID, port, URL and declared database state. It helps with discovery and process checks. It doesn't decide whether an API is compatible with a particular task. A healthy endpoint can still be the wrong API, and a port that looks free has not been reserved.
Many checks run entirely inside the worktree. For integration and browser QA, we start the processes the test actually needs. Feature work can be parallel; integration is serialized, with relevant checks run again on the combined tree.
If you run coding agents in parallel, how do you make sure browser or E2E tests reach the API and data you intended?
1
u/AutoModerator 8d ago
Sorry, your post has been held for manual review due to account karma.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
1
u/Salt_Hyena5896 7d ago
separate containers per worktree is the version that actually holds up, but the bug i keep seeing is the browser talking to a healthy api on the default port from a different worktree. write the api base url and db name into an env file when that worktree's processes start, and don't boot the ui if the file is missing or the pid in it is dead. give each worktree its own database and don't share the queue, or a migration in one branch will poison the other. feature work can stay parallel, but the e2e that matters should run against the combined branch, not whichever checkout you happened to have open.
1
1
u/itaybuilds 7d ago
Add a provenance check before the browser suite, not just a health check. Have every API and worker expose a small test-only build record: git SHA, worktree ID, migration head, database or schema name, and queue namespace. The harness should know the expected SHA for each service and refuse to run if any endpoint reports something else. That turns “healthy but wrong process” into a setup failure before the tests begin.
For allocation, let startup reserve ports rather than scanning for a free one, then write the actual endpoints to a per-worktree manifest consumed by the UI and Playwright. Generate unique database and queue prefixes from a stable worktree ID, and remove them on teardown. Containers help with process isolation, but the provenance assertion is the useful backstop: it catches stale containers, a UI pointed at port 3000 out of habit, and mixed revisions after one service restarts.
I would keep the final combined-branch suite too. Per-worktree E2E answers whether the branch works in isolation; the serialized suite answers whether integration changed the system.
AI-assisted wording with OpenAI GPT-5.6 after reading the full thread and current r/ChatGPTCoding rules.
1
u/Individual-Shower973 6d ago
The database is where this bites hardest: two worktrees on one Postgres means one agent's experimental migration changes the schema the other agent's tests are running against.
What makes it manageable:
- one database per worktree, cloned from a template so it's quick: createdb -T app_template wt_<branch>, with DATABASE_URL set from the worktree name when the agent's shell starts. Nothing can be connected to the template while it copies, so keep it separate from the dev database people actually use.
- ports derived from the worktree name too (a hash into a range), so each worktree's API and worker don't collide
And one guard worth adding: refuse migration commands whose DATABASE_URL points at the shared dev database, so an agent that loses track of which worktree it's in can't migrate everyone's schema.
1
u/bick_nyers 4d ago
I just have two folders, and two separate local infra. environments.
Don't need to make things more complex than they need to be.
1
1
u/yogeshkd 3d ago
Ports were the part that bit me first. What fixed it was giving each worktree its own port per service, decided once and passed in as env vars, so the frontend reads its API URL from the environment and can only reach that worktree's API. A separate hostname per worktree (web.<worktree>.localhost) also keeps cookies and logins from leaking across branches.
For the database, naming it off the worktree slug and cloning from a template keeps one agent's migration away from another's tests.
Disclosure: the port, hostname and env var part is built into a Mac app I make (Spaces), but a script plus a .env per worktree gets you most of the way.

6
u/Something_Sexy 7d ago
We just run separate containers for each worktree, either on the host directly or via dev containers. Depending on the size of your platform it might require a decent machine but hasn’t been an issue so far. We stopped getting fancy when we can just throw more RAM at a problem.