> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jelou.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Branches

> Work on a branch without touching the project draft: publish immutable commits, choose which branch each channel runs, and promote your work to production when it is ready.

By default your local directory reads the project **draft**: the same rows
Studio edits, live and mutable. Branches let you work against a published
version instead, test it on a separate channel, and move the result to
production when it is ready — without anyone seeing work in progress.

A **branch** holds commits. A **commit** is an immutable snapshot of every
workflow in the project, and it is what a channel serves to your users.

<Note>
  This page assumes you already linked the directory with `jelou link` and pulled
  the workflows with `jelou pull`. If you have not, start at
  [Projects and channels](/en/guides/cli/project).
</Note>

## The two origins

Your directory reads from one place at a time, and `jelou status` says which on
its first line.

| Origin     | What it is                 | Who sees it                               |
| ---------- | -------------------------- | ----------------------------------------- |
| **Draft**  | The live rows Studio edits | Only published by `jelou project publish` |
| **Branch** | That branch's head commit  | The channels pointed at that branch       |

The draft is the default origin and it is what the rest of the CLI
documentation describes. Everything below is what changes once you work on a
branch.

## Moving between origins

```bash theme={null}
jelou checkout dev            # read branch dev
jelou checkout draft          # go back to the draft
jelou checkout -b new-branch  # create a branch from where you are
jelou branch list             # which branches exist, and which one you read
```

`jelou checkout <branch>` rewrites your files with what that branch serves. That
is why it refuses when you hold unpublished edits: push them first, or discard
them with `jelou pull --accept-server`.

`jelou checkout -b <name>` is the exception and touches no file. It creates the
branch from the commit you are reading and brings your work in progress along,
so it is how you say "what I have half-finished is going to be a branch".

<Note>
  `draft` is a reserved name, so that `jelou checkout draft` stays unambiguous.
  You cannot create a branch called that.
</Note>

## Publishing on a branch

While you are on a branch, `jelou push` changes meaning: instead of writing the
draft, it **publishes a commit** and moves the branch onto it.

```bash theme={null}
jelou push -m "orders menu"    # publish the changed files
jelou push --dry-run           # show what it would publish
```

Three things worth knowing:

* **The draft is never touched.** Nothing you publish on a branch shows up in
  Studio until you promote to the branch Studio reads.
* **Only what changed is sent.** Workflows and channels you did not touch keep
  the version the branch already served, so publishing one file still produces
  a complete commit.
* **The commit name is required.** Use it to know what a commit holds when you
  see it in the history.

<Warning>
  `jelou push` refuses if the branch moved since your last pull. Somebody else
  published in the meantime, and your commit would be built on work you have not
  seen. Run `jelou pull`, review, and try again.
</Warning>

### Conversations in flight

Publishing moves conversations that are halfway through onto the new version at
their next turn. If you would rather they finish on the version they started
with, publish with `--keep-pinned`.

```bash theme={null}
jelou push -m "hotfix" --keep-pinned
```

It applies only when publishing to `master`, because the setting belongs to the
whole project rather than to one branch.

## Moving work to another branch

```bash theme={null}
jelou promote master           # master serves the commit you are reading
jelou promote master -m "Release 12"
```

`jelou promote` makes another branch serve the commit you are on. The promotion
shows up in the destination branch's history with its own identifier, and your
directory does not change: you stay on your branch, at your commit.

<Note>
  The destination's commit gets a different identifier from the source. It is a
  copy, not one commit pointed at from two places, which is why it is recorded in
  both branches' history.
</Note>

It refuses when you hold local work the commit does not contain — you would be
promoting something other than what is on your screen. Publish first, or use
`--allow-dirty` if you really mean to promote what was published and leave your
edits where they are.

## Which branch each channel runs

This is independent of what your directory reads. A channel can be serving
`master` while you work on `dev`.

```bash theme={null}
jelou channels list --project 01H2XCEJQTG2H5V5NKCYW3J7Z2
jelou channels set-branch 01H2XCEJQTG2H5V5NKCYW3J7Z2 dev
```

The **Branch** column in the listing shows what each channel runs. Dim means it
was never set, so it follows `master`.

`set-branch` takes effect immediately for new conversations. It refuses if the
branch has nothing published yet.

<Tip>
  Point a test channel at your branch and leave the production ones on `master`.
  That way you test with real messages without any user seeing the change.
</Tip>

## A full cycle

<Steps>
  <Step title="Create the branch and edit">
    The branch comes off the commit you are reading and brings your work in
    progress along.

    ```bash theme={null}
    jelou checkout -b promo-christmas
    # edit workflows/*.json
    jelou workflow validate
    ```
  </Step>

  <Step title="Publish the first commit">
    ```bash theme={null}
    jelou push -m "christmas promotion"
    ```

    The draft is not touched: none of this shows up in Studio yet.
  </Step>

  <Step title="Test it on a channel">
    ```bash theme={null}
    jelou channels set-branch 01H2XCEJQTG2H5V5NKCYW3J7Z2 promo-christmas
    ```

    Message the channel and check the behaviour with real messages. Repeat the
    steps above until it works the way you want.
  </Step>

  <Step title="Promote to production">
    ```bash theme={null}
    jelou promote master -m "Christmas promo"
    ```

    `master` now serves the same commit you tested.
  </Step>

  <Step title="Put the test channel back">
    ```bash theme={null}
    jelou channels set-branch 01H2XCEJQTG2H5V5NKCYW3J7Z2 master
    ```

    It follows production again and is free for the next branch.
  </Step>
</Steps>

## A branch with nothing published

A new project starts with an empty `master`, and creating a branch from there is
perfectly valid. Your directory ends up on a branch with no commits — `jelou
status` calls it *nothing published yet* — and the first `jelou push` writes its
initial commit.

Reading an empty branch is not an error. Asking for a branch that does not exist
is a different thing, and that does fail.

## What needs the draft

These commands write the draft, so they refuse while you read a branch. Go back
with `jelou checkout draft` to use them.

| Command                        | Why                                                                                             |
| ------------------------------ | ----------------------------------------------------------------------------------------------- |
| `jelou project publish`        | Publishes the **draft**, not your files: it would replace what you just published on the branch |
| `jelou incoming accept-local`  | Dispatches your file against the draft                                                          |
| `jelou incoming accept-server` | Settles a conflict captured against the draft                                                   |
| `jelou status --check-remote`  | This flag only; plain `jelou status` works on both origins                                      |

After a `jelou push` on a branch there is nothing left to run: the commit exists
and the branch already points at it.

It works the other way round too: `jelou promote` needs a branch checkout,
because the draft has no commit to promote.

## TypeScript workflows

If you adopted a workflow to TypeScript with `jelou workflow adopt`, that file is
the source and the CLI never writes JSON over it, not even when you change
branches.

When the `.ts` differs from what the branch serves, `jelou pull` tells you and
`jelou status` marks it as modified. From there you decide:

* **Publish yours** — `jelou push`, which ships it as a new commit.
* **Take the branch's** — delete the `.ts` and run `jelou pull` again.
