- Book: Ship It — the pragmatic startup tech stack
- Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
You have three agents in three worktrees. Each one has its own folder and its own branch, so you assume each one has its own git settings too. It doesn't. The git-worktree docs say it in one line: "By default, the repository config file is shared across all worktrees." The first agent that runs git config user.email changes the identity of all three.
That shared file is the first item on this list. The other nine decide how conflicts look, how pushes and fetches behave, and what happens to the worktrees nobody cleaned up. Everything is from the current Git docs, starting with the git-config reference (last updated in Git 2.56.0).
The examples use hermes/<name> branches, one per task. That is the layout Hermes IDE creates when you start a task, and I build Hermes, so weigh the last section with that in mind. Any naming scheme works the same way.
Give each worktree its own settings
1. extensions.worktreeConfig, then git config --worktree
Without it, every git config written inside a worktree lands in the one shared file, so a setting meant for one task applies to every task. Turn on the extension once per repository, then write per-task settings with --worktree:
# once, from any worktree of the repo
git config extensions.worktreeConfig true
# inside one task's worktree only
cd ../fix-login
git config --worktree user.name "Codex (fix-login)"
git config --worktree user.email codex@example.com
With the extension on, git-config loads $GIT_DIR/config.worktree on top of the shared file, and "the settings in the config.worktree file will override settings from any other config files." An identity per task is one use: git log --author=codex then finds that agent's commits. Run git rev-parse --git-path config.worktree to see which file a worktree writes to.
Two caveats from the worktree docs. If core.bare or core.worktree sit in the shared config, move them to the main worktree's config.worktree. And "Older Git versions will refuse to access repositories with this extension."

One shared config for every worktree, unless a worktree gets its own.
Make agent conflicts readable
2. merge.conflictStyle zdiff3
The default style shows your side and their side, and leaves out the original. When two agents rewrote the same function, the original is the one thing you need to see which agent changed what. Per git-config, diff3 adds the original text, and zdiff3 does the same but drops lines that match on both sides at the edges of the conflict.
git config --global merge.conflictStyle zdiff3
# redraw the markers of a file already in conflict
git checkout --conflict=zdiff3 src/login.js
The second command is from git-checkout: it re-creates the conflict in the style you name, overriding the config.
3. diff.algorithm histogram
Git's ort merge already lines up changes with histogram. The merge-strategies docs say "ort defaults to diff-algorithm=histogram, while regular diffs currently default to the diff.algorithm config setting", and that default is Myers. So the diff you review and the merge that lands it can pair up lines differently.
git config --global diff.algorithm histogram
An empirical study of Git's diff algorithms (Nugroho, Hata and Matsumoto, Empirical Software Engineering) found Histogram "more suitable than Myers for providing the changes of code" when applying patches.
4. rerere.enabled
Two agent branches that touch the same lines will make you resolve the same conflict more than once: in a trial merge, again in the rebase, again after the next rebase. git-rerere records your resolution the first time and replays it.
git config --global rerere.enabled true
# a recorded resolution was wrong
git rerere forget src/login.js
The record cache lives in rr-cache, which Git's own path.c lists among the shared directories, next to objects and refs. A conflict you resolve in one worktree is replayed in any other worktree of the repo. Recorded resolutions are pruned after 60 days by default. I walked through the full loop in Two Coding Agents Edited the Same File. Make Git Resolve It Once With rerere.
Push and fetch without stopping an agent
5. push.autoSetupRemote
Every task branch is new, so none of them has an upstream. Under the default push.default of simple, git-config says "the current branch must also have an upstream tracking branch with the same name" when you push back to the remote you pull from. The agent's first plain git push doesn't go through, and the agent has to work out --set-upstream on its own.
git config --global push.autoSetupRemote true
With it, a default push assumes --set-upstream "when no upstream tracking exists for the current branch".
6. fetch.prune
Agent branches are short-lived. Merge the pull request, delete the branch on the server, and your clone still keeps origin/hermes/fix-login. The git-fetch PRUNING section explains why: Git holds onto "local references to branches on remotes that have themselves deleted those branches." A few weeks of agent branches later, git branch -r is full of branches the server deleted long ago.
git config --global fetch.prune true
Rebase stacked tasks and find the newest branch
7. rebase.updateRefs
Sometimes task B starts from task A's branch instead of main. Rebase B and A is left pointing at the old commits. rebase.updateRefs turns on --update-refs, which, per git-rebase, "force-update[s] any branches that point to commits that are being rebased."
git config --global rebase.updateRefs true
Read the next sentence of those docs before you count on it: "Any branches that are checked out in a worktree are not updated in this way." If A's worktree is still open, A stays behind. Finish or remove A's worktree first, or detach it (git -C ../task-a switch --detach) so A isn't checked out anywhere, then rebase B. --no-update-refs turns it off for one rebase.
8. branch.sort -committerdate
git branch sorts by name by default, so the task that just finished is buried somewhere in the middle of hermes/*. branch.sort sets the default --sort key, and a leading - means descending (for-each-ref).
git config --global branch.sort -committerdate
git branch --list 'hermes/*'
The newest agent work is now on top. In that list, * is the branch you are on and + marks branches checked out in other worktrees, per git-branch.
Create and clean up worktrees
9. worktree.guessRemote
Say an agent on another machine pushed fix-login and you want it in a worktree. git worktree add ../fix-login with no branch argument creates a new fix-login from your HEAD. Same name, none of the agent's commits. With worktree.guessRemote, git-worktree looks for a remote-tracking branch that "uniquely matches the new branch name", checks it out and sets it as upstream.
git config --global worktree.guessRemote true
git fetch
git worktree add ../fix-login
# branch names with a slash: name the branch
git worktree add ../review hermes/fix-login
The guess matches the folder's basename, so it can't find hermes/fix-login. For that one, name the branch. If it exists in exactly one remote and not locally, git worktree add sets it up with --track for you.
10. gc.worktreePruneExpire, with lock and prune
A worktree folder deleted with rm -rf instead of git worktree remove leaves its admin files in .git/worktrees. git worktree list keeps showing it, marked prunable. Per git-config, git gc runs git worktree prune --expire 3.months.ago, so those records stay for three months. A shorter grace period clears them sooner:
git config --global gc.worktreePruneExpire 2.weeks.ago
# see what would go, then clean now
git worktree prune --dry-run --verbose
git worktree prune
# protect one worktree from pruning and removal
git worktree lock --reason "agent still running" ../fix-login
git worktree unlock ../fix-login
Prune only removes Git's records of worktrees whose folders are gone; it never deletes files. A worktree on a drive that isn't always mounted looks missing, so lock that one. Per the worktree docs, a lock also blocks move and remove, and removing a locked worktree takes --force twice.

The Review Desk's Worktrees tab: one Hermes worktree per project under ~/code, each with its hermes/ branch, task, age and disk size, plus free disk space.
All ten in one block, and where Hermes fits
Paste this once. Item 1 goes in each repository, and its --worktree lines in each task's worktree. The other nine are global.
git config --global merge.conflictStyle zdiff3
git config --global diff.algorithm histogram
git config --global rerere.enabled true
git config --global push.autoSetupRemote true
git config --global fetch.prune true
git config --global rebase.updateRefs true
git config --global branch.sort -committerdate
git config --global worktree.guessRemote true
git config --global gc.worktreePruneExpire 2.weeks.ago
# per repository
git config extensions.worktreeConfig true
In Hermes, ⌘N (Ctrl+Shift+N on Windows and Linux) starts each task on its own hermes/<name> branch in its own worktree, with the task as the agent's first prompt (README). Those branches and worktrees are plain git, so every setting above applies when you diff, rebase or merge them by hand, and git branch --list 'hermes/*' shows them newest first. On cleanup, since Hermes 2.2.9, a worktree that couldn't be removed when its session closed is retried at the next launch, and a worktree you chose to keep is no longer deleted later.

The ⌘N New task sheet: Claude Code, the orders-api project, a new hermes/ worktree, Accept edits, model and effort, and a preview of the command Hermes will run.
Hermes is free to download, source-available under BSL 1.1, and runs on macOS, Windows and Linux. It is not affiliated with Nous Research, Anthropic, OpenAI or any agent vendor. The source is on GitHub, and if a setting above behaves differently with Hermes worktrees than I describe, an issue there is the fastest way to tell me.
If this was useful
These ten settings are the git layer of shipping: every agent branch ends up as a pull request, a CI run and, eventually, a deploy. Ship It covers the rest of that road from localhost to production: hosting, deploys, payments, auth, CI/CD and monitoring, for a small team that has to run all of it.

Top comments (1)
Parallel worktrees with agents get messy fast—these settings are a lifesaver. We use similar configs with Arcwright and it keeps things sane.