Getting Started

Installation

Requirements

  • Git 2.28 or later
  • A terminal with UTF-8 support (virtually all modern terminals qualify)
  • macOS, Linux, or Windows

One-line install

macOS / Linux

curl -fsSL https://raw.githubusercontent.com/AgusRdz/bonsai/main/install.sh | sh

The script downloads the latest release binary for your platform and places it in ~/.local/bin (or /usr/local/bin if that is writable). It adds the directory to your $PATH if needed.

Windows (PowerShell)

irm https://raw.githubusercontent.com/AgusRdz/bonsai/main/install.ps1 | iex

Manual install

  1. Download the binary for your platform from the releases page.
  2. Make it executable: chmod +x bonsai
  3. Move it somewhere on your $PATH: mv bonsai ~/.local/bin/

Build from source

Requires Go 1.21 or later.

git clone https://github.com/AgusRdz/bonsai.git
cd bonsai
go build -ldflags="-s -w" -o bonsai .
mv bonsai ~/.local/bin/

Update

bonsai update

Checks GitHub releases and replaces the current binary in-place.

Uninstall

bonsai uninstall

Removes the binary. You can also delete the global config manually:

rm -rf ~/.config/bonsai/

First run

The first time you run bonsai inside a repo it will automatically open the setup wizard if no global config exists. You can also run it explicitly at any time:

bonsai setup

Getting Started

TUI Guide

Opening bonsai

cd your-repo
bonsai

bonsai must be run from inside a Git repository. If no global config exists it opens the setup wizard first.

Layout

 main  ↑2  [trunk]  [mode:standard]        ← header

  Conflicts (1)
  !  src/auth.go          both modified     ← conflict section (shown first)

  Staged (2)
  M  src/api.go                             ← staged section
  A  src/middleware.go

  Changed (1)
  M  README.md                              ← changed section

  Untracked (1)
  ?  scratch.txt                            ← untracked section

  $ git commit -m "fix: auth token refresh"
  [space] stage/unstage  [c] commit  ...    ← command bar

The header shows your current branch, how many commits you are ahead/behind the remote, the active workflow flow, and the current mode.

The file list is divided into four sections in fixed order: conflicts (if any), staged, changed, untracked. Navigate with / or j/k.

The command bar at the bottom shows the most common keys. Press ? for the full reference.

KeyAction
/ kMove selection up
/ jMove selection down
escClose current panel / go back
q / ctrl+cQuit

File operations

KeyAction
spaceStage a changed/untracked file; unstage a staged file
+Stage all changes at once (git add .)
hOpen the hunk stage panel
dView diff for the selected file
HOpen file history
eOpen blame view
xDiscard all working tree changes to the selected file (confirm required)
oRestore the selected file to HEAD or a specific ref

Hunk staging

Press h on any changed file to open the hunk panel. Each hunk shows its @@ ... @@ header and a short preview. All hunks are selected by default - deselect the ones you want to leave out, then press enter to apply.

KeyAction
/Move between hunks
spaceToggle selected / deselected
aSelect all hunks
enterApply selected hunks
escCancel

File history

Press H on any file to see every commit that touched it. Press enter on a commit to open its full detail view.

Branch graph

Press g to open the branch graph (git log --graph --all). Use / to scroll, esc to close.

Committing

Press c to open the commit panel. Type your message and press enter to commit. Press esc to cancel.

In guided mode the education panel appears after the commit and explains what happened in plain language along with the exact command that ran.

Pushing and pulling

Press p to open the push menu. Choose between:

OptionCommandWhen to use
Pushgit pushNormal push
Force with leasegit push --force-with-leaseAfter a rebase; fails safely if the remote has new commits
Set upstreamgit push --set-upstream origin <branch>First push of a new branch

Press P to pull, f to open the fetch menu (origin / all / prune).

Branches

KeyAction
bCreate a new branch (or open the flow picker in gitflow mode)
BList all branches - switch, merge, rebase, delete, rename, delete remote

Log

Press l to open the commit log.

KeyAction
/Scroll
enterOpen commit detail
/Open search / filter input
ctrl+/ or ctrl+rClear active filter
mLoad more commits
escBack (first esc clears any active filter)

From commit detail, press d to view the full diff, p to cherry-pick, or y to copy the hash.

Stash

KeyAction
sStash all current changes (opens a message input to name the stash)
SOpen stash list - pop, apply, or drop an entry

Advanced operations

Reset

Press z to open the reset menu. Choose between soft (keep staged), mixed (keep unstaged), or hard (discard all changes).

Tags

Press t to list tags. From the tag list you can create a new tag at HEAD, delete one, or push a tag to origin.

Blame

Select a file and press e to open the blame view. Each line is annotated with the commit hash, author, and date.

Bisect

Press i to open the bisect panel. Mark commits as good or bad to find the commit that introduced a bug.

Interactive rebase

Press R to open the interactive rebase panel. Enter a base ref (e.g. HEAD~5 or a commit hash), then reorder and relabel commits (pick, reword, squash, fixup, drop).

Amend

Press A to open the amend panel. You can change the commit message, author, date, or use --no-edit to amend without changing the message.

Only amend commits that have not been pushed to a shared remote.

Undo

Press U to undo the last commit, merge, or rebase.

Worktrees

Press W to list linked worktrees. You can add a new worktree (checked out to a different branch) or remove an existing one.

Remotes

Press O to open remote management. From there you can list all configured remotes, add a new one, remove, or rename an existing one.

Submodules

Press M to open the submodule panel. You can list all submodules, add a new one, run update --init, or deinit a submodule.

Git notes

Press n to view the note attached to the HEAD commit. You can edit the note inline or delete it.

Reflog

Press L to open the reflog. Scroll through all HEAD movements, copy a hash with y, or reset to an entry with r.

Clean

Press X to preview untracked files that would be removed by git clean -fd. A confirmation is required before anything is deleted.

Conflicts

When merge conflicts exist they appear at the top of the file list marked with !. Select a conflicted file and press d to open the conflict viewer.

KeyAction
oAccept ours (discard their changes)
tAccept theirs (discard our changes)
bAccept base (common ancestor)
rRemove conflict markers, keep both sides
eManual edit mode

Press a from the main panel to abort an in-progress merge, rebase, or cherry-pick.

Configuration manager

Press C to open the configuration manager:

  • Global config - view and edit ~/.gitconfig
  • Local config - view and edit .git/config
  • Global gitignore - view and edit the global ignore file
  • Local .gitignore - view and edit the project ignore file
  • Recommendations - best-practice settings with one-key apply
  • Profiles (includeIf) - manage conditional config includes

Education panel

After every action bonsai briefly shows a feedback panel:

  • standard mode: shows the command that ran (e.g. git commit -m "...")
  • guided mode: shows the command plus a plain-language explanation and contextual tips
  • pro mode: no panel (except for complex operations like rebase or bisect)

Press any key to dismiss the panel immediately. The duration is configurable:

[education]
panel_duration = 4   # seconds; 0 disables it entirely

Usage tracking and mastery

bonsai tracks how many times you run each command. When you reach the mastery threshold for a command, it asks whether you want to keep seeing the education panel for it or suppress it.

CommandThreshold
add, commit20 uses
push, pull15 uses
branch, checkout12 uses
stash, merge10 uses
rebase, cherry-pick8 uses
reset, restore6 uses
bisect, worktree, notes5 uses

You can re-enable suppressed panels at any time from the Education & Usage section of the configuration manager (C).


Commands

CLI Commands

All commands that do not open the TUI accept no positional arguments other than subcommands. Options use --flag syntax.

bonsai (no args)

Opens the interactive TUI. Runs the setup wizard on first launch.

bonsai

bonsai clone

Clones a remote repository and opens bonsai in the resulting directory.

bonsai clone <url> [<directory>]
# Clone into a directory named after the repo
bonsai clone https://github.com/example/repo.git

# Clone into a custom directory
bonsai clone https://github.com/example/repo.git my-project

bonsai setup

Interactive wizard that walks you through flow, branch prefixes, mode, and validation. Writes to the global config.

bonsai setup
bonsai setup --local   # per-project overrides

bonsai init

Creates a commented .bonsai.toml template in the current directory without running the wizard. Does not overwrite an existing file.

bonsai init

bonsai config

Opens the global config in your editor.

bonsai config
bonsai config --local   # open per-project config
bonsai config --path    # print the path to the global config file

bonsai doctor

Checks global and local Git configuration health. See the Doctor page for details.

bonsai doctor
bonsai doctor --verbose

bonsai stats

Prints repository statistics. Must be run inside a Git repo.

bonsai stats

Output includes commit count, date range, recent activity, branch and tag counts, top contributors, file type breakdown, and most-changed files.

bonsai patch

Wraps git format-patch and git am.

patch –create

bonsai patch --create --base=<ref> [--output=<dir>]
FlagDescription
--base=<ref>Required. Create patches for commits since this ref
--output=<dir>Directory to write .patch files into. Defaults to the current directory
bonsai patch --create --base=HEAD~3
bonsai patch --create --base=main --output=patches/

patch –apply

bonsai patch --apply <file> [<file>...]
bonsai patch --apply patches/0001-fix-auth.patch
bonsai patch --apply patches/*.patch

If conflicts occur, resolve them manually and run git am --continue, or git am --abort to cancel.

bonsai archive

Exports the repository at a given ref as a compressed archive.

bonsai archive [--format=<fmt>] [--output=<file>] [--ref=<ref>]
FlagDefaultDescription
--formattar.gztar.gz or zip
--outputarchive.<format>Destination file path
--refHEADGit ref to archive
bonsai archive
bonsai archive --format=zip --ref=v1.2.0 --output=release-v1.2.0.zip

bonsai bundle

Wraps git bundle for offline repository transfer.

bonsai bundle --create <file>   # bundle all branches
bonsai bundle --verify <file>   # verify a bundle file
bonsai bundle --create repo.bundle
bonsai bundle --verify repo.bundle

bonsai ssh

Manage SSH keys and check connectivity.

bonsai ssh --status    # SSH key, agent status, connectivity to the repo's remote
bonsai ssh --keygen    # generate ~/.ssh/id_ed25519
bonsai ssh --show      # print your public key

bonsai ssh --status detects the remote host from the current repo’s remotes and tests SSH auth against it. Works with GitHub, GitLab, Bitbucket, Gitea/Forgejo, and Azure DevOps.

Press ` inside the TUI to open the SSH key manager panel.

bonsai lfs

Manage Git LFS tracked files and objects.

bonsai lfs --status              # show pending LFS objects
bonsai lfs --track <pattern>     # track a file pattern (e.g. *.psd, *.zip)
bonsai lfs --untrack <pattern>   # stop tracking a pattern
bonsai lfs --pull                # download all LFS objects for the current checkout
bonsai lfs --install             # install LFS hooks into this repository

bonsai standup

Shows your recent commits, defaulting to today.

bonsai standup
bonsai standup --days 3
bonsai standup -w               # last 7 days
bonsai standup -a "Jane Doe"    # filter by author name
FlagDescription
--days NShow commits from the last N days (default: 1)
-wShorthand for --days 7
-a <name>Filter by author name (defaults to user.name from git config)

bonsai repo

Create and open remote repositories.

bonsai repo --create <name> [--private]   # create a new remote repo (GitHub / GitLab)
bonsai repo --open                        # open the current repo in the browser
bonsai repo --create my-new-repo
bonsai repo --create my-new-repo --private
bonsai repo --open

bonsai update

Updates bonsai to the latest release by downloading the new binary in-place.

bonsai update

bonsai uninstall

Removes the bonsai binary from the system. Prompts for confirmation.

bonsai uninstall

bonsai changelog

Prints the full changelog to stdout.

bonsai changelog
bonsai changelog | less

bonsai version

Prints the current version.

bonsai version
# bonsai v0.29.0

Commands

Keybindings

Open bonsai and press ? for the full in-app reference. Key highlights by panel:

Main panel

File navigation

KeyAction
/ kMove selection up
/ jMove selection down

File operations

KeyAction
spaceStage an unstaged file / unstage a staged file
+Stage all changes at once (git add .)
hStage / unstage individual hunks within a file
HView commit history for the selected file
dView diff for the selected file
eBlame - who last changed each line
xDiscard working tree changes (confirm required)
oRestore file to HEAD or a specific ref

Sync

KeyAction
cOpen commit panel
pOpen push menu (push / force-with-lease / set-upstream)
PPull from remote
fFetch menu
gOpen branch graph (git log --graph --all)

Stash

KeyAction
sStash all changes (opens message input)
SOpen stash list

Branches

KeyAction
bCreate a new branch (or flow picker in gitflow mode)
BList all branches

History

KeyAction
lOpen commit log
LOpen reflog

Advanced operations

KeyAction
zReset menu (soft / mixed / hard)
tTag list
iBisect panel
RInteractive rebase
AAmend HEAD
UUndo last commit / merge / rebase
WWorktree list
ORemote management
MSubmodule management
nNotes for HEAD commit
XClean untracked files
aAbort in-progress merge / rebase / cherry-pick

Configuration and tools

KeyAction
CConfiguration manager
`SSH key manager
VLFS panel
DMulti-repo dashboard

Meta

KeyAction
?Help panel
q / ctrl+cQuit

Log panel

KeyAction
/ kScroll up
/ jScroll down
enterOpen commit detail
/Open search / filter input
ctrl+/ or ctrl+rClear active filter
mLoad more commits
escBack (first esc clears any active filter)

Commit detail panel

KeyAction
/ Scroll
dView full diff of this commit
yCopy commit hash to clipboard
pCherry-pick onto current branch
escBack

File history panel

KeyAction
/ Scroll
enterView commit detail
escBack

Branch graph panel

KeyAction
/ Scroll
escBack

Branch list panel

KeyAction
/ Scroll
enterSwitch to the selected branch
mMerge selected branch into current (confirm required)
rRebase current onto selected branch (confirm required)
dDelete the selected branch (confirm required)
nRename the selected branch
DDelete the remote tracking branch (confirm required)
escBack

Stash list panel

KeyAction
/ Scroll
enterPop the selected stash
aApply without removing
dDrop the selected stash
escBack

Conflict panel

KeyAction
/ Move between conflict hunks
oAccept ours
tAccept theirs
bAccept base (common ancestor)
rRemove conflict markers (keep both sides)
eManual edit mode
escBack

PR / MR panel

KeyAction
/ Scroll
enterOpen PR in browser
dView full diff
aApprove
ARequest changes (with reason)
cPost a general comment
nCreate a new PR for the current branch
escBack

Tag list panel

KeyAction
/ Scroll
nCreate a new tag at HEAD
dDelete the selected tag
pPush the selected tag to origin (confirm required)
escBack

Worktree list panel

KeyAction
/ Scroll
aAdd a new worktree
dRemove the selected worktree
escBack

Remote list panel

KeyAction
/ Scroll
aAdd a new remote
dRemove the selected remote
rRename the selected remote
escBack

Submodule list panel

KeyAction
/ Scroll
aAdd a new submodule
uUpdate –init all submodules
dDeinit the selected submodule
escBack

Reflog panel

KeyAction
/ Scroll
rReset HEAD to the selected entry
yCopy hash to clipboard
escBack

Interactive rebase panel

Step 1: enter a base ref (e.g. HEAD~3) and press enter to load commits. Step 2: edit the todo list, then press enter to execute.

KeyAction
/ kMove cursor up
/ jMove cursor down
KMove selected commit up (reorder)
JMove selected commit down (reorder)
ppick
rreword
eedit
ssquash
ffixup
ddrop
enterExecute rebase
escCancel

Hunk stage panel

KeyAction
/ Move selection
spaceToggle hunk selected / deselected
aSelect all / deselect all
enterApply selected hunks
escBack

Push menu

KeyAction
/ Move selection
enterExecute selected push option
escBack

SSH panel (`)

KeyAction
/ Scroll
tTest SSH connection for selected key
escBack

LFS panel (V)

KeyAction
/ Scroll
tTrack a new file pattern
uUntrack selected pattern
pPull LFS objects
PPush LFS objects
escBack

Multi-repo dashboard (D)

KeyAction
/ Scroll
enterOpen selected repo in bonsai
escBack

Bisect panel

KeyAction
sStart bisect
bMark current as bad
gMark current as good
rReset bisect
escBack

Diff panel

KeyAction
/ kScroll up
/ jScroll down
eBlame for the file being diffed
escBack

Remappable keys

The following keys can be changed in [keybindings] in your config:

DefaultConfig key
ccommit
ppush
lpull
sstash
zundo
qquit
bbranch
ggraph

All other keys are fixed.

[keybindings]
graph  = "g"
commit = "c"
branch = "b"
push   = "p"
pull   = "l"
stash  = "s"
undo   = "z"
quit   = "q"

Configuration

Configuration

Config file locations

ScopePath
Global~/.config/bonsai/config.toml
Per-project.bonsai.toml in the repo root

The per-project file inherits every value from global and overrides only what it defines. On Windows the global config is at %APPDATA%\bonsai\config.toml.

Quick setup

bonsai setup           # global wizard
bonsai setup --local   # per-project wizard (inside a repo)

To create a commented template without the wizard:

bonsai init   # creates .bonsai.toml in the current directory

To open the config in your editor:

bonsai config          # global
bonsai config --local  # per-project
bonsai config --path   # print the path to the global file

Full config reference

[modes]
default = "standard"   # standard | guided | pro

[flow]
type = "auto"          # auto | trunk | gitflow | githubflow | forking

[conventions.branches.feature]
prefix  = "feat/"
pattern = "feat/{ticket-id}-{description}"
example = "feat/PROJ-123-login-oauth"

[conventions.branches.bugfix]
prefix  = "fix/"
pattern = "fix/{ticket-id}-{description}"
example = "fix/PROJ-456-crash-on-login"

[conventions.branches.release]
prefix = "release/"

[conventions.branches.hotfix]
prefix = "hotfix/"

[conventions.validation]
mode = "strict"   # strict | warn | off

[education]
panel_duration = 4   # seconds; 0 disables the feedback panel

[editor]
command = ""   # e.g. "vim", "nano", "code --wait", "hx"

[keybindings]
graph  = "g"
commit = "c"
branch = "b"
push   = "p"
pull   = "l"
stash  = "s"
undo   = "z"
quit   = "q"

[metrics]
enabled = false

  [metrics.track]
  errors      = true
  conventions = true
  commits     = false
  habits      = false

Modes

ModeBehavior
standardShows the command that ran after each action - default
guidedFull explanation after every action, contextual tips
proNo feedback panel - clean interface

Per-project example

A minimal .bonsai.toml that switches to guided mode and enforces stricter branch names:

[modes]
default = "guided"

[conventions.branches.feature]
prefix  = "feature/"
example = "feature/auth-oauth"

[conventions.branches.bugfix]
prefix = "bugfix/"

[conventions.validation]
mode = "strict"

Mode migration

If you have an older config with deprecated mode names, bonsai migrates them automatically on load:

Old nameNew name
noviceguided
learningstandard

Keybinding remapping

Only eight keys are remappable. All other keys (l, B, d, x, o, f, t, W, O, M, n, L, X, C, R, A, i, e, ?, a) are fixed.

Example - swap push and pull:

[keybindings]
push = "l"
pull = "p"

Configuration

Flows and Conventions

Workflow flows

A “flow” tells bonsai how your team organises branches and where pull requests land. It affects the branch creation picker and the contextual hints shown after each action.

FlowDescription
autoDetected from your branch conventions (default)
trunkShort-lived branches merged frequently into main
gitflowfeature / bugfix / release / hotfix; PRs target develop
githubflowFeature branches with PRs directly into main
forkingFork-based contribution model
[flow]
type = "auto"   # auto | trunk | gitflow | githubflow | forking

auto (default)

bonsai inspects your [conventions.branches] config and infers the flow:

  • If all four gitflow types are present (feature, bugfix, release, hotfix) - gitflow
  • Otherwise - trunk

Use auto if you want bonsai to adapt without manual configuration.

trunk

Short-lived topic branches that merge directly into main. The branch picker shows a simple name input.

[flow]
type = "trunk"

[conventions.branches.feature]
prefix = "feat/"

[conventions.branches.bugfix]
prefix = "fix/"

gitflow

Feature branches off develop; releases and hotfixes have their own prefixes. The branch picker shows four options:

  1) feature   feat/PROJ-123-description
  2) bugfix    fix/PROJ-456-description
  3) release   release/1.2.0
  4) hotfix    hotfix/critical-fix
[flow]
type = "gitflow"

[conventions.branches.feature]
prefix  = "feat/"
pattern = "feat/{ticket-id}-{description}"
example = "feat/PROJ-123-login-oauth"

[conventions.branches.bugfix]
prefix  = "fix/"
example = "fix/PROJ-456-crash-on-login"

[conventions.branches.release]
prefix = "release/"

[conventions.branches.hotfix]
prefix = "hotfix/"

githubflow

Feature branches with PRs into main. Simpler than gitflow - only two branch types:

[flow]
type = "githubflow"

[conventions.branches.feature]
prefix = "feat/"

[conventions.branches.bugfix]
prefix = "fix/"

forking

Same branch structure as githubflow but the hints remind you to push to your fork and open a PR upstream.

Branch conventions

Conventions let you enforce a consistent naming scheme across your team.

[conventions.branches.feature]
prefix  = "feat/"
pattern = "feat/{ticket-id}-{description}"
example = "feat/PROJ-123-login-oauth"
FieldRequiredDescription
prefixyesBranch names must start with this string
patternnoHuman-readable template shown in the convention panel
examplenoConcrete example shown as a hint

Validation modes

[conventions.validation]
mode = "strict"   # strict | warn | off
ModeBehavior
strictBlocks actions that would result in a non-conforming branch name
warnShows a warning in the main panel header but does not block
offNo validation at all

Custom branch types

You can define as many types as you need:

[conventions.branches.chore]
prefix  = "chore/"
example = "chore/update-dependencies"

[conventions.branches.docs]
prefix  = "docs/"
example = "docs/api-reference"

Protected branch names

The following branch names are always allowed regardless of conventions: main, master, develop, HEAD, and any branch whose name matches a configured prefix exactly.

Per-project conventions

Add a .bonsai.toml to override conventions for a specific repo without changing your global defaults:

# .bonsai.toml
[conventions.branches.feature]
prefix  = "feature/"
example = "feature/auth-oauth"

[conventions.validation]
mode = "warn"

Interactive setup

Run the wizard to configure conventions interactively:

bonsai setup           # global
bonsai setup --local   # this repo only

Reference

Doctor

bonsai doctor audits your Git configuration and reports findings as a structured health check. It covers both the global ~/.gitconfig and the local repo config.

Usage

bonsai doctor            # standard output
bonsai doctor --verbose  # adds a one-line explanation per check

Output format

Global
  ✓  git version             2.50.1
  ✓  user.name               Jane Doe
  ✓  user.email              jane@example.com
  ⚠  credential.helper       not set
     fix: run: git config --global credential.helper osxkeychain
  ⚠  init.defaultBranch      set to "master" (recommended: main)
     fix: run: git config --global init.defaultBranch main
  ✓  pull.rebase             true
  ✓  ssh key                 /Users/jane/.ssh/id_ed25519
  ✓  ssh-agent               running (2 key(s) loaded)
  ✓  ssh github.com          Hi jane! You've successfully authenticated...

Local  (my-project)
  ✓  remote origin           git@github.com:org/my-project.git
  ✓  upstream tracking       origin/main
  ✓  .gitignore              present

Summary: 0 errors, 2 warnings, 17 passed

Exit code is 1 if any check has level error (), 0 otherwise.

Global checks

CheckWhat it looks for
git versionGit 2.28 or later
user.nameMust be set; used on every commit
user.emailMust be set and look like an email address
credential.helperPrevents re-entering passwords on every push
init.defaultBranchShould be main to match GitHub/GitLab defaults
pull.rebasetrue keeps history linear by rebasing instead of merging on pull
fetch.prunetrue auto-removes stale remote-tracking refs
push.autoSetupRemotetrue eliminates the need for -u origin <branch> on first push
rerere.enabledtrue memorises conflict resolutions so git can replay them
core.editorChecks $VISUAL, $EDITOR, and core.editor
global gitignoreChecks core.excludesfile and standard locations
gpg signingIf commit.gpgsign=true, verifies user.signingkey is set
ssh keyLooks for an SSH key in ~/.ssh
ssh-agentChecks SSH_AUTH_SOCK is set and at least one key is loaded
ssh <host>Tests SSH connectivity against the repo’s remote host

Local checks

CheckWhat it looks for
remote originAn origin remote must be configured
upstream trackingCurrent branch must track a remote branch
.gitignoreA project-level .gitignore must exist
merge/rebase stateNo interrupted merge, cherry-pick, or rebase
uncommitted changesReports how many files have uncommitted changes
stale remote branchesDetects refs that would be pruned by git remote prune origin
branch conventionsIf .bonsai.toml is present, checks current branch name
repo sizeWarns if the pack size exceeds 100 MB

Verbose mode

Adds a dimmed explanation line under each check:

  ⚠  pull.rebase             not set
     'git pull' merges by default, which creates noisy merge commits on every
     sync. With pull.rebase=true it rebases instead, keeping history linear.
     fix: run: git config --global pull.rebase true

Fixing issues

Each warning and error includes a fix: line with the exact command to run. You can copy and run it directly, or apply global settings from the Configuration manager inside the TUI (C key → Recommendations).


Reference

Advanced Git

All advanced operations are accessible from the main TUI panel. This page explains what each one does, how to reach it, and what to expect.

Hunk staging (h)

Stage or unstage individual hunks within a file instead of the whole file.

  1. Navigate to a changed or staged file in the main panel.
  2. Press h to open the hunk panel.
  3. Each hunk shows its @@ ... @@ header and a short preview of the changed lines.
KeyAction
/Move selection
spaceToggle the selected hunk on/off
aSelect all / deselect all
enterApply selected hunks (stage or unstage)
escCancel

All hunks are selected by default. Deselect the ones you want to leave out, then press enter.

Staging hunks uses git apply --cached. Unstaging reverses the patch with git apply --cached --reverse.

Untracked files cannot be partially staged - press space to stage the full file first.

Push menu (p)

Opens a menu instead of pushing immediately, so you can choose the push mode.

OptionGit commandWhen to use
Pushgit pushNormal push to the tracking remote
Force with leasegit push --force-with-leaseForce-push after a rebase; fails if the remote has commits you have not fetched
Set upstreamgit push --set-upstream origin <branch>First push of a new branch

Navigate with / and press enter to execute.

Reset (z)

Opens a menu with three reset modes. Resets apply to the current HEAD.

OptionGit commandEffect
softgit reset --soft HEAD~1Undoes the last commit; changes remain staged
mixedgit reset --mixed HEAD~1Undoes the last commit; changes remain unstaged
hardgit reset --hard HEAD~1Undoes the last commit and discards all changes

Hard reset is destructive and requires confirmation.

Merge

Available from the log panel (l - select a commit - m). Merges the selected commit into the current branch.

If the merge produces conflicts they appear in the Conflicts section at the top of the main panel. Use the conflict panel (d on a conflicted file) to resolve them.

Cherry-pick

Also available from the log panel. Select a commit and press p to cherry-pick it onto the current branch.

Tags (t)

The tag list panel shows all local tags.

KeyAction
nCreate a new lightweight tag at HEAD
dDelete the selected tag
pPush the selected tag to origin (confirm required)
escBack

Interactive rebase (R)

  1. Press R from the main panel.
  2. Enter a base ref - the rebase will include all commits between that ref and HEAD. Examples: HEAD~5, main, a specific hash.
  3. The commit list appears. Each commit shows its action, hash, and message.
KeyAction
/Move selection
K / JReorder commits up / down
enterCycle action (pick - reword - squash - fixup - drop)
rStart the rebase
escCancel
ActionDescription
pickKeep the commit as-is
rewordKeep the commit but edit the message
squashMerge into the previous commit, edit combined message
fixupMerge into the previous commit, discard this message
dropRemove the commit entirely

Amend (A)

Opens the amend panel for HEAD.

OptionDescription
messageChange the commit message
authorChange the author name and email
dateChange the commit date
–no-editAmend without changing the message (absorbs staged changes)

Only amend commits that have not been pushed to a shared remote.

Blame (e)

Select a file from the main panel and press e to open the blame view.

Each line shows the abbreviated hash, author, date, and source line. Scroll with /. Press esc to close.

Bisect (i)

Binary search for the commit that introduced a bug.

  1. Press i to open the bisect panel.
  2. Press s to start.
  3. Mark the current state as b (bad) or g (good).
  4. Git checks out the midpoint commit. Test it and mark again.
  5. Repeat until bisect identifies the culprit.
  6. Press r to reset and return to the original branch.

Worktrees (W)

Linked worktrees let you check out a different branch in a separate directory without disturbing your current work.

KeyAction
aAdd a new worktree (enter path and branch name)
dRemove the selected worktree
escBack

Example: check out a hotfix while keeping your feature branch work intact:

~
├── my-project/           ← main worktree (feat/login branch)
└── my-project-hotfix/    ← linked worktree (hotfix/critical-fix branch)

Remotes (O)

KeyAction
aAdd a new remote (enter name and URL)
dRemove the selected remote
rRename the selected remote
escBack

Submodules (M)

KeyAction
aAdd a submodule (enter URL and optional local path)
uRun git submodule update --init on all submodules
dDeinit the selected submodule
escBack

Status icons:

IconMeaning
(space)Clean, matches parent recorded hash
MChecked out commit differs from the recorded hash
?Not initialised
!Merge conflict

Restore (o)

Select a file and press o to restore it to a specific state.

Enter a ref in the input (defaults to HEAD). Valid values:

  • HEAD - discard all changes and return to the last commit
  • HEAD~2 - restore to two commits ago
  • abc1234 - restore to a specific commit hash
  • main - restore to the tip of another branch

The restore appears as a modification in your working tree; you still need to stage and commit it if you want to keep it.

Reflog (L)

Shows all recent HEAD movements - commits, checkouts, resets, merges, rebases.

KeyAction
/Scroll
rReset HEAD to the selected entry (mixed reset, confirm required)
yCopy the hash to clipboard
escBack

Use the reflog to recover commits that appear to be lost after a hard reset or accidental branch deletion.

Notes (n)

Git notes attach metadata to a commit without changing the commit itself.

KeyAction
eEdit the note (opens inline input)
dDelete the note (confirm required)
escBack

Notes are stored in refs/notes/commits and are not transferred on push/pull by default. To share notes:

git push origin refs/notes/*
git fetch origin refs/notes/*:refs/notes/*

Clean (X)

Shows a preview of all untracked files and directories that would be removed by git clean -fd. Requires confirmation before deleting anything.

This is a destructive operation. Untracked files are not in Git history and cannot be recovered once removed.

Conflict resolution

When a merge, cherry-pick, or rebase produces conflicts:

  1. The conflicts appear at the top of the main panel.
  2. Select a conflicted file and press d to open the conflict viewer.
KeyAction
oAccept ours - keep our version, discard theirs
tAccept theirs - keep their version, discard ours
bAccept base (common ancestor)
rRemove markers - keep both sides concatenated
eManual edit mode - type a custom resolution

After resolving all conflicts, stage the files and commit.

Press a from the main panel to abort an in-progress operation entirely.

File history (H)

Shows the commit history for a single file - every commit that touched it.

  1. Select any tracked file in the main panel.
  2. Press H to open the file history panel.
  3. Each line shows the hash, date, author, and subject of the commit.
  4. Press enter on a commit to open the commit detail panel.
  5. From the commit detail panel press d to see the full diff, or esc to return.

Branch graph (g)

Opens a full git log --graph --all --oneline --decorate view showing the commit and branch topology of the whole repository.

Scroll with / and press esc to close.

Branch operations (from branch list B)

KeyAction
enterSwitch to selected branch
mMerge selected branch into current
rRebase current onto selected branch
dDelete selected local branch
nRename selected branch
DDelete the remote tracking branch for the selected branch

d uses git branch -d (safe delete - fails on unmerged work). Both require confirmation.

Stash operations (from stash list S)

KeyAction
enterPop the selected stash (git stash pop)
aApply without removing (git stash apply)
dDrop the selected stash (git stash drop)

Use a when you want to apply a stash to multiple branches. Both d and enter require confirmation.

Configuration manager (C)

The configuration manager panel gives you a read/edit view of all config files without leaving bonsai.

SectionFile
Global config~/.gitconfig
Local config.git/config
Global gitignore~/.config/git/ignore or core.excludesfile
Local .gitignore.gitignore
RecommendationsBest-practice settings with one-key apply
Profiles (includeIf)Conditional config includes

Press enter on a section to view it. Press e to open it in your configured editor. In the Recommendations section press enter to apply a setting directly.