# Git and Files

The Git view shows the session's repository: its branches, its history as a graph, and its working
changes. The Files view lets you read and edit the session's files while its agent keeps working.
The **Git** and **Files** buttons at the window's right edge open each one over the board and the
transcript for the open session. The view's header names the session. The same button closes it,
and the other one switches to it. The view's X button closes it too, and so does Escape, except in
the editor. Files refreshes when the session's turn ends.

## Git

The session's repository at its folder, or its worktree where it has one, in three columns. `/diff`
opens it too. It follows the repository as it changes, so an agent's commit shows as it lands, and
it reads it all again when the window comes back to the front. Where it can't follow it, as past
Linux's limit of watched folders, it says so.

- The left column lists the local branches, in folders by their prefix (`feature/login` under
  `feature`), each with how far it's ahead of its upstream (↑) and behind it (↓), or "gone" where
  its upstream was deleted. Then come the remote branches, the worktrees, the stashes and the tags,
  each section with its count. Folders start closed, and a click on a section's name closes or
  opens it. **Filter** narrows every section at once. The session's own branch says "this session".
  The worktree the view opened on, the session's own where it has one, shows its name in bold, and
  each worktree names the sessions working in it.
- **Fold the list to icons** shrinks the left column to an icon for each section, with its count in
  the icon's tooltip. An icon opens the column again at its section.
- A click on a branch, a remote branch, a tag, a stash or a worktree shows its commit.
- Beside each branch and remote branch, while the pointer or the focus is on it: hide it in the
  graph, pin it to the left, or show it alone. Above the graph, a branch shown alone or pinned is
  named, and a click there shows every branch again or unpins it. If that branch is deleted, every
  branch shows again, and the view says so.
- The middle column is the history as a graph, its branches as lanes, each lane in its own
  colour, with each commit's branch, remote-branch and tag labels (the branch checked out first),
  its message, its author, its date and its short SHA. **Columns**, above it, shows or hides each of
  those four. The top row is the working changes, with how many files they touch. The history reads
  more as you scroll, so a large repository opens at once.
- The find box above the graph finds commits by their message, their author or their SHA, as
  **Find by** picks. Enter finds them and chooses the first; the arrows beside it go through the
  rest. It finds at most 100 commits, newest first, on the branches the graph shows. A message or
  an author is found as written, ignoring case, and a SHA needs at least 4 of its characters.
- The right column shows the commit chosen: its summary and description, its author with the date,
  its committer where the name, email or time isn't the author's, its co-authors, its SHA, its
  parents (a click shows a parent), whether it's signed and what git made of the signature (good,
  by a key git doesn't trust, bad, by an expired or a revoked key, or not checked here), and its
  files, by path or **As a tree**.
  **All files** lists every file in the commit, not just those it changed.
- Each person shows as a coloured circle with their initials, made on your computer. Nothing about
  them is sent anywhere.
- With the working changes' row chosen, the right column lists the files in conflict, then those
  unstaged and those staged. The + and − beside a file stage and unstage it, and **Stage all** and
  **Unstage all** do every file. The commit box below takes a summary and a description, with
  **Amend the last commit** to change the last commit instead, which fills an empty box with the
  last commit's message. **Commit** needs a summary and
  something staged; with **Amend the last commit** on, the button is **Amend** and needs only a
  summary. A merge, rebase, cherry-pick or revert that stopped partway says so; finish or
  abort it in the session's terminal.
- Each session keeps its Git view as it was left, across a switch to another session, while the
  window is open: the column folded or not, the filter, the folders opened, the columns, the find,
  the branches hidden, pinned or shown alone, the row chosen, and the commit box's draft.
- It needs git, and the session's folder must be a git repository; otherwise it says why.
- If a read fails once the view is open, it says why above the graph, with **Read again**.

### Fetch, pull and push

The button left of the find box does one of **Fetch all**, **Pull, fast-forward if possible**,
**Pull, fast-forward only**, **Pull, rebase** or **Push**, and the arrow beside it, **What the
button does**, picks which one and does it. A choice that can't run now, such as a pull with no
branch checked out, says why.

- Fetch all fetches every remote; if one can't be fetched, the others still are, and the view says
  what went wrong.
- Pull takes the branch's upstream: fast-forward if possible merges where the branches have gone
  different ways, fast-forward only refuses then, and rebase replays your commits on top.
- Push sends the branch to its upstream. A branch without one goes to the repository's only remote,
  or, with two or more, asks which in **Push to a remote**; that remote becomes its upstream. With
  no remote, the item can't run and says so.
- A push the remote rejects says why: the remote has commits the branch doesn't, or the branch is
  behind its remote (pull first, then push), or the remote declined it.
- A force push, from a branch's menu, replaces the remote branch only while it's still at the commit
  the view showed, so a teammate's push in the meantime is refused rather than lost.
- While the view is open, it fetches every 3 minutes.

Git never asks for a password or a key's passphrase here; it uses the sign-ins already set up on
this computer: your credential helper or keychain, Git Credential Manager, or your SSH agent. When
one is missing or refused, or a host isn't trusted yet, the view says so. Set it up in the session's
terminal, for example by running `git fetch` there once, then try again. When a host's key has
changed since this computer trusted it, which can mean someone is in the way, nothing is sent, and
the view says so. After such a failure, the timed fetches stop until the view is opened again. A
pull that stops at a conflict is finished or aborted in the session's terminal.

### Menus

A right-click on a branch, a remote branch, a tag, a commit, the working changes, a stash, a
worktree or a file opens its menu, as does the keyboard's menu key on whichever has the focus. A
commit's branch, remote-branch and tag labels in the graph open their own. An item that can't run
now says why beneath it.

- A branch: **Check out**; **Merge into**, **Rebase onto** and **Fast-forward to**, for the
  branch checked out; **Fast-forward to** its upstream where it's behind; the three pulls, on the
  branch checked out; **Push** and **Force push over** its upstream; **Create a branch here…** and
  **Create a tag here…**; **Make a worktree from** it; **Rename…**, **Set the upstream…** and
  **Delete**; **Copy the name** and **Copy a link**.
- A remote branch: **Fetch all**, as the button over the graph does; **Check out as** a local
  branch of the same name; merge, rebase or fast-forward the branch checked out; create a branch or
  a tag there; **Delete from** its remote; copy its name or a link.
- A tag: **Check out this commit**; create a branch there; **Delete the tag**, or **Delete the
  tag here and on** a remote; copy its name.
- A commit: **Check out this commit**; create a branch or a tag; **Make a worktree here…**;
  **Cherry-pick** and **Revert**; **Fast-forward to this commit**; reset the branch checked out
  here: **Reset here, keeping the changes staged**, **Reset here, keeping the changes unstaged** or
  **Reset here, discarding the changes**; on the commit checked out, **Edit the message…**;
  **Compare with the working changes**; **Copy the SHA**, **Copy a link** and **Copy the patch**.
- The working changes: **Stash the changes…**, **Apply a patch…**, **Stage all** and
  **Unstage all**. The first two are also buttons under the working changes' files.
- A stash: **Apply it**, **Apply it and drop it**, or **Drop it**.
- A worktree: **Open** each session working in it, **Start a session here…**, **Remove the
  worktree** or **Remove the worktree and** its branch, and **Copy the path**.
- A file, among a commit's files, the working changes or a comparison, or from the button beside
  its name over the graph: **Open in Files**, where it's inside the session's folders; **Open in the
  text editor**, never in the app for its kind, so nothing an agent wrote runs; **Show in the file
  manager**; **Show its history** and **Show its blame**; staging, unstaging, discarding or
  restoring it, as its side allows; for an untracked file, **Ignore the file**, every file with its
  extension, or its folder; **Delete the file**; **Copy the path** and **Copy the patch**. Moontors
  checks each path is inside the view's worktree before opening or showing it.

Some items ask first, in a dialog of their own: **Create a branch** (its name, and **Check it out**
or not), **Rename the branch**, **Set the upstream** (as remote/branch, with the remote branches
offered), **Create a tag** (a message makes it annotated), **Make a worktree** (a new branch, or
none for the commit on its own), **Edit the last commit's message** (what's staged stays out of it),
**Stash the changes** (with a message) and **Apply a patch** (pasted, and **Stage it too** or not).

Discarding, deleting a file, resetting, force pushing, deleting a remote branch, rebasing and
dropping a stash always ask in **Before it runs**, with what they lose: the commits no other branch
or tag holds, and the working changes to how many files. Deleting a branch or removing a worktree
asks when it would lose either, and restoring a file asks where it has changes of its own. So does
any action that would change the files of a folder where a turn is running. Deleting a tag, here or
on a remote too, asks where it alone holds commits, and so does a checkout, of a branch, a remote
branch or a commit, that leaves behind a detached HEAD whose commits no branch or tag holds. A copy
says it's done, and a link is built only for github.com, gitlab.com and bitbucket.org.

**Compare with the working changes** lists, at the right, the files that differ between the commit
and the working tree, under **Compared with the working changes**; a click opens a file's changes
from the commit to the working tree. **Back to the commit** ends it, as choosing another row does.

### Worktrees and sessions

A worktree in the left column with one session working in it names that session, and a click opens
it; one with several says how many, and a click lists them in its menu to open. The + beside a worktree, or **Start a session here…** in its menu, opens **Create session**
in its folder. Its menu also offers **Remove the worktree**, or **Remove the worktree and** its
branch, though never the main worktree or the one the view is open on; a worktree a session still
works in is refused, and the view says to archive or delete that session first.

### A file's changes

A click on a file, among a commit's files or in the working changes, opens its changes over the
graph. **Back to the history** shows the graph again. The buttons above it show:

- **Hunks**: git's own patch, hunk by hunk, each line numbered on the side it's on.
- **Inline** and **Split**: the file before and after in the editor's comparison, in one column or
  side by side, with the stretches that didn't change folded away.
- **File**: the whole file as it stands.
- **Blame**: each line with the commit that last changed it. A click on a commit chooses it in the
  history. Lines not yet committed say **Not committed yet**. Staged changes have no blame, as blame
  reads the working tree or a commit, not what's staged.
- **History**: the commits that changed the file, newest first, across renames. A click opens the
  file's changes in that commit.

Beside the hunks and the comparison, where they act:

- **Ignore whitespace**: in **Hunks**, changes in whitespace are left out; in **Inline** and
  **Split**, only whitespace at the start and end of lines is, as the editor compares them.
- **Wrap lines** wraps long lines, and **Previous change** and **Next change** go from one change to
  the next.

What the file can do:

- Each hunk acts on git's own: unstaged, **Stage hunk** or **Discard hunk**; staged, **Unstage
  hunk**; in a commit, **Revert into the working changes**. A hunk's buttons wait while whitespace
  is ignored, as git takes a hunk whole, and a hunk that changed since it was shown is refused
  rather than guessed at.
- The file itself: unstaged, **Stage file** or **Discard changes**; staged, **Unstage file**; in a
  commit, **Restore from this commit**, which puts it back as it was there, asking first where the
  file has changes of its own.
- Discarding asks first, in **Before it runs**, with what it loses, and so does an action that would
  change the files of a folder where a turn is running: **Go ahead** or **Cancel**.
- A file in conflict shows no hunks or actions: finish the merge or rebase, or abort it, in the
  session's terminal, and its changes show here once it's done.
- A binary file says so in place of its lines, and a very large change shows only its first lines,
  and says so.
- **Inline**, **Split**, **File** and **Blame** read the file's whole text, which opens only as UTF-8
  and at most 10 MB. **History** lists the newest 1,000 commits that changed the file.
- Each session keeps the file it had open and how it showed it, across a switch to another session.

### How actions run

- Each action is your own git, run as you'd run it, so your hooks and commit signing run too. When
  git refuses, its own message shows as it wrote it, in your language.
- A merge, rebase, cherry-pick or revert is refused while tracked files have changes: "Working
  changes would be overwritten. Commit or stash them first."
- A stash that moved since it was shown, as when another stash was made, is refused: "This changed
  since it was shown. Check it again, then try again."
- What an action loses is counted as it runs, after any action or fetch before it in the same
  repository, so the question is never about a state that has since changed.
- If another git is writing in the repository at that moment, as an agent's commit, the action tries
  once more, then says so. Moontors never deletes git's lock files.
- A stash takes the untracked files too, never the ignored ones. Dropping one counts the files it
  holds, its untracked ones included.
- Ignoring a file adds a line to the folder's `.gitignore`. A file git already tracks stays tracked
  until it's removed from the index. A `.gitignore` that's a link, or anything but a file, is left
  as it is, and Ignore says so.
- A worktree made here goes in Moontors' own folder, as a worktree session's does.
- A merge, rebase, cherry-pick or revert that stops partway, as on a conflict, is left for you or the
  agent to finish in the session's terminal. So are a stash's conflicts, where popping or applying it
  meets them; the stash is kept.

## Files

A file tree on the left, and an editor on the right with a tab per open file.

- The tree leaves out `.git` and the files git ignores; outside a git repository, hidden folders and
  `node_modules`. A folder lists at most 5,000 entries, then says "More files than are listed".
- The editor colours code like the transcript does.
- Files open from the session's folder (or its worktree) and any folder added with `/add-dir`,
  never from anywhere else.
- A tab shows when it has unsaved changes. Cmd+S (Ctrl+S on Windows and Linux) saves, writing the
  file in place and keeping its permissions. Cmd+W (Ctrl+W) closes the tab.
- Closing a tab with unsaved changes asks "Discard unsaved changes?": **Discard** or **Keep
  editing**.
- Files opens text in UTF-8 only. A binary file, a file larger than 10 MB, or text in another
  encoding opens as a note in its tab saying why, never as text that saving would damage.
- If the editor doesn't load, Files says "The editor didn't load." with **Try again**.

### The editor

The editor is the one Visual Studio Code is built on, with its own keys and its right-click menu:
cut, copy and paste, find and replace (Cmd+F, or Ctrl+F on Windows and Linux), folding, several
cursors at once, and moving and copying lines. Besides the Git view's eight (see
[Menus](#menus)), it's the only right-click menu in Moontors.

- A line longer than 10,000 characters is cut off on screen, and one longer than 50,000 isn't
  coloured. The file itself is kept whole.
- Each session keeps its open tabs, the active one and unsaved edits while the window is open,
  across a switch to another session. They aren't kept across a restart: closing the window with
  unsaved edits asks first.

### Editing beside the agent

- When the agent changes a file you have open with no unsaved changes, the tab reloads. Undo takes
  you back.
- When you have unsaved changes and the agent changes the file, your changes are kept, and the tab
  says the file changed on disk.
- Saving a file that changed on disk since you opened it asks first: **Reload**, **Overwrite**, or
  **Keep editing**.
- If the file is deleted while you have unsaved changes, the tab keeps them, and saving writes the
  file again.
- A file that mixes line endings says so: saving makes every line end the same way.
- Your hand edits aren't part of Claude Code's checkpoints, so a `/rewind` that restores files can
  overwrite them; its confirmation says so.
- Archiving a session with unsaved changes asks first. So does **Restart to update**, naming the
  unsaved files: **Restart and discard**, or **Keep working**.
- Closing the window or quitting with unsaved changes asks **Close with unsaved changes?**:
  **Save all** saves each file, then closes or quits; **Discard** drops the changes; **Cancel**
  keeps you editing. If a file can't be saved, it's named, and nothing closes. A message you've
  started typing to the agent holds a close too: the question names "the unsent message in" its
  session. **Save all** saves only the files and lets the message go; with no files to save, the
  question offers **Discard** and **Cancel**.