Raised: $10,026
83.5% of monthly goal Help us cross the finish line!
Goal: $12,000
Raised: $10,026 Goal: $12,000
83.5% of monthly goal Help us cross the finish line!
Sponsor DDEV

Using `git worktree` with TYPO3 (Video)

July 8, 2026 4 min read

Edit this page
Git, DDEV, and TYPO3 logos combined with a "git worktree" caption

People have increasingly been discovering git worktree for use in working on multiple features or bugs at the same time, or for having AI agents work in parallel. A DDEV contributor training covered this, and a Drupal Florida presentation.

TYPO3 projects sometimes provide a special challenge for git worktree if they have the full URL specified in config/sites/*/config.yaml’s base, like base: https://typo3.ddev.site/. When you add a second git worktree checkout, DDEV names that project after its directory, giving it a different *.ddev.site hostname—but TYPO3’s base is still trying to route the first worktree’s hostname, so the new one fails with a 404 “not found”.

This is the same underlying problem covered in Sharing Your TYPO3 Project with ddev share, but it can be fixed with a different post-start hook fix. (If your base is already a relative path like /camino, as in the DDEV TYPO3 quickstart, there’s nothing to fix—every worktree works out of the box.)

Watch the Video

What You’ll See

  • Removing name from project .ddev/config.yaml
  • Using ddev config global --omit-project-name-by-default
  • Setting up a second git worktree checkout of a TYPO3 project
  • Each project getting its own hostname from its directory name
  • The base URL mismatch breaking the second worktree
  • Fixing it with a post-start hook which checks out the original TYPO3 config.yaml

Why Worktrees Get Different Hostnames

By default, DDEV names a project after the directory it lives in. Remove the name: key from .ddev/config.yaml (or set this globally with ddev config global --omit-project-name-by-default) and every git worktree checkout gets its own project name and *.ddev.site hostname automatically, matching its directory.

That’s what you want for running several branches side by side, as covered in Contributor Training: git worktree for Multiple DDEV Projects—but it means a TYPO3 project with a hardcoded base containing a URL will only route correctly in whichever single worktree happens to match that hostname.

The Fix: post-start and post-stop Hooks

Unlike ddev share, where the tunnel URL is temporary and the pre-share/post-share hooks restore the original base afterward, a worktree’s hostname is permanent for the life of that checkout. So instead of a temporary swap, use a post-start hook that sets base to match whatever hostname the current worktree actually has, every time it starts, and optionally git restore on ddev stop:

# .ddev/config.yaml
hooks:
  post-start:
    - exec: |
        for f in config/sites/*/config.yaml; do
          cp "$f" "$f.post-start-backup"
          newbase=$(yq '.base' "$f" | sed -E 's#^https?://[^/]+##')
          [ -z "$newbase" ] && newbase="/"
          yq -i ".base = \"$newbase\"" "$f"
        done
        typo3 cache:flush
  post-stop:
    - exec-host: |
        git restore config/sites/*/config.yaml

The simplest answer is not to use the absolute base at all, just make it relative in the first place—base: / (or /your-path/ for a subpath)—which is hostname-independent and needs no hook. That works for git worktree, ddev share, and any other hostname change alike, as described in New ddev share Provider System.

Trusted Host Patterns

DDEV already automatically adds a trustedHostsPattern to additional.php for any hostname running under DDEV, so PHP’s own host validation isn’t a concern here—only TYPO3’s base setting is.

return [
    # ...
    'SYS' => [
        'trustedHostsPattern' => '.*.*',
        'devIPmask' => '*',
        'displayErrors' => 1,
    ],
];

Setting Up the Database and Files

Each worktree is a separate DDEV project, so it needs its own database and files. See Setting Up the Database and Files in the git worktree training post for exporting from one checkout and importing into another.

Example project: rfay/typo3demo

A pre-built example project based on the TYPO3 docs and DDEV quickstart is at rfay/typo3demo, with the post-start hook described here already in place.

Learn More

For background on git worktree with DDEV in general, see Contributor Training: git worktree for Multiple DDEV Projects. For more on TYPO3’s base URL and the ddev share version of this problem, see Sharing Your TYPO3 Project with ddev share and the docs on ddev share.

For another way to manage TYPO3 system routing check out the b13/host_variants extension, a more sophisticated way to manage what routes the TYPO3 router will accept and work with.

If you have questions, reach out in any of the support channels.

Follow our blog, Bluesky, LinkedIn, Mastodon, and join us on Discord. Sign up for the monthly newsletter.


This article was edited and refined with assistance from Claude Code.