Editor guide
The git workflow
Commit, branches, Merge/Push, Publish, and the three ways to undo: every git control in the Editor, and the distinctions that matter most.
The Editor writes your real source files as you work, so git is not an afterthought here: it is the mechanism that makes any of it safe to keep. Every git control lives in the top bar, plus one in the Activity panel of the right rail.
If you have not read branch mode, read that first: it explains the model this page is the button-by-button reference for.
The three ways to go back#
Editor gives you three different recovery mechanisms, and they have three different scopes. They do not stack, and one cannot undo another. Mixing them up is the most expensive mistake available in this tool.
| Mechanism | Where | What it restores | Scope |
|---|---|---|---|
| Undo / Redo | The floating toolbar, the arrow buttons | The previous state of the files one edit touched | Edits made in this running Editor |
| Undo on an Activity row | Activity panel, per entry (⋮ menu) | The bytes that one recorded edit replaced, written as a new change | One edit, survives quitting the CLI |
| Backup journal | .desde/backups/ on disk |
The bytes any single write replaced | Every write, recoverable by hand |
There used to be a fourth mechanism: a per-file Discard changes button on the Activity panel that reset a whole file to your last commit. It was removed when the panel was rebuilt around the edit ledger on 2026-08-19. To throw away a file's uncommitted changes now, use git directly:
git checkout HEAD -- <path>Warning That is not an undo of one step. It throws away everything uncommitted in that file, including work you did by hand in your own code editor, and there is no way back from the Editor. Commit before you reach for it.
Commit#
Commit sits in the top bar and shows a count of changed files: Commit (3). It is disabled when your working tree is clean, and the tooltip says so.
Clicking it opens a dialog with an optional message. Leave the message blank and it uses a default.
What runs is the equivalent of:
git add -A && git commiton the branch you have checked out. Two consequences:
-
git add -Astages your entire working tree, not only files the Editor touched. Anything you changed by hand in the same repo goes into the same commit. -
The commit runs with
--no-verify, so your repo's pre-commit hooks do not run. A failing hook would otherwise strand your edits behind an error you cannot act on from inside the Editor. If you rely on hooks for formatting or linting, run them yourself before pushing.
While edits are queued for the AI lane, the Commit button is replaced by Apply N with AI. Those edits have not reached your files yet, so committing first would leave them out. Flush the queue, then commit.
You can also commit from your own terminal at any time. The Editor just reads git status.
The Branch menu#
The branch segment of the breadcrumb opens a plain git branch switcher. It lists your local branches with the current one ticked and the default one labelled, then offers:
- New branch from
<default> - Duplicate current branch
- Rename current branch…
- Publish to
<default>…: hidden when you are already on the default branch
Switching and creating both refuse on a dirty tree, before git is invoked at all: "You have uncommitted changes on <branch>. Switching branches would carry them across. Commit them first (git commit -am "…") or discard them, then try again." This is deliberate. git checkout carries non-conflicting uncommitted changes across to the target branch, which would quietly smear one branch's work onto another. Branch mode never commits on your behalf, so it stops and asks you to commit or discard first.
Renaming does not touch the working tree, so it works with uncommitted changes present. Renaming the branch you are on is fine: HEAD follows.
Switching or creating a branch clears the undo stack. Those operations rewrite the working tree, so replaying an old step against it would apply the wrong bytes.
Merge / Push#
A dropdown in the top bar holding the "send this branch somewhere" actions. Every item disables itself when it cannot run, and its subtitle doubles as the reason: "No GitHub remote configured", "Nothing new to push", "You're on main".
Push branch. Commits anything pending first, then git push -u origin <branch> using your own git credentials. The Editor never handles authentication: it relies on your SSH key or credential helper, and shows git's failure text verbatim when that goes wrong.
Pull remote changes. Merges new commits from GitHub into your branch. With a dirty working tree, it asks first: your edits are committed onto the branch, then the merge runs. A conflict opens the conflict dialog described below rather than silently failing.
Update from <default>. The same thing, but merging the latest default branch into
yours instead of GitHub's copy of your own branch. Useful for picking up other people's
work before you publish.
Merge & push to <default>. Squash-merges your branch into the default branch locally, then pushes the default branch. If the merge lands but the push fails, you are told exactly that: the local default branch moved, GitHub did not.
Merge to local <default>. The same squash-merge, locally only. GitHub is untouched. This is the same operation as Publish in the Branch menu.
Open pull request opens a dialog with a title field and creates the pull request
through your own gh CLI. It is disabled in two cases, each named in its own subtitle:
you are on the default branch ("You are on <default>. Switch to another branch to open
a pull request."), or the repository has no origin remote ("This project has no
origin remote.").
You stay on your own branch after any of these.
Publish#
Publishing is the "make this the real version" step: your branch is folded into the default branch as a single commit.
What actually happens:
- If the branch being published is the one you have checked out and it has uncommitted changes, those are committed onto it first. Publishing is a save boundary too.
- A temporary git worktree is created under
.desde/, checked out on the default branch. A worktree is a second checkout of the same repository in another directory: your own checkout is not involved. - The squash-merge runs inside that temporary directory.
- The temporary worktree is removed, whether the merge succeeded or failed.
- Your branch is reset to match the newly published default branch. The content is identical (you just published it), and this stops your next publish from conflicting against your own earlier squash.
You stay on your branch throughout. The default branch simply moves forward.
When a publish conflicts#
A conflicting publish fails cleanly and changes nothing. The merge happened in the throwaway worktree, so there is no half-merged state to clean up: the temporary directory is torn down, the default branch stays where it was, and your branch keeps exactly the state it had a moment earlier.
The Editor names the specific files that conflicted, in a dialog rather than a bare
failure, and the Merge / Push dropdown offers Pull remote changes and Update from
<default> to bring your branch up to date before you publish again. What it does not
do is resolve the conflict for you: nothing auto-merges, and there is no editor for
conflict markers. You fix it in your own branch, with ordinary git:
git merge mainResolve the conflicts, commit, then publish again.
A publish can also stop with "Nothing to publish": the squash produced no changes, meaning your branch's content is already in the default branch.
A successful publish or merge-and-push clears the undo stack, for the same reason a branch switch does.
Undo and Redo#
Two arrows in the floating toolbar under the header. Their tooltips name the step they would apply: "Undo: prop: src/App.vue".
Each entry holds the before and after bytes of every file one edit touched. Undoing writes those bytes back through the same path a live edit uses: a backup is journalled first, per-file write locks are taken, and a multi-file step either fully applies or fully rolls back. It is not a git operation and leaves no trace in git history.
Limits worth knowing:
- The stack lives in the running CLI process. Quit the Editor and it is gone.
- At most 50 steps, and at most 20 MB of file content across the undo and redo stacks combined. Older steps fall off.
- It is cleared when you switch branches, create a branch, publish, or merge and push.
Before restoring anything, the Editor reads every file in the step and checks it still looks the way it expects. If you edited one of them in your own code editor in the meantime, the whole step refuses: never a partial undo.
When a step can never be applied again from the current state on disk, it would otherwise sit at the top of the stack blocking everything behind it. The error toast then offers Discard step, which drops just that entry without applying it.
Activity, and its own Undo#
The Activity tab in the right rail is one list, newest first, mixing two kinds of row: an edit the Editor itself made, and a dirty file no such entry claims (something you or another tool changed outside the Editor). There are no A/M/D/R git-status letters any more: each row's second line spells out the path, the change type and the commit state in plain words instead. Verification results for recent edits show inline on the row itself, not as a separate section above the list.
Each row has a ⋮ menu with two items: Undo and Copy path. There is no Discard here; see the three ways to go back above for why, and what to use instead.
This Undo is backed by the edit ledger, not the toolbar's in-process stack, so it survives quitting the CLI. It restores the bytes that edit replaced by writing them as a new change. It never rewrites history, and it never produces a revert commit.
It is offered only when Editor can still prove the file has not moved underneath it. A whole-file delete or rename is disabled up front with a reason, because undoing either can never be proven safe: the file's absence (or its new path) is exactly what that edit itself produced, not evidence of drift. If a previous attempt on a row was refused for a permanent reason (its backup was swept, or it never recorded one), that reason is remembered and the row stays disabled without asking the server again.
Habits that make this comfortable#
- Work on a branch, not on the default branch. Create one from the Branch menu before you start.
- Commit early and often. It costs nothing, and it is the only thing that survives quitting the CLI.
- Commit before switching branches: you will be told to anyway.
- If you keep a code editor open on the same repo, expect files to change under you. Reload rather than saving over the Editor's write.
Next#
- Branch mode: the model behind all of the above
- Chat: where agent writes come from
- What refuses and why