Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Branches

Every conversation starts from a branch of your repository, its base branch, and builds on that branch's tip at the start of every turn. Your checkout is not where a conversation starts from: what you have checked out, staged, or left dirty is never read, and switching branches in your checkout changes no conversation.

The base branch question

The first time a conversation runs a turn, heph needs its base branch. If the project's config names one, that is it:

# .heph/config.toml
[git]
base_branch = "main"

It is written onto the conversation the first time it is used, so changing the config later does not move a conversation that has already started.

With no base_branch, heph asks, once per conversation, before the turn begins: a list of your local branches and then your remote-tracking ones (origin/main), with the branch you have checked out first and selected. Type to filter the list, Up and Down to choose, Enter to take it. Esc cancels the turn and puts your prompt back in the input. A conversation made with /fork or /new starts from the base branch of the one you made it from, so in the common case you are asked once per project.

heph exec has no one to ask: it needs [git] base_branch or --base BRANCH, and ends before any turn without them (heph exec).

A name is looked up as a local branch first and a remote-tracking branch second. If the base branch is deleted or renamed, the next turn stops and names it; choose another with /base.

/base

/base

shows the branch the conversation starts from, and the branch it publishes to if it has one yet.

/base release/2.4

starts the conversation from another branch. It works on a conversation that already has turns: the next turn replays the conversation's accepted work onto the new branch's tip, as it replays it onto new commits on the old one, and where the two changed the same lines the branch's text stands and the model is handed the displaced text to reapply. /base waits while a turn runs.

This also works after the conversation has published a branch. The new base wins until a successful /commit publishes the rebase to that same branch; turns never automatically republish. /base reports the pending rebase, which survives restarts and further turns. Only private changes relative to the recorded upstream are replayed: commits belonging solely to the old branch are not automatically copied. A different /branch cancels the override.

A conversation from before base branches asks the question at its next turn and then carries its work onto the branch you choose in the same way.

The conversation's branch

The first /commit names the branch from the work: two to four words from the title model, given what the commit changes, what you asked for, and your recent branch names for style, after [git] branch_prefix (heph/ unless you change it; Git). A name that is taken, by a local branch, a branch on any remote, or another conversation, gets -2, -3, and so on. The name is kept on the conversation and shown in the status bar as soon as it is generated, before gates and message drafting. A commit that a gate or a hook refuses keeps the same branch when you try again.

Set [git] branch_prefix = "team/" for names such as team/wrap-lines, or branch_prefix = "" for names such as wrap-lines. Put it in the user config for all projects, or the project config to override it for one project. Changing the setting does not rename a branch already chosen.

/branch

shows the branch, or that none is chosen yet.

/branch fix/pager-wrap

names it yourself. If your repository has that branch, the conversation adopts it: its tip is where the next turn starts, and the next /commit advances it. If not, it is the name the next /commit creates. /branch refuses the conversation's base branch and any remote's default branch (origin/HEAD): a conversation cannot be pointed at the branch it started from, or at the one a remote calls its default. That, and that heph writes no other branch and never pushes, is all the branch protection there is. /branch waits while a turn runs.

The status bar shows the branch after the conversation's name, main -> heph/wrap-lines, and /refs lists each conversation's branch, or (base main) for one that has not committed yet.

Working through pull requests

  1. Set the project's base branch once, in .heph/config.toml: [git] base_branch = "main", or "origin/main" to start from what the remote has.

  2. Prompt, review, and /commit. The conversation's branch now holds one commit per /commit, on top of the base.

  3. Push the branch and open the pull request yourself, from your checkout: git push -u origin heph/wrap-lines. You never need to check it out.

  4. Keep going in the same conversation. Review feedback becomes the next prompt; the next /commit adds a commit to the same branch.

What you do to the branch between turns is fine; the next turn takes it as it finds it:

  • Advanced (you committed on it, merged the base into it, or pressed the forge's update button): the new commits come in under the conversation's own work, and where they changed the same lines the model is handed its displaced text.

  • Rebased or amended: the conversation's own difference is replayed onto the rewritten tip; work already published is found already there and not proposed again.

  • Deleted after the pull request merged: the next turn starts from the base branch, which holds the work, with nothing private left, and says branch heph/wrap-lines is gone; the next /commit starts a new one.

What the model is told

The system prompt says where the conversation's work goes, from the conversation's own record and never from your checkout (What the Model Is Told). In the worktree, git log shows the base branch's history, and the branches tool lists your remote-tracking branches with the local ones.