---
title: "Building a worktree"
description: "The operations that make a worktree and what is inside it."
canonical: build.html
navigation-title: "Building"
---

<a id="build"></a>

- [add](#add)
- [fork](#fork)
- [provision](#provision)
- [config](#config)
- [php](#php)

<a id="building-a-worktree"></a>

# Building a worktree

The operations that make a worktree and what is inside it.

<a id="operations-add"></a>

<a id="add"></a>

## add

`ddev branchery worktree:add <branch>` · `POST /api/worktrees`

Checks out a branch that exists locally or on a remote, and builds it.

1. **Reading what the branch needs.** The branch's own `.ddev/branchery.yaml`
   is read out of the ref (`git show origin/<branch>:.ddev/branchery.yaml`),
   and the project's applies where the branch carries none. A PHP version the
   web image has no pool for, or a database name that another worktree uses or
   that holds tables, stops the operation here, before anything exists. A
   `composer.lock` that lacks a package its `composer.json` requires is
   said as a warning; the worktree is still made, because the checkout is where
   that is fixed. Whatever history stands under this name belongs to a worktree
   that was removed and is forgotten.

   The interface asks the same questions before the press: the dialog names
   the version the worktree will be served with and repeats the operation's
   own warnings.
2. **Checking out worktree.** `git worktree add .worktrees/<name> <branch>`
   for a branch that is already here,
   `git worktree add -b <branch> .worktrees/<name> origin/<branch>` for one
   that is not. An entry left behind by a worktree deleted by hand is pruned
   first, so its name can be used again.
3. **Reading how this is built.** The project's file, and the profile it
   names, decide the rest of the operation. What the worktree serves is written
   into its metadata, and the docroot link is made.
4. **Choosing the versions.** PHP is what step 1 read, or what the file the
   configuration points at says now; a version other than the project's gets
   an FPM pool and a `<Directory>` block of its own. Node is decided here
   and only here, from the configuration or from the checkout's own
   `.nvmrc`, `.node-version` or `package.json`; a version that is not in
   the cache is fetched once. [PHP and Node versions](configuration.md#php-and-node-versions) says how both are
   read.
5. **Installing dependencies** (**config**). The TYPO3 profiles remove the
   application's caches before anything else: its compiled container is kept
   for the installed packages and not for the code, so a worktree rebuilt on
   other code would otherwise run on the container of the old one.
6. **Writing the configuration** (**config**), together with the worktree's
   `.vscode/launch.json` and `.vscode/settings.json`.
7. **Preparing the database.** `branchery_<name>` is created on the project's
   server. With `data.from: source` the project checkout's data is copied
   into it, the files `data.needs` names come with it, and the addresses in
   the files `data.addresses` names are pointed at this worktree. Then
   **migrate** (**config**) fits the schema to the checked-out code.

   Where the project says nothing about its data, or the source holds no
   tables, the database stays empty and **setup** (**config**) installs the
   application. Where the copied data cannot be fitted to the code, the copy
   is dropped and the application installed instead, and the log says so. The
   source database is never written to. [Databases and data](../use-branchery/databases.md) follows all three
   paths.
8. **Finishing up.** **finish** (**config**) runs -- where a cache flush
   stands -- and the `ddev describe` block is rewritten. Every page under
   `entrypoints` is then asked of the web server, redirects followed; one that
   answers an error, or nothing, ends the operation in `⚠` with the status,
   so a backend that cannot be reached is said here and not found in the
   browser.

A branch that is already in the repository is checked out as it stands and is
never moved onto its remote; one that is behind stays behind, and the list says
so. [Branch safety](../architecture/safety.md#architecture-branch-safety) is the rule.

<a id="operations-fork"></a>

<a id="fork"></a>

## fork

`ddev branchery worktree:fork <branch> [--from=<worktree>] [--base=<ref>]` ·
`POST /api/worktrees` with `mode: fork`

Creates a branch that does not exist yet, from the project checkout or from
another worktree, and builds it. `--base` cuts it at another commit -- a
review of `origin/main` while the project checkout stands on a feature --
and everything else still comes from the source: its unversioned files and its
data.

1. **Reading what the branch needs**, as for `add`, out of the commit the
   branch starts from. The lock file checked is the one the fork installs
   from: the committed one, or, in a project that keeps `composer.lock` out
   of git, the source checkout's working copy.
2. **Creating branch.**
   `git worktree add -b <branch> .worktrees/<name> <commit>`, where the
   commit is the one `--base` names, or `HEAD` of the source worktree or of
   the project checkout. It is cut at the commit and not at the name, so a base
   on a remote does not become the new branch's upstream. Which branch and
   commit that was is written into the worktree's metadata and shown on its
   page, because git keeps no such thing. A base that names no commit stops the
   operation before anything exists.
3. **Carrying over unversioned files.** Everything git ignores in the source is
   copied over — `vendor/`, generated files, configuration, uploads --
   except what a run leaves behind: `var`, `typo3temp`, `.vscode`,
   `.idea`, and always `.git`, `.ddev` and the worktrees themselves. The
   log says how many entries travelled; `-v` names each. A project changes
   the list under `copy`; see [Copied files](copied-files.md#copied-files).
4. **Building the worktree.** The build phases of `add`: reading how this
   is built, choosing the versions, installing dependencies, writing the
   configuration.
5. **Preparing the database.** `branchery_<name>` is created and the
   source's data is copied into it — the project checkout's, or that of the
   worktree this was branched off. The rest is `add`'s database step.
6. **Finishing up.**

<a id="operations-provision"></a>

<a id="provision"></a>

## provision

`ddev branchery worktree:provision <name> [--fresh]` ·
`POST /api/worktrees/<name>/provision`

Builds again everything inside a worktree that stays as it is. It is the way
on from a build that stopped and from a worktree whose dependencies changed
since it was built.

1. **Reading how this is built**, from the `.ddev/branchery.yaml` in the
   checkout. A PHP version an earlier build assigned and the configuration no
   longer asks for is let go of, and the log says so.
2. **Choosing the versions**, **installing dependencies** and **writing the
   configuration**, as in `add`.
3. **Preparing the database.** The database is created if it is missing.
   Where it already holds tables, **migrate** brings the schema up to the
   code and nothing is installed over the data; where it is empty, **setup**
   installs the application. With `--fresh` it is dropped first, so the
   worktree ends up as it would have been created today.
   [Keep the database or start fresh](../use-branchery/databases.md#databases-fresh) is the choice.
4. **Finishing up.**

A worktree that is to take the project's data again is what
[sync](sync-and-remove.md#operations-sync) is for.

<a id="operations-config"></a>

<a id="config"></a>

## config

`ddev branchery worktree:config [<name>]`

Writes the generated configuration again without rebuilding dependencies or
replacing data: the project's `configure` moment, the docroot link, the site
addresses and the editor files, then the `finish` moment and the
`ddev describe` section. Without a name it refreshes every
worktree. Use it after a change to the configuration that needs neither
dependencies nor a migration; provision the worktree when its build inputs
changed.

<a id="operations-php"></a>

<a id="php"></a>

## php

`ddev branchery worktree:php <name> [<version>]`

Shows the assigned version, or changes it: the new version's PHP-FPM pool is
assigned, the web-server configuration updated and `finish` run. A
version below the requirement Composer recorded is refused, because every
request would fail. [PHP and Node versions](configuration.md#php-and-node-versions) says how a branch chooses its
version to begin with.
