Guide contents

Everyday Git

Strand is a complete daily-driver Git client alongside its review features. This page covers staging and committing in Local Changes, syncing with remotes, the sidebar's branch/tag/stash/remote/submodule sections, history operations like cherry-pick and interactive rebase, and conflict resolution.

Commit and amend run system Git’s hooks, including a configured core.hooksPath. A rejecting hook leaves your subject, body and amend selection in the checkout’s session draft. Drafts also survive view/repository switches. Failures show Git’s diagnostics; successful commits offer expandable Commit output. Output keeps the first and last 8 KiB of each stream when a hook is verbose.

Local Changes (Mod+2)#

Local Changes is a pure staging workspace: an Unstaged pane and a Staged pane (hierarchical file trees with status badges), a diff pane, and the commit form.

Right-click a single file in Local Changes or Review and choose Open in editor to open that exact working-tree path with the editor selected in Settings → Integrations. The same action is available in the sidebar Files tree and in each repository inside Workspace Review. Multi-file selections keep their batch actions and omit this single-file command.

The staging loop is fully keyboard-driven:

Key Action
j / k Next / previous file
n / p Next / previous change block
s Stage or unstage the selected file
d d Discard the selected file, folder descendants, or multi-selection (press twice to confirm)
c Jump to the commit subject field
Shift+J / Shift+K Scroll the diff pane
Mod+F Search within the diff

Inside Lines…, Tab moves through each changed-line checkbox and action, Space toggles the focused line, and Escape closes the picker. All and Clear make large blocks quick to adjust before Stage, Unstage, or Discard.

Working-tree files#

Switch the sidebar from Git to Files to browse tracked and untracked working-tree entries. Open the + menu beside search to create an empty file or folder at the repository root; New file… and New folder… are also searchable in Quick Launch. A file path may include existing parent folders. Existing entries are never overwritten, and Strand rejects paths that escape the checkout or enter .git.

Open a row's context menu with right-click, the Menu key, or Shift+F10:

The Files tree uses the repository's ignored-inclusive local listing directly; it does not first substitute the Git snapshot while that listing loads. Current Git state is overlaid on those local paths, so added, modified, and deleted entries keep their status colors. Ignored files and fully ignored folders are muted gray, do not create change dots on their parent folders, and stay out of Local Changes. Strand loads the local listing only after you open Files. It lists ignored folder boundaries immediately, then fetches one directory level when you expand a muted folder; generated trees such as node_modules therefore do not block the view or the normal status/snapshot path. An empty folder created in Strand appears in the tree immediately and remains visible for the session; Git itself cannot persist an empty directory across a restart until it contains a file. Successful creates, deletes, renames, and moves update the open Files tree without a reload or tab switch.

Committing#

The commit form takes a subject and an optional description body. The body grows with short or wrapped text, then scrolls once a long message reaches its bounded height so it does not crowd the diff. Mod+Enter in either field commits (the Commit button shows the same chip); plain Enter still inserts a newline in the description. An amend checkbox rewrites the previous commit instead.

Every commit and amend runs your real git commit, including applicable hooks, core.hooksPath, rejecting policies and message rewrites. Commit options, the chevron beside Commit, defaults to Use Git setting and shows whether Git will sign. Sign this commit and Do not sign this commit override that operation without changing config. Repository signing settings… opens the Signing tab of Repository settings. Signing uses your existing GPG/SSH agents; hook or signing failures retain the subject, description, amend and signing choices for retry, including when you leave this view and return during the session. Successful output is saved in Activity history…, available in Commit options and the repository context menu. Failures remain in the commit form.

AI commit message suggestions#

The sparkle button next to the subject field (or Mod+Shift+M, or the palette action "Suggest commit message") generates a commit message from your staged changes. If nothing is staged, it uses all unstaged changes instead, so it is available as soon as there is work to describe. Suggestions use your own subscription CLIs — the Codex CLI (ChatGPT) or the Claude Code CLI — with no Strand-side API key. Pick the provider and sign in under Settings → AI; see Settings for setup.

Generation is explicit and cancellable. Strand sends a bounded manifest plus the highest-signal patches. If conservative path or content checks flag potentially sensitive files, choose to exclude them, explicitly include them, or cancel; changed input requires a new confirmation. The generated subject and body remain directly editable. A non-authentication failure can be retried with the other provider without changing the default in Settings.

Fetch, pull, push#

The topbar Fetch / Pull / Push buttons show real ahead/behind counts. The adjacent chevron opens the full network menu: fetch with or without pruning stale remote-tracking branches; pull using Git's configured behavior, an explicit merge, rebase, or fast-forward-only, with or without autostash; and push the current branch, follow annotated tags, push every tag, or force-push with a lease. Fetch-prune, pull-strategy, and pull-autostash choices can each be saved as this repository's default. Network operations stream progress (phase and percent) into a live topbar toast, are cancellable, and surface git's own stderr in a toast on failure. Sync runs fetch, then the repository's default pull, then push, and stops at the first failed stage.

Force-push is deliberately guarded: Strand only exposes --force-with-lease, names the branch and upstream in a confirmation dialog, and refuses the update if the remote branch moved since the last fetch. Plain --force is not available. The same strategy actions are keyboard-reachable from the command palette; the current branch's context menu also exposes the pull and push variants.

The first push of a new local branch creates the same-named branch on origin and sets it as the upstream, so later Push and Pull actions work normally. A branch's context menu can also set, change, or remove its upstream, or push that branch to a chosen remote and destination without checking it out. The explicit push dialog can set the new destination as upstream and offers the same safe push strategies.

Shortcut Action
Mod+P Push
Mod+Shift+P Pull
Mod+Shift+Y Fetch
Mod+Shift+S Sync (fetch + pull + push)

Network operations shell out to your system git, so credential helpers, SSH keys and agents, and proxy settings just work — Strand never asks for credentials of its own.

Git LFS#

Right-click a repository tab or rail icon and choose Git LFS…, or search Git LFS: in the command palette. A single working file’s Files context menu also offers Git LFS → Track a pattern…, Lock this file…, and View locks for this file…. Tracking prefills the selected path; review wildcard patterns before running. Select an action, fill its fields, then use the action’s named button. Reads are explicit: opening the dialog does not start an object scan or contact the remote.

Whole-file staging (including Stage all), discard, hard reset and branch/revision checkout run the required LFS filters. Missing filters fail rather than stage raw assets. LFS files cannot be partially staged or discarded: use the whole-file action. Operations show bounded output/progress and Cancel operation. After an error, inspect status, correct the installation/configuration or remote access, and retry. There is no LFS history migration operation in Strand.

The sidebar Git tab#

The sidebar's Git tab holds collapsible Worktrees, Branches, Remotes, Tags, Stashes, Submodules sections, all filtered by the box at the top. Per-row actions live in right-click context menus (also keyboard-openable via the Menu key or Shift+F10); destructive items require a "Confirm" second click. Worktrees have their own page — see Worktrees.

Branches#

Branches render as a flat list with their full names visible. A green check over the branch icon means that branch's tip is already contained in the repository's primary branch, or a completed GitHub or Azure pull request into that primary branch used the same source branch name. The latter recognizes squash and rebase merges, which do not preserve Git ancestry and may not keep a usable source tip on the provider record. A branch that still has an open or active PR into the primary branch is never marked this way. The primary and checked-out branches are never marked. Strand resolves the primary branch from the remote's default branch, then falls back to local main, master, or the checked-out branch. The same check appears on the branch's commit-graph chip. Clicking a branch reveals its tip commit in the graph; double-click (or Enter) checks it out. Checkout, create-and-track from a remote branch, and tag/commit detach show a transient “Checking out …” progress pill (the same look as fetch/pull/push, without Cancel) until HEAD and the sidebar catch up; a failure still raises an error toast. The context menu offers: Checkout, Push to remote…, Set/Change upstream…, New branch from here…, New worktree from here…, Rename branch…, Merge into the current branch, Rebase the current branch onto this, Interactive rebase (on the current branch), and Delete branch. It can also copy the branch name, full ref, or tip SHA; the current branch adds pull and push strategy submenus.

Run Clear merged branches… from the command palette to remove several checked branches at once. Strand refreshes hosted pull requests before freezing the list; if the provider is unavailable, it clearly falls back to ancestry-only results. Every removable local branch starts selected. Provider-confirmed squash/rebase branches (completed PR into the primary branch by source name) are deleted with a tip guard that refuses if the branch moved after the dialog froze its plan. A matching upstream remote branch (or the same-named branch on origin when no upstream is configured) is shown separately and stays opt-in only when that remote tip is independently contained by the primary branch. Primary-branch refs are never offered. You can change either selection per row. Branches checked out in another worktree are listed as excluded and are never deleted. Remote deletion uses git push --delete; if it fails, Strand keeps the local branch as a recovery anchor and continues with the other selected refs.

The topbar branch dropdown also checks out local branches, tracks remote ones, and has an inline "Create branch…" field with prefix autocomplete. A detached HEAD shows a "detached" chip.

Remotes#

Each remote is a tree rooted at its name, showing all remote-tracking branches. Branch leaves can fetch only that branch, pull it into the current branch with a chosen strategy, set it as the current branch's upstream, checkout-or-track ("Create local branch & track"), create a worktree, delete the branch on the remote, and copy its short name, remote ref, or tip SHA. The remote folder menu can fetch, prune stale branches from only that remote, inspect its fetch/push refspecs, set Git's repository-local default remote, edit URLs, rename, copy URLs, or remove it. Adding or editing a remote accepts a required fetch URL and an optional push URL; remote URLs, refspecs, and remote.pushDefault stay in native Git configuration so command-line Git sees the same setup. Scoped prune, refspec inspection, and default selection are also searchable per remote in the command palette. The section’s Remote actions menu offers Add remote and Publish repository.

Tags#

Clicking a tag reveals the tagged commit in the graph; double-click (or Enter) checks it out (detached). Checkout shows the same transient progress pill as a branch switch. The menu offers Checkout, create a branch or worktree from the tag, Push to a remote, Delete on the remote (grayed out for tags the remote doesn't have), Verify tag signature, copy the tag name or target SHA, and Delete tag. The section + opens the tag dialog — adding a message creates an annotated tag. Tags can also be created from a commit's detail panel ("Tag…") and the palette ("Create tag…", "Push all tags").

The tag dialog’s Advanced options offers Use Git setting, Sign this tag, and Do not sign this tag. Inherited signing honors tag.gpgSign and tag.forceSignAnnotated. A signed tag requires an annotation; unsigned tags with no message are lightweight. A failed signing attempt keeps the form open with your draft and Git’s error. To inspect a signature, use the tag menu or the palette’s Verify tag signature…. The dialog verifies the selected tag object on demand and shows its immutable object ID, unsigned/valid/failed status, and Git’s verification output. Review that output for trust details; a valid signature alone does not establish that you trust the signer.

Stashes#

Single-clicking a stash switches to All Commits, reveals its graph node, and opens the stash diff without applying anything. Double-clicking it (or pressing Enter) applies it; Apply, Pop, and Drop show a transient progress pill while Git runs. The menu offers Inspect changes, Apply, Pop, Create branch from stash…, Drop, and copy actions for its stash@{n} reference or SHA. Branch-from-stash creates and checks out the branch at the stash base, applies the changes, and removes the stash only after a clean apply; the same action is searchable in the command palette. The section + opens the stash dialog: a message, a selectable file checklist for partial stashes, "Include untracked files", and "Keep changes in working directory" (which turns the stash into a snapshot). The topbar Stash split button opens the stash dialog, with a chevron menu for snapshot and untracked/keep-index variants plus "Pop latest". Stashes also appear inline on the commit graph as diamond nodes — see Commits & History.

Submodules#

Submodules list with status badges (uninitialized, out of date, modified). Double-click opens the module as its own repository tab. The menu offers Open, Update (or Init & update), Copy path, Inspect submodule…, and a Manage submenu for URL changes, synchronization, deinitialization and removal. The header’s Submodule actions menu offers Add, Update all and Manage, even when there are no submodules. Every management action is searchable as Submodules: in the command palette.

Choose an action and a module, then use the action’s named button:

Removal and deinitialization need a second confirmation. Dirty/untracked or ignored files, nested changes and checked-out commits that differ from the index block those actions. Updates also refuse dirty modules. Commit or stash the module's changes, and stage/commit the intended gitlink before retrying. Add/remove/URL changes refuse pending .gitmodules edits so they cannot stage or overwrite unrelated work.

The manager loads one level and up to 100 modules per page. Its list compares recorded and checked-out commits; Inspect working-tree status explicitly checks local and nested files. Inspect nested modules descends into an initialized module; Repository root returns to the original repository. Use Previous page / Next page for larger lists and Open repository to work in a module's own tab.

Progress and errors remain visible. Cancel operation stops Git and its helpers. Completed clones and local objects remain available: refresh, inspect the current state, correct the error and retry. Git's transport restrictions still apply, including restrictions on local-file submodule URLs.

Repository maintenance#

Run Repository maintenance… from the command palette to use Git's own housekeeping tools without leaving Strand:

Every run is cancellable. Strand records its exact safety-prefixed command, success or failure, duration, and captured Git output in a per-repository activity list outside the repository. The list survives relaunch, retains the latest 50 runs, and bounds unusually large transcripts so maintenance history cannot grow the app database indefinitely. Expand a row to inspect the command and output; a successful integrity check may still report ordinary dangling objects.

Cherry-pick, revert, merge#

Open Compare branches… from the command palette (⌘K / Ctrl+K) or the Branches → Branch actions menu to compare any two local or remote branches. It starts with the current branch in To and its upstream in From, falling back to main, then master, then the first other branch. With detached HEAD, it uses the first available pair. Neither branch needs to be checked out.

Local branches, remote branches, and tags also offer Compare … with this… in their sidebar menus. The comparison dialog lets you swap or change either ref, navigate the full file tree from both revisions with the arrow keys, and inspect text and image diffs without checking anything out. Changed files have status badges; selecting an unchanged file shows that it is identical.

If any of these operations hit conflicts, they pause rather than fail — see Paused operations and conflicts below.

Interactive rebase#

Strand drives interactive rebase entirely in-app — no $EDITOR ever pops up. Launch it from:

The rebase editor is a keyboard-operable list of the commits in the plan:

Key Action
/ Move the focused row
Alt+↑ / Alt+↓ Reorder the focused commit (disabled while preserving merges)
p / r / e / s / f / d Set the verb: Pick / Reword / Edit / Squash / Fixup / Drop
Backspace / Delete Drop
Escape Close the editor

Autosquash: the graph context menu's "Create fixup! commit" commits your staged changes as fixup! <subject> of the chosen commit. When you next open the rebase editor, fixup! commits are automatically arranged next to their targets (like git rebase --autosquash), with a notice telling you how many moved — and the plan stays fully editable before you run it.

Edit pauses the rebase immediately after the chosen commit. Strand opens Local Changes: change and stage files, enable Amend, commit the amendment, then use the operation banner's Continue button. You can also continue without amending.

When the range contains a merge, Preserve merge commits is enabled by default. Strand keeps Git's branch topology and disables reorder, squash/fixup, and dropping a merge commit while that mode is active. Turn it off explicitly if you intend to flatten the range into linear history.

Interactive rebase shells out to your system git, so hooks and commit signing apply to rewritten commits.

Paused operations and conflicts#

Whenever a merge, rebase, cherry-pick, or revert pauses, a banner appears above the main view with Continue and Abort. Conflicts disable Continue until they are resolved; an interactive-rebase Edit stop lets you amend the current commit first. "Abort " is also in the palette.

Conflicted files show in a conflict bar in Local Changes. Selecting one opens a landing panel that explains the conflict and offers whole-file resolutions — take incoming, take current, or take both — plus Open merge editor and External tool (which runs your configured git mergetool).

The merge editor is a full-screen three-way view:

Once every conflicted file is resolved, the banner's Continue button resumes the operation.

Patches, mailboxes and bundles#

Open Import / Export in the Repository menu or a repository’s context menu. Choose Apply patch or mailbox…, Import bundle…, or Export bundle…. Each command also appears separately in Quick Launch. Tab moves between controls; native selectors use arrow keys; Enter or Space activates buttons and Escape closes the dialog while idle.

For a patch, choose the file and an explicit target: Working tree only (unstaged), Stage changes only (without changing files), or Apply and stage changes. Preview and validate lists every affected old/new path and checks application before enabling Apply. A changed input or repository requires another preview. Paths outside the repository, Git administrative paths and symlink patches are rejected. Patch and mailbox input is limited to 32 MiB; mailbox series are limited to 1,000 patches.

Choose Mailbox for format-patch output. The preview includes authors, dates and subjects, and validates the series against a temporary index. Starting requires a clean repository and creates commits with the original author metadata. If direct application fails, Git tries a three-way merge. A paused mailbox is detected from Git’s own state, including one started in a terminal. Resolve and stage conflicts in Local Changes, reopen the dialog, then Continue mailbox. Skip patch discards the current patch changes; Abort mailbox restores the checkout before the mailbox. Both require a second click after explaining the discarded changes. Git errors remain visible.

For a bundle, Verify bundle shows advertised refs, prerequisite commits and Git’s validation output. Choose one advertised ref and a new local branch to import; existing branches and the current checkout are preserved. An incremental bundle cannot be imported until this repository has its prerequisites. Export bundle takes a full ref (such as refs/heads/main) and an optional prerequisite revision to exclude. It writes a new destination file and reports the exported refs/prerequisites; it never overwrites a file.

Where Strand uses your system git#

Strand reads repositories with its own fast engine, but the operations where your environment matters shell out to the real git binary and therefore honor your global and per-repo configuration:

If it works in your terminal, it works in Strand.

Git notes, replacements and tag editing#

Use Git note… on a commit’s context menu. Replacement refs… lives under Advanced in the Repository menu or repository context menu. A tag’s Edit tag submenu offers Change target commit… and Edit message…. Quick Launch also offers Git notes, Replacement refs, Change tag target and Edit tag message.

Git notes live in a selected refs/notes/… namespace and are separate from Strand's local Review notes. Inspect an object, edit its note, then Save. Removing a note requires confirmation. An external namespace change refuses Save and keeps your draft; use Load Git note to review the current note before retrying. Notes are shared by linked worktrees.

Replacement review shows the full original/replacement object IDs and types. Both types must match; cycles and excessive replacement chains are refused. Replacement-aware Git commands read the replacement; Strand's normal in-process graph and diff readers continue to show original objects.

Tag editing shows current and proposed commit IDs, subjects and changed-file count. Retarget preserves an unsigned tag's annotation or lightweight kind; re-annotation keeps its target. Check any configured remote explicitly to inspect whether its tag matches the local tag. Acknowledgement applies to the local edit only: other repositories' copies remain unchanged and no push is performed. Signed tags require a new signature and are refused by this editor. External tag changes require reviewing the targets again.

Git-flow workflows#

Open Branch actions → Git-flow… in the sidebar, or search Git-flow workflows in the command palette. The extension is optional: Check Git-flow installation checks the installed tool. Install Git-flow AVH separately if it is missing. Other Git-flow implementations are not supported by this dialog.

Choose two distinct existing production/develop branches, branch prefixes and an optional version-tag prefix, then Save and enable Git-flow. This opts the repository into Strand's workflow and saves the reviewed shared Git settings. Other Git-flow options are retained and can be inspected in the dialog. Save refuses an external configuration change until you reload it. Disable in Strand leaves Git-flow configuration and branches intact. Per-worktree or symlinked config files must be managed externally.

Choose Feature, Release or Hotfix and enter its exact name without the prefix. Existing names are suggested, including branches started from a terminal. Review start shows the base branch and commit; Review finish / resume shows source/destination commits, tag behavior and the arguments passed to Git. Workflow names use letters, digits, /, -, _ and .. Workflows with custom bases must be finished using the external tool.

Start and finish require a clean branch checkout. Feature finish merges into develop. Release/hotfix finish merges into production, creates an annotated version tag, then back-merges it into develop. The tag annotation is the reviewed Finish release NAME or Finish hotfix NAME; configured signing and Git/Git-flow hooks are honored. Finish retains local and remote workflow branches and explicitly disables fetching/pushing, squashing and feature rebasing for this operation. Publish or delete branches separately when ready.

Progress and failures appear in the Git output panel. If a merge conflicts, open Local Changes, resolve and stage the files, reopen Git-flow, then Review continue merge. After that merge completes, select the original workflow name and review Finish again to complete remaining stages. Git-flow skips stages it already completed. Review abort merge aborts only the currently active merge: prior successful production merges and tags remain. The review becomes stale when refs, configuration, checkout or merge state change externally; review again before executing.