From d7b10e3ffa517e98ee537d5c4bd508ecf9b978b4 Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Mon, 1 Jun 2026 22:35:43 +0200 Subject: [PATCH 1/2] Updated AI agents docs --- content/docs/ai-agents/getting-started.mdx | 103 + content/docs/ai-agents/meta.json | 12 + content/docs/ai-agents/overview.mdx | 56 + content/docs/ai-agents/parallel-agents.mdx | 96 + content/docs/ai-agents/review-agent-work.mdx | 65 + .../docs/ai-agents/tuning-agent-behavior.mdx | 171 + content/docs/ai-agents/useful-requests.mdx | 123 + content/docs/features/meta.json | 2 +- content/docs/meta.json | 2 + public/img/docs/ai-agents-tui.png | Bin 0 -> 374055 bytes public/llms-full.txt | 5160 +++++++++-------- 11 files changed, 3378 insertions(+), 2412 deletions(-) create mode 100644 content/docs/ai-agents/getting-started.mdx create mode 100644 content/docs/ai-agents/meta.json create mode 100644 content/docs/ai-agents/overview.mdx create mode 100644 content/docs/ai-agents/parallel-agents.mdx create mode 100644 content/docs/ai-agents/review-agent-work.mdx create mode 100644 content/docs/ai-agents/tuning-agent-behavior.mdx create mode 100644 content/docs/ai-agents/useful-requests.mdx create mode 100644 public/img/docs/ai-agents-tui.png diff --git a/content/docs/ai-agents/getting-started.mdx b/content/docs/ai-agents/getting-started.mdx new file mode 100644 index 0000000..5dfa21f --- /dev/null +++ b/content/docs/ai-agents/getting-started.mdx @@ -0,0 +1,103 @@ +--- +title: Getting started +description: Install `but`, install the GitButler agent skill, and add a baseline version-control policy for coding agents. +--- + +This page is for coding agents that can read local instruction files and run +commands in your repository. The GitButler skill does not give the agent new +permissions. It tells the agent how to use `but` instead of driving Git through +checkout, stash, add, commit, and rebase commands. + +## Install the `but` CLI + +If you already have GitButler Desktop installed, you can install the CLI from +the Desktop Client settings. For terminal-only setup, run: + +```sh +curl -fsSL https://gitbutler.com/install.sh | sh +``` + +See [Installation and setup](/cli-guides/installation) for the full CLI install +options. + +## Install the GitButler skill + +Run the installer from the same repository: + +```sh +but skill install +``` + +The installer prompts for scope first: current repository or global home +directory. It then prompts for the skill format. Current formats include Agent +Skills (`.agents/skills`), Claude Code, OpenCode, Codex, GitHub Copilot, Cursor, +and Windsurf. + +For custom paths, global installs, non-interactive updates, and skill checks, +see [`but skill`](/commands/but-skill). + +## Set up the repository + +GitButler currently needs the repository in workspace mode for its multi-branch +model: multiple GitButler branches in one working directory. + +From the repository where the agent will work, run: + +```sh +but setup +``` + +You can also skip this step and let the agent run `but setup` when it first +needs GitButler. For the full list of setup changes, see +[`but setup`](/commands/but-setup). + +GitButler is working toward a plain Git mode that switches into a workspace only +when multiple concurrent branches are needed. Follow +[gitbutlerapp/gitbutler#11866](https://github.com/gitbutlerapp/gitbutler/issues/11866) +for that work. + +## Add optional agent instructions + +The GitButler skill tells the agent how to use `but`. Your own instructions +tell the agent what behavior you want. + +Put project defaults in a repository instruction file such as `AGENTS.md` or +`CLAUDE.md`. Put personal defaults in a global instruction file such as +`~/.codex/AGENTS.md`, `~/.claude/CLAUDE.md`, Cursor rules, Copilot custom +instructions, or the equivalent for your tool. + +These files steer agent behavior; they are not access controls. Use your usual +repository permissions and branch protection for hard limits. + +Use this baseline to keep agent work isolated: + +```md +## Version control + +- Use GitButler (`but`) for version-control write operations, including + branching, committing, pushing, and history edits. +- Assume multiple agents may be working in this repository. Do not move, amend, + squash, discard, commit, push, or otherwise modify another agent's work unless + the user asks. +- Use a dedicated GitButler branch for each agent session, unless the user asks + for a different branch structure. Commit only changes that belong to that + session. +- Do not push or open pull requests unless the user asks. +- Keep commit messages and pull request descriptions succinct: explain what + changed, why it changed, and any important decision. +``` + +You can also tune the agent to: + +- amend local fixes into existing commits; +- create checkpoint commits and tidy them before review; +- create stacked pull requests for dependent work; +- follow your branch and commit naming conventions; +- publish, update from main, or create recovery points only when your policy + allows it. + +For copyable snippets, see +[Tuning agent behavior](/ai-agents/tuning-agent-behavior). + +For prompt examples that ask for specific branch and commit outcomes, see +[Useful requests](/ai-agents/useful-requests). diff --git a/content/docs/ai-agents/meta.json b/content/docs/ai-agents/meta.json new file mode 100644 index 0000000..0b09916 --- /dev/null +++ b/content/docs/ai-agents/meta.json @@ -0,0 +1,12 @@ +{ + "title": "AI Agents", + "defaultOpen": false, + "pages": [ + "overview", + "getting-started", + "useful-requests", + "parallel-agents", + "review-agent-work", + "tuning-agent-behavior" + ] +} diff --git a/content/docs/ai-agents/overview.mdx b/content/docs/ai-agents/overview.mdx new file mode 100644 index 0000000..ccaf722 --- /dev/null +++ b/content/docs/ai-agents/overview.mdx @@ -0,0 +1,56 @@ +--- +title: Overview +description: Use GitButler to keep coding-agent changes organized into branches and commits you can inspect and review. +--- + +Use GitButler with coding agents when you want messy local changes to become +reviewable branches and commits without moving every task into a separate +worktree. + +GitButler keeps one working directory while organizing changes into separate +branches and commits. Agents can do that through the [`but` CLI](/cli-overview), +and you can inspect the same state in the [Desktop Client](/overview). For when +to use GitButler instead of separate worktrees, see +[Parallel agents](/ai-agents/parallel-agents#how-this-differs-from-worktrees). + +You decide how far the agent goes. You can tell it to stop after local commits, +or you can allow it to push and open pull requests. GitButler gives the agent +version-control commands; your instructions decide when it stops. + +## What agents can do with GitButler + +- **Parallel branches in one workspace.** An agent can create separate branches + for independent work while staying in the same working directory. That gives + you separate review branches without creating a new worktree, directory, and + setup for each task. +- **Selected files and hunks.** The agent can assign selected files or hunks to + a branch, then commit that branch. You can inspect the split before the work + is pushed. +- **Stacked branches for dependent work.** If one change depends on another, the + agent can put the dependent branch on top of the branch it needs. +- **History edits without an interactive rebase.** The agent can move a change + from one commit to another, reorder commits, reword commits, absorb fixes, or + split a commit with `but` commands. +- **Review and recovery before publishing.** You can inspect the same branches + and commits in the CLI or Desktop Client, then use [`but oplog`](/commands/but-oplog) + to restore an earlier local GitButler state if the branch layout needs to be + rolled back. + +## History edits as direct commands + +History edits are where agent workflows often get brittle. Moving one file's +changes from one commit to another with Git can involve patch restore/reset +steps, fixup commits, autosquash, or an interactive rebase with one or more +`edit` stops. + +With GitButler, that kind of edit becomes a direct operation: move this file's +changes into that commit. The operation can still rewrite commits and can still +conflict. The difference is control flow: the agent gets targeted tools for the +edit instead of driving a multi-step rebase session. + +For more detail, see the [`but rub` command reference](/commands/but-rub) and +the [CLI guide to moving changes between commits](/cli-guides/cli-tutorial/rubbing#moving-files-between-commits). + +GitButler does not currently focus on a direct "push to main" workflow. Today, +it is best used to get from agent changes to clean local branches, commits, and +PRs or MRs quickly. diff --git a/content/docs/ai-agents/parallel-agents.mdx b/content/docs/ai-agents/parallel-agents.mdx new file mode 100644 index 0000000..3e1e8a8 --- /dev/null +++ b/content/docs/ai-agents/parallel-agents.mdx @@ -0,0 +1,96 @@ +--- +title: Parallel agents +description: Run multiple coding agents in one GitButler workspace without creating separate worktrees. +--- + +Parallel agents do not require separate worktrees or pre-created branches. Once +agents use GitButler for version-control writes, you can start another coding +session in the same repository and prompt it like any other task: + +```text +Work on checkout validation. +``` + +When either session is ready, ask it to commit: + +```text +Commit your changes. +``` + +The agent uses GitButler to commit the changes for its task to its GitButler +branch. The branch routing is the agent's job; your prompt can stay small. + +If two sessions touch the same file or generated output, have the agents call +out the overlap before committing. + +You can also ask an agent to split independent work out of the current session. +For example, if a feature session also finds a small bug fix, the agent can +move the relevant changes or commits to a new branch and prepare a separate PR +instead of stacking the fix on the feature. + +For more background on the branch model, see +[Parallel branches](/features/branch-management/virtual-branches). + +The baseline `Version control` instructions from +[Getting started](/ai-agents/getting-started#add-optional-agent-instructions) +are useful if you want to steer commit behavior, but they are not a separate +parallel-agent setup step. + +## How this differs from worktrees + +Git has one checked-out branch per worktree. If you want two agents to work on +two branches at the same time, the usual Git answer is multiple worktrees. + +GitButler gives you a different option: multiple active branches in one +worktree, with each agent's commits organized onto the branch for its session. + +| | Multiple worktrees | GitButler parallel branches | +| --- | --- | --- | +| Workspace | One directory per agent | One shared working directory | +| Branches | One checked-out branch per worktree | Multiple active branches in one worktree | +| Isolation | Separate checkout | Shared filesystem and runtime state | +| Setup cost | Usually more directories, dependency installs, build outputs, and dev servers | Reuse one install and dev server when tasks can share runtime state | +| Version-control shape | Branches stay separate because work happens in separate directories | GitButler can commit the right subset of changes to each branch | +| Best fit | Competing attempts, incompatible checkout states, isolated runtimes | Unrelated features or fixes that can share one workspace | + +Use multiple worktrees when agents need incompatible checkout states, separate +runtime state, or competing attempts at the same task. Use GitButler parallel +branches when the tasks are independent enough to share one workspace and you +want less local overhead. + +## Handle dependencies explicitly + +Parallel agents work best when sessions start independent. If one session +starts depending on another, make that relationship explicit by stacking the +branches: + +```text +The notification settings work now depends on checkout validation. Stack your +branch on top of the checkout validation branch. +``` + +If an unrelated fix shows up inside a feature session, tell the agent to extract +it instead: + +```text +The cache invalidation fix is independent. Move it to a separate GitButler +branch and prepare a separate PR for it. +``` + +If the feature depends on the fix, put the fix on the lower branch and stack the +feature above it instead. For stacked PR policy, see +[Create stacked pull requests](/ai-agents/tuning-agent-behavior#create-stacked-pull-requests). + +## Know what is shared + +Parallel GitButler branches are not runtime isolation. The agents share one +filesystem, dependency install, generated files, and app state. That can surface +overlap and broken builds earlier, but it can also hide accidental +dependencies. + +Before shipping a branch independently, check whether it depends on another +active branch. If two agents start editing the same files or generated output, +decide whether to keep the work parallel, stack one branch on the other, or use +separate worktrees. + +For more request examples, see [Useful requests](/ai-agents/useful-requests). diff --git a/content/docs/ai-agents/review-agent-work.mdx b/content/docs/ai-agents/review-agent-work.mdx new file mode 100644 index 0000000..55a9d79 --- /dev/null +++ b/content/docs/ai-agents/review-agent-work.mdx @@ -0,0 +1,65 @@ +--- +title: Inspect and adjust agent work +description: Choose a GitButler surface for previewing and adjusting coding-agent branch and commit history. +--- + +import ImageSection from "@/components/ImageSection" + +When your coding agent uses GitButler, it can do the version-control work for +you: create branches, commit changes, move work between commits, and reshape +local history. The agent usually does this through the GitButler CLI. + +You may still want to preview what it created or manually adjust the branch and +commit history before anything is pushed or turned into a PR. GitButler gives +you three ways to inspect and adjust that state: the TUI, the CLI, and the +Desktop Client GUI. Use this page to pick the surface you want. The detailed +CLI and Desktop workflows live in their own docs. + +## GitButler TUI + +Use the TUI when you want a terminal view of the workspace without switching to +the Desktop Client. It is useful for checking branch state, looking at what is +on a branch or still unassigned, and making small manual adjustments to branch +assignment, commit membership, or history shape. + +```sh +but tui +``` + + + +## GitButler CLI + +Use the CLI when you want exact output, scriptable commands, or the same view of +the repository state that the agent uses. + +For command details, start with the [CLI overview](/cli-overview). + +## GitButler Desktop Client + +Use the Desktop Client when you want a visual overview of branches, commits, +assigned changes, unassigned changes, parallel work, and stacked work. It is +also the visual surface for moving changes between branches and adjusting +commit history. + +```sh +but gui +``` + +For details, see the [Desktop Overview](/overview), +[Branch lanes](/features/branch-management/branch-lanes), and +[Commits](/features/branch-management/commits). + +## Operations history + +GitButler records version-control operations so you can inspect or undo local +history edits. If a branch reorganization does not look right, inspect the +operation history before making more changes. See +[Timeline](/features/timeline), [`but oplog`](/commands/but-oplog), and +[`but undo`](/commands/but-undo). diff --git a/content/docs/ai-agents/tuning-agent-behavior.mdx b/content/docs/ai-agents/tuning-agent-behavior.mdx new file mode 100644 index 0000000..d14406e --- /dev/null +++ b/content/docs/ai-agents/tuning-agent-behavior.mdx @@ -0,0 +1,171 @@ +--- +title: Tuning agent behavior +description: Add optional instruction snippets that steer how coding agents amend, checkpoint, stack, publish, and recover work with GitButler. +--- + +Add these optional bullets under the same `## Version control` section as the +baseline from +[Getting started](/ai-agents/getting-started#add-optional-agent-instructions). +Use this page as a menu: copy only the policies you want for the repository and +agent you are using. + +## Amend local fixes into the right commits + +Use this when you want the agent to fold follow-up fixes into unpublished local +commits when the new change clearly belongs with that commit's intent. With +GitButler, the agent can move the relevant change into the commit where it +belongs. + +```md +- For small cleanup or follow-up fixes, amend an unpublished local commit when + the change clearly belongs with that commit's intent. +- Do not create tiny fixup commits unless I ask. +- Use GitButler to move the relevant changes into the commit where they belong. +- Ask before rewriting pushed, reviewed, shared, or ambiguous history. +``` + +You do not need to tell the agent which command to use. The GitButler skill +gives it the relevant operations. For background, see +[`but absorb`](/commands/but-absorb) and [`but amend`](/commands/but-amend). + +## Commit checkpoints after each completed turn + +Use this when you want local savepoints while the agent works. The checkpoints +do not need to be the final review history. Before review, you can ask the +agent to tidy unpublished local history. + +```md +- Commit after a working checkpoint, when the requested change is complete and + relevant checks have passed or been reported. +- Treat checkpoint commits as local savepoints, not final review history. +- When I ask you to tidy the history, use GitButler to squash commits, reword + commits, and move changes between commits where appropriate. +- Only tidy unpublished local history unless I explicitly authorize changing + pushed or shared history. +``` + +## Create stacked pull requests + +Use this when you want dependent work reviewed as stacked pull requests. This is +useful when one agent session depends on another session's branch, or when an +agent is working on a branch that sits at the bottom of a stack. + +```md +- If this session depends on another in-flight branch, stack its branch on top + of that dependency instead of mixing the changes. +- If this session is working in a stack, put commits on the branch where they + belong. +- Ask before moving commits onto lower, pushed, reviewed, or shared branches. +- Use `but move` for branch stacking and restacking. Do not recreate branches + to simulate stacking. +- For stacked branches, create pull requests with `but pr`, not `gh`, so + GitButler keeps the right PR base branches and stack metadata. +``` + +For background, see [Stacked branches](/features/branch-management/stacked-branches), +[`but move`](/commands/but-move), and [`but pr`](/commands/but-pr). + +## Customize branch names + +Use this when your team has a naming convention for branches the agent creates. +This is only an example; replace the prefix and shape with your convention. + +```md +- When creating a GitButler branch for an agent session, use + `feature/-` when a ticket ID is available. +``` + +## Customize commit messages + +Use this when your team has a commit-message convention. This is only an +example; replace it with your preferred style. + +```md +- Use Conventional Commits, such as `feat: add branch naming policy` or + `fix: handle empty branch names`. +``` + +## Publish when you say "ship it" + +Use this when you want a short phrase to authorize the agent to finish the +version-control work for its session. This commits, pushes, and creates or +updates a pull request, so use it only when the agent is allowed to publish. + +```md +- When I say "ship it", commit this session's changes on its dedicated + GitButler branch, creating one if needed. +- Push the branch and open or update its pull request with GitButler. +- Reuse the existing branch or pull request for this session when one already + exists. +``` + +For background, see [`but push`](/commands/but-push) and +[`but pr`](/commands/but-pr). + +## Update from main automatically + +Use this when your project moves quickly and you want the agent to keep its +workspace current with the target branch, usually `main` or `master`. The +GitButler command for this is `but pull`, which fetches the target branch and +rebases applied branches onto the new target commit. This is a preference: in +some repositories, you may want the agent to ask before updating. + +Add the last bullet only if you want the agent to handle update conflicts. + +```md +- When GitButler status shows new changes on the target branch, run + `but pull --check`. +- If the check is clean and the update affects only this session's branches, + update the workspace with `but pull`. +- If the check reports conflicts or the update would affect another agent's + branch, ask before updating. +- If I ask you to handle update conflicts, use GitButler's conflict tools. Ask + before resolving semantic conflicts, dependency updates, generated files, or + conflicts involving another person's work. +``` + +You do not need to tell the agent which command to use. For background, see +[`but pull`](/commands/but-pull) and [`but resolve`](/commands/but-resolve). + +## Open draft pull requests by default + +Use this when the agent is allowed to publish work, but you still want review to +start in draft. Creating a draft pull request still publishes the branch. + +```md +- When I ask you to open a pull request, create it as a draft with GitButler + unless I say it is ready for review. +``` + +## Create a recovery point before large history edits + +Use this when you want the agent to be more cautious before reorganizing several +commits or branches. + +```md +- Before squashing, splitting, moving commits between branches, or reorganizing + multiple branches, run `but oplog snapshot -m ""`. +- Use GitButler history-edit commands such as `but move`, `but squash`, + `but reword`, `but absorb`, and `but amend` instead of raw Git rebases. +- If an operation makes the branch or history layout worse, stop and inspect the + operation log before attempting another fix. +- Prefer `but undo` or `but oplog restore` over trying to repair a bad state + with more history edits. +``` + +For command details, see [`but oplog`](/commands/but-oplog) and +[`but undo`](/commands/but-undo). + +## Split unrelated hunks + +Use this when agents tend to commit whole files even when one file contains +separate changes. + +```md +- If one file contains unrelated changes, split them by hunk instead of + committing the whole file. +- Keep tests with the behavior they verify. +- Split generated output, docs-only edits, or mechanical cleanup into separate + commits when each commit remains coherent on its own. +- If the split is ambiguous, summarize the options before committing. +``` diff --git a/content/docs/ai-agents/useful-requests.mdx b/content/docs/ai-agents/useful-requests.mdx new file mode 100644 index 0000000..f3b9622 --- /dev/null +++ b/content/docs/ai-agents/useful-requests.mdx @@ -0,0 +1,123 @@ +--- +title: Useful requests +description: Ask coding agents to commit, reshape history, split work, and create stacked pull requests with GitButler. +--- + +Once the GitButler skill is installed and your baseline version-control +instructions are in place, ask for the branch, commit, or pull request outcome +you want. You do not need to know the `but` commands or CLI IDs; the agent uses +those to build the structure you describe. + +Use these examples as one-off requests you can mix with normal coding prompts. +They are intentionally short; add whatever constraints matter in your repo. For +standing rules that always apply, see +[Tuning agent behavior](/ai-agents/tuning-agent-behavior). + +## Commit changes + +With the baseline instructions from +[Getting started](/ai-agents/getting-started#add-optional-agent-instructions), +the agent commits on the dedicated GitButler branch for its session. It commits +that session's changes there, not unrelated user or agent work. + +You can tell your agent: + +```text +Commit your changes. +``` + +Relevant command: [`but commit`](/commands/but-commit). + +## Clean up history + +GitButler gives the agent direct tools for moving commits, squashing commits, +rewording commits, and moving changes between commits. Describe the end result +you want instead of writing out an interactive rebase plan. + +Keep history cleanup to unpublished local work unless you explicitly authorize +rewriting pushed or shared branches. + +```text +Clean up the history. Squash WIP commits, split unrelated work, and reword +messages based on intent. Show me the plan before changing history or pushing. +``` + +Relevant commands: [`but move`](/commands/but-move), +[`but squash`](/commands/but-squash), [`but reword`](/commands/but-reword), +and [`but rub`](/commands/but-rub). + +## Split a large commit into smaller commits + +Use this when a commit is too large to review as one unit. Say how you want the +work grouped; the agent can create the intermediate commits and move the right +changes into them. + +This prompt is an example; replace the grouping rules with whatever matters for +your project. + +```text +Split this into smaller commits by concern. Keep tests with the behavior they +verify. +``` + +## Put uncommitted fixes into existing commits + +Use this after review feedback, test fixes, or a small follow-up edit that +belongs with an earlier local commit. + +```text +Amend your follow-up fixes into the appropriate local commits. +``` + +Relevant commands: [`but absorb`](/commands/but-absorb) and +[`but amend`](/commands/but-amend). + +## Take changes out of a commit + +Use this when something was committed by mistake, or when one commit contains a +change that belongs somewhere else. + +```text +Take the debug logging out of the commit and leave it uncommitted. +``` + +```text +Move the docs changes out of the feature commit and into a separate docs commit. +``` + +Relevant commands: [`but uncommit`](/commands/but-uncommit) and +[`but rub`](/commands/but-rub). + +## Create stacked pull requests + +Stacked pull requests help when one change depends on another, but reviewers can +still review the lower branch first. Creating draft PRs still pushes branches, +so use this only when the agent is allowed to publish. + +```text +Make the API work the base branch and stack the UI work on top. Create draft +PRs. +``` + +The agent can also stack or restack existing branches when the dependency +structure changes. If branches have already been pushed or reviewed, ask the +agent to show which PRs will change before restacking. If something in a stack +turns out to be independent, ask the agent to move it out into a separate +branch. + +For more background, see +[Stacked branches](/features/branch-management/stacked-branches), +[`but move`](/commands/but-move), and [`but pr`](/commands/but-pr). + +## Work in parallel + +Use parallel branches when the work does not depend on another branch. +GitButler lets multiple branches be active in the same workspace, so different +agents can work on their own branches without creating and managing separate +worktrees. + +This works best when the tasks do not depend on each other and are not editing +the same files. + +Stack branches only when one branch depends on another. For the fuller +multi-agent workflow, see [Parallel agents](/ai-agents/parallel-agents). diff --git a/content/docs/features/meta.json b/content/docs/features/meta.json index 4992924..4a13f0d 100644 --- a/content/docs/features/meta.json +++ b/content/docs/features/meta.json @@ -1,5 +1,5 @@ { "title": "Features", "defaultOpen": false, - "pages": ["branch-management", "timeline", "forge-integration", "ai-integration", "coding-agents", "gerrit-mode"] + "pages": ["branch-management", "timeline", "forge-integration", "gerrit-mode"] } diff --git a/content/docs/meta.json b/content/docs/meta.json index f52319c..a6ff354 100644 --- a/content/docs/meta.json +++ b/content/docs/meta.json @@ -11,6 +11,8 @@ "butler-flow", "features", "troubleshooting", + "---AI Agents---", + "...ai-agents", "---GitButler CLI---", "cli-overview", "cli-guides", diff --git a/public/img/docs/ai-agents-tui.png b/public/img/docs/ai-agents-tui.png new file mode 100644 index 0000000000000000000000000000000000000000..18d432548250461f4472d8b78cbf7f27f45c69f1 GIT binary patch literal 374055 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

A_{uEg?rAYzk#-^5 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

%PJkHrN!hA- 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

&zC|88 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

pewMb^HI3_Lfn3Wl6Yj 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 z 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 literal 0 HcmV?d00001 diff --git a/public/llms-full.txt b/public/llms-full.txt index 28d6636..fc1e5da 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -42,6 +42,7 @@ - [but-absorb](#but-absorb.mdx) - [but-alias](#but-alias.mdx) - [but-amend](#but-amend.mdx) +- [but-apply](#but-apply.mdx) - [but-branch](#but-branch.mdx) - [but-commit](#but-commit.mdx) - [but-config](#but-config.mdx) @@ -66,6 +67,7 @@ - [but-stage](#but-stage.mdx) - [but-status](#but-status.mdx) - [but-teardown](#but-teardown.mdx) +- [but-unapply](#but-unapply.mdx) - [but-uncommit](#but-uncommit.mdx) - [but-undo](#but-undo.mdx) - [but-unmark](#but-unmark.mdx) @@ -86,6 +88,11 @@ - [scripting](#scripting.mdx) - [tutorial-overview](#tutorial-overview.mdx) - [updating-the-base](#updating-the-base.mdx) +- [getting-started](#getting-started.mdx) +- [parallel-agents](#parallel-agents.mdx) +- [review-agent-work](#review-agent-work.mdx) +- [tuning-agent-behavior](#tuning-agent-behavior.mdx) +- [useful-requests](#useful-requests.mdx) # butler-flow.mdx @@ -113,7 +120,7 @@ In a nutshell, the basic development cycle is very simple. In stock, vanilla Git tooling, there is nothing specified as the production branch, no special "trunk". It is only by convention that this is enforced. -In GitButler, parallel branches will not work without the specification of a special "target branch". Everything exists in relation to this special branch, everything that differs from it must be accounted for by being owned by some other branch, until those changes are integrated. +In GitButler, branches will not work without the specification of a special "target branch". Everything exists in relation to this special branch, everything that differs from it must be accounted for by being owned by some other branch, until those changes are integrated. ### Parallel Branches @@ -138,32 +145,133 @@ Merge conflicts are known almost as soon as they occur and can be communicated a Parallel branches can remain applied locally until they are merged into your upstream target branch. Once integrated by any fashion (squash merge, rebase, merge), the virtual branch is automatically disposed of, keeping cruft and overhead low. -# cli-overview.mdx +# overview.mdx -In addition to the Desktop graphical client, GitButler ships with a command line interface that allows you to do all of the same powerful things that the GUI does, but from the terminal or via scripts or agents. +Use GitButler with coding agents when you want messy local changes to become +reviewable branches and commits without moving every task into a separate +worktree. + +GitButler keeps one working directory while organizing changes into separate +branches and commits. Agents can do that through the [`but` CLI](/cli-overview), +and you can inspect the same state in the [Desktop Client](/overview). For when +to use GitButler instead of separate worktrees, see +[Parallel agents](/ai-agents/parallel-agents#how-this-differs-from-worktrees). + +You decide how far the agent goes. You can tell it to stop after local commits, +or you can allow it to push and open pull requests. GitButler gives the agent +version-control commands; your instructions decide when it stops. + +## What agents can do with GitButler + +- **Parallel branches in one workspace.** An agent can create separate branches + for independent work while staying in the same working directory. That gives + you separate review branches without creating a new worktree, directory, and + setup for each task. +- **Selected files and hunks.** The agent can assign selected files or hunks to + a branch, then commit that branch. You can inspect the split before the work + is pushed. +- **Stacked branches for dependent work.** If one change depends on another, the + agent can put the dependent branch on top of the branch it needs. +- **History edits without an interactive rebase.** The agent can move a change + from one commit to another, reorder commits, reword commits, absorb fixes, or + split a commit with `but` commands. +- **Review and recovery before publishing.** You can inspect the same branches + and commits in the CLI or Desktop Client, then use [`but oplog`](/commands/but-oplog) + to restore an earlier local GitButler state if the branch layout needs to be + rolled back. + +## History edits as direct commands + +History edits are where agent workflows often get brittle. Moving one file's +changes from one commit to another with Git can involve patch restore/reset +steps, fixup commits, autosquash, or an interactive rebase with one or more +`edit` stops. + +With GitButler, that kind of edit becomes a direct operation: move this file's +changes into that commit. The operation can still rewrite commits and can still +conflict. The difference is control flow: the agent gets targeted tools for the +edit instead of driving a multi-step rebase session. + +For more detail, see the [`but rub` command reference](/commands/but-rub) and +the [CLI guide to moving changes between commits](/cli-guides/cli-tutorial/rubbing#moving-files-between-commits). + +GitButler does not currently focus on a direct "push to main" workflow. Today, +it is best used to get from agent changes to clean local branches, commits, and +PRs or MRs quickly. -https://www.youtube.com/watch?v=loavN_hHuEs -This includes tooling for: +# releases.mdx -- [managing stacked and parallel branches](cli-guides/cli-tutorial/branching-and-commiting) -- [inspecting and diffing](cli-guides/cli-tutorial/inspecting) -- [an operations log and restoration of older states](cli-guides/cli-tutorial/operations-log) -- [powerful commit editing](cli-guides/cli-tutorial/rubbing) -- [upstream management](cli-guides/cli-tutorial/updating-the-base) -- [conflict resolution](cli-guides/cli-tutorial/conflict-resolution) -- [working with forges](cli-guides/cli-tutorial/forges) -- [aliases and configuration](cli-guides/cli-tutorial/configuration) -All with a simple command line tool. +GitButler is released on a regular basis in two separate tracks. Their version numbers are incremented independently. -## Quick Reference +1. **Release** - stable releases +2. **Nightly** - development releases built at minimum 1x per day via GitHub Actions. -For a quick reference of the most commonly used commands, check out our [**GitButler CLI Cheat Sheet**](/cli/cheat) - available as a web page or downloadable PDF. -## Getting Started + +You can find the download links and changelogs for the latest releases on our [GitHub Releases](https://github.com/gitbutlerapp/gitbutler/releases). + -Feel free to get started with our [Tutorial](cli-guides/installation) or just dig into the available commands. +## Platforms + +We bundle and ship GitButler for Mac OS, Windows, and Linux. + +### Windows + +| Arch | Format | In-app updater | +| --- | --- | --- | +| `x86_64` | `msi` | | + +### Mac OS + +| Arch | Format | In-app updater | +| --- | --- | --- | +| `x86_64` | `dmg` | | +| `arm64` | `dmg` | | + +### Linux + +| Arch | Format | In-app updater | +| --- | --- | --- | +| `x86_64` | `deb` | | +| `x86_64` | `rpm` | | +| `x86_64` | `AppImage` | | + +> Support for the Linux releases are complicated a bit through a core dependency of our framework, `libwebkit2gtk`, which is used to provide the web view on Linux. Tauri v1 required `libwebkit2gtk-4.0` which is not available in Ubuntu 24.04 or Debian 13 and newer. +> +> We've recently upgraded to Tauri v2 (as of Nightly `0.5.845` and Release `0.13.9`), and it now requires `libwebkit2gtk-4.1`. This version of the package is not available in the repositories for Ubuntu 20.04 and older as well as Debian 11 and older. +> +> For more information, check out the [pinned issue](https://github.com/tauri-apps/tauri/issues/9662) in the Tauri repository. + + +# why-gitbutler.mdx + +The GitButler manifesto, as it were. + +Everyone loves a good manifesto. So, why is there a need for a new Git client in the world? Don't we have enough? Isn't the command line just fine? + +Having cofounded GitHub, trained dozens of corporate teams on distributed version control tools and literally written the book on Git, we have spent a lot of time and energy over the last decade thinking about the source code management tools that software developers use every day. + +GitHub has changed the way that millions of developers across the world collaborate and work with their source code, but as sophisticated and user friendly as that tool is in our daily coding lives, using GitHub or GitLab or Bitbucket still requires all of those developers to work with a command line tool that is confusing, difficult to use, error prone and not originally designed or built for the workflows and processes that most developers today use. That tool is Git. + +Sure, some small minority will use a GUI of some sort, but even those tools are mostly wrappers around the core concepts of Git itself, never reimagining what source code management could be or if Git itself is actually good at helping them with the tasks they face on a daily basis. I've never personally used one because they do little that Git itself doesn't and honestly it's generally easier to just do those tasks on the command line, where it's quick and efficient and I don't have to take my hands off the keyboard. + +But what if we broke down everything that you try to accomplish with Git, with source code management tools in general, reduce them down to first principles and imagine a tool that does all of those things better? Are you using Git because it's the best way you can imagine accomplishing those tasks, or are you using it because it's what is there, it's what works with GitHub, it's the only real option? + +The reality is that source code management tools have changed very little on a fundamental level in the last 40 years. If you look at the tools and commands and interface that RCS had in the 80s, or Subversion had in the 90s, is it really massively different than how you use Git today on a daily basis? + +Yes, Git has easy branching, acceptable merging, a nice network transport method to move your code around, but you're still making manual checkins, you're still trying to remember obscure arguments, you're still losing work when things get complicated. + +GitButler is rethinking everything between when you write code in your editor of choice and when you push that code to GitHub for review. Why are you making 'wip' commits when your SCM should be recording everything for you? Why are everyone's commit messages close to useless? Why is `git blame` the best way to get context on the code your team has written? Why can't you seamlessly transition work between computers? + +We are creating not only a new kind of Git client, but an entirely new way of thinking about managing the code that you work on. A tool that helps you at every step of the software development process. A code concierge, hard at work for you to ensure that you'll never lose a moment of work again. That you'll have all the context and support you'll need around every line of code you work on. + +Managing your source code can be different, smarter, leaps ahead of the 40 year old concepts that we're using today. + +Our goal is to make sure that nobody ever has to read Scott's book again. That you don't have to learn how to manage your source code management tool. + + # index.mdx @@ -215,6 +323,81 @@ The GitButler client is a powerful Git client. You can manage your branches, wor - [Project History](/features/timeline) +# workspace-branch.mdx + +If you run some normal Git commands (like `git log`) while in GitButler mode, you'll see a few special branches that GitButler maintains behind the scenes. The one that most people get confused by is the `gitbutler/workspace` commit. + +There are a few different reasons that we need it, so let's take a quick look. + +If you run a normal `git log` on a GitButler managed repository, you will see something like this: + +```git +commit de56d20e282f7641d48d288b510141996c3c3cfc (HEAD -> gitbutler/workspace) +Author: GitButler +Date: Wed Sep 9 09:06:03 2020 +0800 + + GitButler Workspace Commit + + This is is a merge commit of the parallel branches in your workspace. + + For GitButler to manage multiple parallel branches, we maintain + this commit automatically so other tooling works properly. + + If you switch to another branch, GitButler will need to be + reinitialized. + + Here are the branches that are currently applied: + + - update-homepage (refs/gitbutler/update-homepage) + branch head: a32f33273948837078e5f5a4e1677ab6274a4629 + + For more information about what we're doing here, check out our docs: + https://docs.gitbutler.com/workspace-branch + +commit a32f33273948837078e5f5a4e1677ab6274a4629 (update-homepage) +Author: Scott Chacon +Date: Mon Jan 26 07:33:31 2026 +0500 + + hero update - new branding + +``` + +That first commit is a merge commit that we rebuild as you modify branches in GitButler. The reason that it exists is mainly because if you have more than one branch applied in your workspace, when other tools run `git status`, it will look strange, since Git has no concept of having several branches applied at once. + +## Status, Diff and Log + +To keep Git command output for things that look at the index and HEAD (such as status or diff) somewhat sane, we modify your index to look like the union of all the committed states of all your applied parallel branches. This makes git diff and git status behave more or less like you would expect. + +For instance, if you have two files on Branch A and two files on Branch B, then git status will simply list four files as modified. + +If you run git log, the first commit should be our custom commit message and the tree of that commit is the union of all the committed work on all your applied parallel branches, as though they were all merged together into one (something stock Git can understand). + +## Committing, Branching, Checking Out + +However, if you try to use something that writes to HEAD, like git commit or git checkout, then you might have some headaches. For this reason, we install custom Git hooks for `pre-commit` and `post-checkout` that will protect this from happening. + +If you try to commit when in GitButler managed mode, the `pre-commit` hook should disallow it and tell you how to fix it. + +```git +❯ git commit -am 'commit on the workspace branch' + +GITBUTLER_ERROR: Cannot commit directly to gitbutler/workspace branch. + +GitButler manages commits on this branch. Please use GitButler to commit your changes: + - Use the GitButler app to create commits + - Or run 'but commit' from the command line + +If you want to exit GitButler mode and use normal git: + - Run 'but teardown' to switch to a regular branch + - Or directly checkout another branch: git checkout + +If you no longer have the GitButler CLI installed, you can simply remove this hook and checkout another branch: + rm ".git/hooks/pre-commit" +``` + +If you want to get out of this mode, you can follow any of those instructions. The easiest is running `but teardown`, but simply switching directly to a normal Git branch will also do the trick. + + # guide.mdx Here is a quick overview of how to get started with GitButler. In this guide, we will: @@ -227,7 +410,7 @@ Here is a quick overview of how to get started with GitButler. In this guide, we ## Importing a Local Repository -After [downloading](https://app.gitbutler.com/downloads) and installing GitButler, you will be greeted with the welcome screen. From here you can +After [downloading](https://gitbutler.com/downloads) and installing GitButler, you will be greeted with the welcome screen. From here you can -# releases.mdx +# cli-overview.mdx +In addition to the Desktop graphical client, GitButler ships with a command line interface that allows you to do all of the same powerful things that the GUI does, but from the terminal or via scripts or agents. -GitButler is released on a regular basis in two separate tracks. Their version numbers are incremented independently. +https://www.youtube.com/watch?v=Jg8L3SbgZ3o -1. **Release** - stable releases -2. **Nightly** - development releases built at minimum 1x per day via GitHub Actions. +This includes tooling for: +- [managing stacked and parallel branches](cli-guides/cli-tutorial/branching-and-commiting) +- [inspecting and diffing](cli-guides/cli-tutorial/inspecting) +- [an operations log and restoration of older states](cli-guides/cli-tutorial/operations-log) +- [powerful commit editing](cli-guides/cli-tutorial/rubbing) +- [upstream management](cli-guides/cli-tutorial/updating-the-base) +- [conflict resolution](cli-guides/cli-tutorial/conflict-resolution) +- [working with forges](cli-guides/cli-tutorial/forges) +- [aliases and configuration](cli-guides/cli-tutorial/configuration) - -You can find the download links and changelogs for the latest releases on our [GitHub Releases](https://github.com/gitbutlerapp/gitbutler/releases). - +All with a simple command line tool. -## Platforms +## Quick Reference -We bundle and ship GitButler for Mac OS, Windows, and Linux. +For a quick reference of the most commonly used commands, check out our [**GitButler CLI Cheat Sheet**](/cli/cheat) - available as a web page or downloadable PDF. -### Windows +## Getting Started -| Arch | Format | In-app updater | -| --- | --- | --- | -| `x86_64` | `msi` | | +Feel free to get started with our [Tutorial](cli-guides/installation) or just dig into the available commands. -### Mac OS -| Arch | Format | In-app updater | -| --- | --- | --- | -| `x86_64` | `dmg` | | -| `arm64` | `dmg` | | +# fetch-push.mdx -### Linux -| Arch | Format | In-app updater | -| --- | --- | --- | -| `x86_64` | `deb` | | -| `x86_64` | `rpm` | | -| `x86_64` | `AppImage` | | +If you are having trouble pushing or fetching from a remote, this is likely related to git authentication. Here are a few configuration options you can try out, found in the project settings. -> Support for the Linux releases are complicated a bit through a core dependency of our framework, `libwebkit2gtk`, which is used to provide the web view on Linux. Tauri v1 required `libwebkit2gtk-4.0` which is not available in Ubuntu 24.04 or Debian 13 and newer. -> -> We've recently upgraded to Tauri v2 (as of Nightly `0.5.845` and Release `0.13.9`), and it now requires `libwebkit2gtk-4.1`. This version of the package is not available in the repositories for Ubuntu 20.04 and older as well as Debian 11 and older. -> -> For more information, check out the [pinned issue](https://github.com/tauri-apps/tauri/issues/9662) in the Tauri repository. +## Configuring the auto-fetch frequency +GitButler will periodically fetch from your configured remotes in order to display new branches etc. By default, this happens every every 15 minutes. -# workspace-branch.mdx +You can configure the interval or completely disable this behavior by editing the application's `settings.json` file: -If you run some normal Git commands (like `git log`) while in GitButler mode, you'll see a few special branches that GitButler maintains behind the scenes. The one that most people get confused by is the `gitbutler/workspace` commit. + + ```bash ~/Library/Application\ Support/gitbutler/settings.json ``` + ```bash C:\Users\[username]\AppData\Roaming\gitbutler\settings.json ``` + ```bash ~/.config/gitbutler/settings.json ``` + -There are a few different reasons that we need it, so let's take a quick look. +The file is in JSONC format and follows the [following schema](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but-settings/assets/defaults.jsonc) -If you run a normal `git log` on a GitButler managed repository, you will see something like this: +```json + "fetch": { + "autoFetchIntervalMinutes": 15 + } +``` -```git -commit de56d20e282f7641d48d288b510141996c3c3cfc (HEAD -> gitbutler/workspace) -Author: GitButler -Date: Wed Sep 9 09:06:03 2020 +0800 +A negative value (e.g. -1) disables auto fetching. Note that if `fetch` is the only entry in the JSON file, you may want to enclose it in a top-level object. - GitButler Workspace Commit +## Available authentication methods - This is is a merge commit of the parallel branches in your workspace. +GitButler can be configured to use several different git authentication methods. You can switch between them in your project settings. You can try multiple different options and see if any of them are appropriate for your setup. Note that if you are on Windows, the only applicable method is the "Git executable", therefore the application will now show this as a configuration option. - For GitButler to manage multiple parallel branches, we maintain - this commit automatically so other tooling works properly. + - If you switch to another branch, GitButler will need to be - reinitialized. +### Use a Git executable (default) - Here are the branches that are currently applied: +The default way to push and fetch is for GitButler to use an existing system Git executable. This should use whatever authentication mechanism that Git uses for the remote that you're trying to push to or fetch from. - - update-homepage (refs/gitbutler/update-homepage) - branch head: a32f33273948837078e5f5a4e1677ab6274a4629 +### Use an existing SSH key - For more information about what we're doing here, check out our docs: - https://docs.gitbutler.com/workspace-branch +If already have an SSH key set up (eg. `~/.ssh/id_rsa`), you can instruct GitButler to use it. In case the key is password protected, you can also provide the password to it (which will be stored locally). -commit a32f33273948837078e5f5a4e1677ab6274a4629 (update-homepage) -Author: Scott Chacon -Date: Mon Jan 26 07:33:31 2026 +0500 +### Use locally generated SSH key - hero update - new branding +This option generates a new SSH key which will be stored locally in the application [data dir](https://docs.gitbutler.com/development/debugging#data-files). For this to work you will need to add the new public key to your Git remote provider. -``` +### Use a git credential helper -That first commit is a merge commit that we rebuild as you modify branches in GitButler. The reason that it exists is mainly because if you have more than one branch applied in your workspace, when other tools run `git status`, it will look strange, since Git has no concept of having several branches applied at once. +If your system is set up with a credential helper, GitButler can use that. For more info on git credential helpers, see this [article](https://git-scm.com/doc/credential-helpers). -## Status, Diff and Log +### FIDO security keys (YubiKey, etc.) -To keep Git command output for things that look at the index and HEAD (such as status or diff) somewhat sane, we modify your index to look like the union of all the committed states of all your applied parallel branches. This makes git diff and git status behave more or less like you would expect. +If you're using a FIDO key, check out this issue to see how people have set it up with the Git executable method: [#2661](https://github.com/gitbutlerapp/gitbutler/issues/2661) -For instance, if you have two files on Branch A and two files on Branch B, then git status will simply list four files as modified. +### Keys managed by 1Password -If you run git log, the first commit should be our custom commit message and the tree of that commit is the union of all the committed work on all your applied parallel branches, as though they were all merged together into one (something stock Git can understand). +Keys stored in 1Password should properly use it as an SSH agent for authentication and signing commits if you use the Git executable option. (Previously tracked in [#2779](https://github.com/gitbutlerapp/gitbutler/issues/2779)) -## Committing, Branching, Checking Out +### Host certificate checks -However, if you try to use something that writes to HEAD, like git commit or git checkout, then you might have some headaches. For this reason, we install custom Git hooks for `pre-commit` and `post-checkout` that will protect this from happening. +There is an option to ignore host certificate checks when authenticating with ssh. This may be a helpful option to enable in some cases. -If you try to commit when in GitButler managed mode, the `pre-commit` hook should disallow it and tell you how to fix it. +## Other known issues -```git -❯ git commit -am 'commit on the workspace branch' +### Git remote servers with a non-standard SSH port +In some cases, the git remote may be setup on a port number other than 22. If the port is set in your `~/.ssh/config` file, GitButler will not be able to recognize that - tracked in GitHub issue [#2700](https://github.com/gitbutlerapp/gitbutler/issues/2700). -GITBUTLER_ERROR: Cannot commit directly to gitbutler/workspace branch. +As a workaround you may set your remote in the [SSH format](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols) (eg. `ssh://git@example.com:3022/foo/bar.git`) -GitButler manages commits on this branch. Please use GitButler to commit your changes: - - Use the GitButler app to create commits - - Or run 'but commit' from the command line +Updating parallel branches when the respective remote has new commits +If you have added a remote branch to your active workspace in GitButler, or pushed a virtual branch to the remote, and new commits are added to the remote branch, there is currently no way to sync those new commits into the existing virtual branch in GitButler. This is being tracked in the GitHub issue [#2649](https://github.com/gitbutlerapp/gitbutler/issues/2649). -If you want to exit GitButler mode and use normal git: - - Run 'but teardown' to switch to a regular branch - - Or directly checkout another branch: git checkout +The current workaround is to undo any local commits and then stash your local changes manually using [git stash](https://git-scm.com/docs/git-stash) and then delete the virtual branch that has upstream changes. Then you can update the trunk by clicking the update button next to the word "Trunk" in the sidebar on the left to make sure all new upstream changes are synced, then select the remote branch that has the new changes and click the "Apply +" button above the list of commits for the branch. Once the updated branch is applied to your working directory, you can manually `git stash pop` your stashed changes and then resolve any merge conflicts. -If you no longer have the GitButler CLI installed, you can simply remove this hook and checkout another branch: - rm ".git/hooks/pre-commit" -``` +### OAuth app access restrictions on your GitHub organization -If you want to get out of this mode, you can follow any of those instructions. The easiest is running `but teardown`, but simply switching directly to a normal Git branch will also do the trick. +If you're submitting code and PRs to a repository under an organization on GitHub, you may receive an error that, despite having correct authorization credentials, your organization has enabled OAuth app access restrictions. These restrictions are an organization-level security feature designed to prevent unauthorized third-party applications from accessing organization resources. + +To solve this, go to Applications. Select the "Authorized OAuth Apps" tab, and look for "GitButler Client". If you don't find "GitButler Client", it's possible you haven't yet set GitButler up for personal use. If so, try creating a test commit on a test branch for a personal repository using GitButler, which you can delete after, then check the same tab as before. + +If you see "GitButler Client", click on it and, under "Organization Access", across from the organization you wish to enable GitButler for, click either the "Request" or "Grant" button, depending on whether you are a contributor or owner, respectively. If you're a contributor clicking "Request", note that you'll need to wait for an organization owner to approve your access request before you can proceed. + +Note for organization owners: To streamline this process for your team members, you can pre-approve GitButler for all organization members. This eliminates the need for individual access requests and approvals. This can be managed through your organization's OAuth app access settings. + +### Help on Discord +If none of the available options helps, feel free to hop on our [Discord](https://discord.gg/MmFkmaJ42D) and we will be happy to help you out. + + + +# coding-agents.mdx + + +GitButler can also orchestrate your coding agents and help automatically manage, checkpoint and commit the work that they do for you. + + + Currently the only supported agent is [Claude Code](https://www.anthropic.com/claude-code), but we + are working on more agent support. + + +You can start a session by clicking the AI stars on a branch header, or use the shortcut for a new branch and AI session in the top right corner of the window. + + + +Each session is tied to a branch such that you can run them in parallel, and changes are assigned to the respective branch as long as they are mutually exclusive. Information about the branch is also added to the respective context, giving the agent knowledge of the work they contain. + +# Setup + +There is some basic setup that may need to be done the first time, if you've never used Claude Code before. + +### Installing Claude Code + +Before you can use the agents integration, you need to have Claude Code installed as we wrap the SDK that it provides. If we can't find the binary, you should see something like this: + + + +To install Claude Code, you can read through the docs [here](https://docs.anthropic.com/en/docs/claude-code/quickstart), but the simple version is to use their "Native Install" method: + +{/* */} + + + + ```bash + curl -fsSL https://claude.ai/install.sh | bash + ``` + + + ```bash + irm https://claude.ai/install.ps1 | iex + ``` + + + ```bash + curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del + install.cmd + ``` + + +{/* */} + +You will then need to setup and login to Claude Code, which will require an Anthropic account. You can either connect it to an API key for direct billing or use one of the plans. You can learn more on the [Claude Code](https://www.anthropic.com/claude-code) page. + + + GitButler does not charge you for agent use, but Anthropic does. This goes directly through Claude + Code usage, we simply help manage the agent. + + +# Generating Code with an Agent + +Once your agent is setup, you can select a branch to work on, type in a prompt and we will run that though Claude Code, same as if you ran it in the terminal. + + + +While this is still running Claude Code, running through the GitButler UI will make sure that each agent works on the branch it is attached to. You can run multiple agents at once, each committing to their attached branches. + +### Model Selection + +There are a few different models that you can choose from for running your task. You can change your active model in the model selection dialog of the chat box. + + + +### Thinking Modes + +Claude Code also allows for selection of a "thinking mode". The lower modes are faster, the higher modes tend to take longer and be more expensive, but can produce better results. + + + +### Prompt Templates + +If you find that you're using similar prompts over and over, you can easily setup several prompt templates. Selecting one will seed the prompt with the contents of that template. + + + +You can also edit your available templates by selecting the "Edit templates" option, which opens up our JSON file in your editor of choice. The templates look something like this: + +````json +{ + "templates": [ + { + "label": "Bug Fix", + "template": "Please fix the bug in this code:\n\n```\n// Your code here\n```\n\nExpected behavior:\nActual behavior:\nSteps to reproduce:" + }, + { + "label": "Code Review", + "template": "Please review this code for:\n- Performance issues\n- Security vulnerabilities\n- Best practices\n- Code style\n\n```\n// Your code here\n```" + }, + { + "label": "Refactor", + "template": "Please refactor this code to improve:\n- Readability\n- Performance\n- Maintainability\n\n```\n// Your code here\n```\n\nRequirements:" + }, + { + "label": "Add Tests", + "template": "Please write comprehensive tests for this code:\n\n```\n// Your code here\n```\n\nTest cases should cover:\n- Happy path\n- Edge cases\n- Error conditions" + } + ] +} +```` + +### Context Clearing + +After a while, your context in a single branch can get long. If you no longer need all the context but want to keep your agent working on the same branch, you can clear it with the "Clear Context" button in the context menu. # custom-csp.mdx @@ -616,95 +947,246 @@ Note that if `extraCsp` is the only entry in the JSON file, you may want to encl The changes will take effect the next time you start GitButler. -# fetch-push.mdx - +# recovering-stuff.mdx -If you are having trouble pushing or fetching from a remote, this is likely related to git authentication. Here are a few configuration options you can try out, found in the project settings. -## Configuring the auto-fetch frequency +How to dig around our internal data to find (nearly) anything -GitButler will periodically fetch from your configured remotes in order to display new branches etc. By default, this happens every every 15 minutes. +GitButler saves data in a few different ways. As we're still in beta, sometimes things might break and it may look like you've lost work, but you almost certainly haven't. We're pretty good about saving stuff a lot. Here's how to recover almost anything you had in your working directory or parallel branches. -You can configure the interval or completely disable this behavior by editing the application's `settings.json` file: +## GitButler References - - ```bash ~/Library/Application\ Support/gitbutler/settings.json ``` - ```bash C:\Users\[username]\AppData\Roaming\gitbutler\settings.json ``` - ```bash ~/.config/gitbutler/settings.json ``` - +If everything crashes or the UI isn't working at all, you may be surprised to know that even though your parallel branches don't show up in a normal git branch output, we do actually constantly write them out as Git references (just not in refs/heads). -The file is in JSONC format and follows the [following schema](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but-settings/assets/defaults.jsonc) -```json - "fetch": { - "autoFetchIntervalMinutes": 15 - } +```bash title="Terminal" +❯ git for-each-ref | grep gitbutler +e63b3bac82835dc17083a785d25db8b4b46744b9 commit refs/gitbutler/add-can-create-method-to-notebook +98ef3cd6eea14ee4159a600e448271c0d777efe2 commit refs/gitbutler/add-conditional-blocks-for-image-and-video +c7e27b9f99f25160a4d5f07d5972c217bdd44319 commit refs/gitbutler/add-database-schema-conversion-script +4afdfed6c14b57491a9d295c31613fd79b92f63a commit refs/gitbutler/add-gems-for-test-group ``` -A negative value (e.g. -1) disables auto fetching. Note that if `fetch` is the only entry in the JSON file, you may want to enclose it in a top-level object. -## Available authentication methods +These references are just like git branches - they point to a commit that has the latest version of your branch. You can create other git branches off of them, you can push them to GitHub, etc. -GitButler can be configured to use several different git authentication methods. You can switch between them in your project settings. You can try multiple different options and see if any of them are appropriate for your setup. Note that if you are on Windows, the only applicable method is the "Git executable", therefore the application will now show this as a configuration option. +You will have one for each virtual branch (applied or unapplied) that you've created (that you haven't deleted). + +If you've committed everything on a virtual branch, the reference will just point to the latest commit. If you have work in progress on the branch, it will point to a WIP commit that includes those changes. + +So for example, if I have the following two parallel branches, one fully committed and one with work pending: -### Use a Git executable (default) -The default way to push and fetch is for GitButler to use an existing system Git executable. This should use whatever authentication mechanism that Git uses for the remote that you're trying to push to or fetch from. +I can view the git branches like this: -### Use an existing SSH key +```bash title="Terminal" +❯ git show gitbutler/Convert-tables-to-utf8mb4 +commit 841e4db701ca41206c03f1f4fe345f7e27d05eab +Author: Scott Chacon +Date: Fri Feb 23 10:30:17 2024 +0100 -If already have an SSH key set up (eg. `~/.ssh/id_rsa`), you can instruct GitButler to use it. In case the key is password protected, you can also provide the password to it (which will be stored locally). + my latest commit -### Use locally generated SSH key +❯ git show gitbutler/Add-database-schema-conversion-script +commit d95e7f4da1611ea6bb8a80da06e66ca923fbff55 +Author: GitButler +Date: Fri Feb 23 10:30:18 2024 +0100 -This option generates a new SSH key which will be stored locally in the application [data dir](https://docs.gitbutler.com/development/debugging#data-files). For this to work you will need to add the new public key to your Git remote provider. + GitButler WIP Commit -### Use a git credential helper + This is a WIP commit for the virtual branch 'Add database schema conversion script' -If your system is set up with a credential helper, GitButler can use that. For more info on git credential helpers, see this [article](https://git-scm.com/doc/credential-helpers). + This commit is used to store the state of the virtual branch + while you are working on it. It is not meant to be used for + anything else. +``` -### FIDO security keys (YubiKey, etc.) +See how the `Add-database-schema-conversion-script` reference points to a "WIP commit"? The tree of that commit has all those changed files in it as though we had committed them. -If you're using a FIDO key, check out this issue to see how people have set it up with the Git executable method: [#2661](https://github.com/gitbutlerapp/gitbutler/issues/2661) +If you don't want to search through all your refs with `for-each-refs`, you can also just run a normal `git log` command and we'll show you what references we've written and which modified files are in each one: -### Keys managed by 1Password +```bash title="Terminal" +❯ git log +commit 2d8afe0ea811b5f24b9a6f84f6d024bb323a2db5 (HEAD -> gitbutler/workspace) +Author: GitButler +Date: Fri Feb 23 10:30:18 2024 +0100 -Keys stored in 1Password should properly use it as an SSH agent for authentication and signing commits if you use the Git executable option. (Previously tracked in [#2779](https://github.com/gitbutlerapp/gitbutler/issues/2779)) + GitButler Integration Commit -### Host certificate checks + This is an integration commit for the parallel branches that GitButler is tracking. -There is an option to ignore host certificate checks when authenticating with ssh. This may be a helpful option to enable in some cases. + Due to GitButler managing multiple parallel branches, you cannot switch back and + forth between git branches and parallel branches easily. -## Other known issues + If you switch to another branch, GitButler will need to be reinitialized. + If you commit on this branch, GitButler will throw it away. -### Git remote servers with a non-standard SSH port -In some cases, the git remote may be setup on a port number other than 22. If the port is set in your `~/.ssh/config` file, GitButler will not be able to recognize that - tracked in GitHub issue [#2700](https://github.com/gitbutlerapp/gitbutler/issues/2700). + Here are the branches that are currently applied: + - Add database schema conversion script (refs/gitbutler/Add-database-schema-conversion-script) + - butler/Gemfile + - butler/README.md + - butler/db/schema.rb + - butler/db/migrate/20240209144600_change_mysql_charset.rb + - .pscale.yml + - Convert tables to utf8mb4 (refs/gitbutler/Convert-tables-to-utf8mb4) + branch head: 841e4db701ca41206c03f1f4fe345f7e27d05eab + - butler/create_column_conversions.rb -As a workaround you may set your remote in the [SSH format](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols) (eg. `ssh://git@example.com:3022/foo/bar.git`) + Your previous branch was: refs/heads/sc-branch-comments -Updating parallel branches when the respective remote has new commits -If you have added a remote branch to your active workspace in GitButler, or pushed a virtual branch to the remote, and new commits are added to the remote branch, there is currently no way to sync those new commits into the existing virtual branch in GitButler. This is being tracked in the GitHub issue [#2649](https://github.com/gitbutlerapp/gitbutler/issues/2649). + The sha for that commit was: 5e16e99667db9d26f78110df807853a896120ff3 -The current workaround is to undo any local commits and then stash your local changes manually using [git stash](https://git-scm.com/docs/git-stash) and then delete the virtual branch that has upstream changes. Then you can update the trunk by clicking the update button next to the word "Trunk" in the sidebar on the left to make sure all new upstream changes are synced, then select the remote branch that has the new changes and click the "Apply +" button above the list of commits for the branch. Once the updated branch is applied to your working directory, you can manually `git stash pop` your stashed changes and then resolve any merge conflicts. + For more information about what we're doing here, check out our docs: + https://docs.gitbutler.com/features/branch-management/integration-branch +``` -### OAuth app access restrictions on your GitHub organization +You can see the two `gitbutler` refs under the "Here are the branches that are currently applied" section. -If you're submitting code and PRs to a repository under an organization on GitHub, you may receive an error that, despite having correct authorization credentials, your organization has enabled OAuth app access restrictions. These restrictions are an organization-level security feature designed to prevent unauthorized third-party applications from accessing organization resources. +Again, these are real git refs, just not under `refs/heads` so that we don't pollute your `git branch` output. But if GitButler crashes at some point, you can still push them to GitHub or whatever you want. Here is an example pushing my virtual branch to a GitHub branch called `convert-tables`: -To solve this, go to Applications. Select the "Authorized OAuth Apps" tab, and look for "GitButler Client". If you don't find "GitButler Client", it's possible you haven't yet set GitButler up for personal use. If so, try creating a test commit on a test branch for a personal repository using GitButler, which you can delete after, then check the same tab as before. +```bash title="Terminal" +❯ git push origin refs/gitbutler/Convert-tables-to-utf8mb4:refs/heads/convert-tables +Enumerating objects: 6, done. +Counting objects: 100% (6/6), done. +Delta compression using up to 10 threads +Compressing objects: 100% (4/4), done. +Writing objects: 100% (4/4), 474 bytes | 474.00 KiB/s, done. +Total 4 (delta 2), reused 1 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (2/2), completed with 2 local objects. +remote: +remote: Create a pull request for 'convert-tables' on GitHub by visiting: +remote: https://github.com/gitbutlerapp/web/pull/new/convert-tables +remote: +To github.com:gitbutlerapp/web.git + * [new branch] refs/gitbutler/Convert-tables-to-utf8mb4 -> convert-tables +``` -If you see "GitButler Client", click on it and, under "Organization Access", across from the organization you wish to enable GitButler for, click either the "Request" or "Grant" button, depending on whether you are a contributor or owner, respectively. If you're a contributor clicking "Request", note that you'll need to wait for an organization owner to approve your access request before you can proceed. +## GitButler Operations Log -Note for organization owners: To streamline this process for your team members, you can pre-approve GitButler for all organization members. This eliminates the need for individual access requests and approvals. This can be managed through your organization's OAuth app access settings. +Ok, let's say that your work was not in one of those refs for some reason. Maybe you hit some weird bug and it completely changed everything in a way where now you're sitting on the couch in the dark with a glass of whisky, slowly mumbling the word "GitButler..." and plotting your revenge. -### Help on Discord -If none of the available options helps, feel free to hop on our [Discord](https://discord.gg/MmFkmaJ42D) and we will be happy to help you out. +Most of the time, we'll have whatever you're looking for in our operations log. + +The easiest way to access this is to use the built in Project History UI: [Project History](/features/timeline) + +However, let's dig into how this works, just in case you want to check it out yourself. + +Every time that GitButler does some possibly data-changing operation, we store a snapshot of your project state in our operations log before the operation happens so you can undo it if you want to. This is stored as a Git commit history that is parallel to your projects (ie, no common parents). + +You can inspect this by looking at the `.git/gitbutler/operations-log.toml` file. + +```bash title="Terminal" +❯ tree .git/gitbutler +.git/gitbutler +├── operations-log.toml +└── virtual_branches.toml + +1 directory, 2 files + +❯ cat .git/gitbutler/operations-log.toml +head_sha = "16e47cb1d091ca9dd44327fef2f5305b09403a95" + +[modified_at] +secs_since_epoch = 1717663406 +nanos_since_epoch = 560458000 +``` + +If we look at this commit, we can see the history of all of the project history snapshots that GitButler is keeping: + +```bash title="Terminal" +❯ git log 16e47cb1d091ca9dd44327fef2f5305b09403a9 -2 +commit 16e47cb1d091ca9dd44327fef2f5305b09403a95 +Author: GitButler +Date: Thu Jun 6 10:43:26 2024 +0200 + + CreateBranch + + Version: 1 + Operation: CreateBranch + name: Virtual branch + +commit 2c95aa06d76b3230f1a51d9f89a211770d93ae51 +Author: GitButler +Date: Thu Jun 6 10:28:30 2024 +0200 + + UpdateWorkspaceBase + + Version: 1 + Operation: UpdateWorkspaceBase +``` + +You can see that before creating a branch or updating our workspace with upstream work, we're recording the state of our project so we have an undo point. So what data are we keeping here in addition to this trailer information? + +Let's look at the tree of one of these commits: + +```bash title="Terminal" +❯ git cat-file -p 16e47cb1d091ca9dd44327fef2f5305b09403a95^{tree} +040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 conflicts +040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 index +040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 target_tree +100644 blob d839dca7e14f5833ad737b4adbf337bd20489927 virtual_branches.toml +040000 tree a0821552c0e7d5defe369d577af5e3a87b442469 virtual_branches +``` + +The parallel branches toml file has the interesting metadata: + +```bash title="Terminal" +❯ git cat-file -p 16e47cb1d091ca9dd44^{tree}:virtual_branches.toml +[default_target] +branchName = "master" +remoteName = "origin" +remoteUrl = "git@github.com:gitbutlerapp/gitbutler.git" +sha = "e00e54af7f903ef84600079a45490a7f07e4702e" +pushRemoteName = "origin" + +[branch_targets] + +[branches.09ef54c4-1081-4a52-8182-a5ec725016b6] +id = "09ef54c4-1081-4a52-8182-a5ec725016b6" +name = "commit signing settings" +notes = "" +applied = false +upstream = "refs/remotes/origin/commit-signing-settings" +upstream_head = "b60a66452dfecef74103346af6a3291ad677d246" +created_timestamp_ms = "1717489406268" +updated_timestamp_ms = "1717489406268" +tree = "b28e7eefdd7b6f36456516b696146a2ea7638ca4" +head = "b60a66452dfecef74103346af6a3291ad677d246" +ownership = "" +order = 4 +selected_for_changes = 1717489406268 +``` + +The virtual_branches tree has the actual contents of those computed branches in case we need to recreate them: + + + + + + + + + + + + + + + + + + + + + + +This allows you to get contents of any file in any of your virtual branch states as well. # fixing-conflicts-outside-gitbutler.mdx @@ -913,501 +1395,56 @@ Once you have finished bringing all of your commits into your reconstruction branch, you can then push it to your remote via `git push`. -# why-gitbutler.mdx - -The GitButler manifesto, as it were. - -Everyone loves a good manifesto. So, why is there a need for a new Git client in the world? Don't we have enough? Isn't the command line just fine? - -Having cofounded GitHub, trained dozens of corporate teams on distributed version control tools and literally written the book on Git, we have spent a lot of time and energy over the last decade thinking about the source code management tools that software developers use every day. - -GitHub has changed the way that millions of developers across the world collaborate and work with their source code, but as sophisticated and user friendly as that tool is in our daily coding lives, using GitHub or GitLab or Bitbucket still requires all of those developers to work with a command line tool that is confusing, difficult to use, error prone and not originally designed or built for the workflows and processes that most developers today use. That tool is Git. - -Sure, some small minority will use a GUI of some sort, but even those tools are mostly wrappers around the core concepts of Git itself, never reimagining what source code management could be or if Git itself is actually good at helping them with the tasks they face on a daily basis. I've never personally used one because they do little that Git itself doesn't and honestly it's generally easier to just do those tasks on the command line, where it's quick and efficient and I don't have to take my hands off the keyboard. - -But what if we broke down everything that you try to accomplish with Git, with source code management tools in general, reduce them down to first principles and imagine a tool that does all of those things better? Are you using Git because it's the best way you can imagine accomplishing those tasks, or are you using it because it's what is there, it's what works with GitHub, it's the only real option? - -The reality is that source code management tools have changed very little on a fundamental level in the last 40 years. If you look at the tools and commands and interface that RCS had in the 80s, or Subversion had in the 90s, is it really massively different than how you use Git today on a daily basis? - -Yes, Git has easy branching, acceptable merging, a nice network transport method to move your code around, but you're still making manual checkins, you're still trying to remember obscure arguments, you're still losing work when things get complicated. - -GitButler is rethinking everything between when you write code in your editor of choice and when you push that code to GitHub for review. Why are you making 'wip' commits when your SCM should be recording everything for you? Why are everyone's commit messages close to useless? Why is `git blame` the best way to get context on the code your team has written? Why can't you seamlessly transition work between computers? +# timeline.mdx -We are creating not only a new kind of Git client, but an entirely new way of thinking about managing the code that you work on. A tool that helps you at every step of the software development process. A code concierge, hard at work for you to ensure that you'll never lose a moment of work again. That you'll have all the context and support you'll need around every line of code you work on. -Managing your source code can be different, smarter, leaps ahead of the 40 year old concepts that we're using today. +Undo nearly any of your actions or go back in time to an earlier state. -Our goal is to make sure that nobody ever has to read Scott's book again. That you don't have to learn how to manage your source code management tool. +## How it works - +Before GitButler does any major action, it records the state of everything (your virtual branch state, your uncommitted work, conflict state, etc) and stores it in your Git object database as snapshots. You can hit the 'revert' button on any of the entries and it will restore the state of all of these things to what they looked like when they were recorded, letting you go back in time. + -# gerrit-mode.mdx +## Restoring State -Not _everyone_ uses GitHub or GitLab to review code and collaborate. If you use the [Gerrit](https://www.gerritcodereview.com/) code review tool, GitButler has a mode for you! In fact, GitButler is the best Gerrit client there is. +If you hover over any of the entries, you will see a button named "Revert" that will restore the state of things to right before you did that action. So if you revert one that says "Create Commit", it will put you where you were right before you made that commit. -## What is Gerrit + -If you've never heard of Gerrit, it's used by large teams like the Android or Chrome projects to manage huge numbers of changes and users across large numbers of interdependent repositories. +## Recovering Content -Here is an example of incoming changesets on the [Android project](https://android-review.googlesource.com/q/status:open+-is:wip,50): +Occasionally, GitButler will also take snapshots of files that were changed recently, even if they weren't committed. If this, or any other action, sees changes in files, you can see which ones and view the change by clicking on the file name. -## How is Gerrit different than Pull/Merge Requests? -Good question. With GitHub or GitLab, when you send a pull/merge request, the review process is branch based. If you add more commits on top of your branch, the changes are squashed into one big unified diff for review. Most teams tend to avoid rebasing anything that was already shared. +# gitlab-integration.mdx -Gerrit is a commit based review system. Every review is based on exactly one commit. It's very common to edit shared commits and submit new versions of them to address feedback. -This model works _very well_ with GitButler's easy [commit editing](/features/branch-management/commits) features. With any other Git client, interactive rebasing and amending tends to be quite painful and error prone, making it fairly difficult to work with Gerrit's model. With GitButler, it's ideal. Just drag and drop changes and update your changesets easily. +Create your GitLab Merge requests without leaving GitButler. -## How to turn on Gerrit Mode +## Setting up the GitLab Integration -If you have a Gerrit remote, GitButler will automatically enable Gerrit Mode when the project is being added to GitButler. You can also enable it manually. -To manually turn on Gerrit Mode in GitButler, you just have to set a Git config option called `gitbutler.gerritMode` in the project you want to act in a Gerrit compatible fashion: - -``` -❯ cd my_project -❯ git config gitbutler.gerritMode 1 -``` - -## What is Gerrit Mode - -Now GitButler will change its behavior in the following ways: - -- When you commit, we will automatically inject a `Change-Id` trailer into the commit in the format that Gerrit expects. You do not need to [setup a `commit-msg` hook](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) like you do with other Git clients. -- When you push, it will not push to a matching branch name on the remote. Instead it will push to `refs/for/main` (or whatever the name of the target branch is set to be). -- After a push, we record the change url and show you the link and number for each commit automatically. - - - -We can also set some extra push options when we push, including: - -- [Topics](https://gerrit-review.googlesource.com/Documentation/cross-repository-changes.html) -- [Hashtags](https://gerrit-review.googlesource.com/Documentation/intro-user.html#hashtags) -- [WIP status](https://gerrit-review.googlesource.com/Documentation/intro-user.html#wip) - - - - -# coding-agents.mdx - - -GitButler can also orchestrate your coding agents and help automatically manage, checkpoint and commit the work that they do for you. - - - Currently the only supported agent is [Claude Code](https://www.anthropic.com/claude-code), but we - are working on more agent support. - - -You can start a session by clicking the AI stars on a branch header, or use the shortcut for a new branch and AI session in the top right corner of the window. - - - -Each session is tied to a branch such that you can run them in parallel, and changes are assigned to the respective branch as long as they are mutually exclusive. Information about the branch is also added to the respective context, giving the agent knowledge of the work they contain. - -# Setup - -There is some basic setup that may need to be done the first time, if you've never used Claude Code before. - -### Installing Claude Code - -Before you can use the agents integration, you need to have Claude Code installed as we wrap the SDK that it provides. If we can't find the binary, you should see something like this: - - - -To install Claude Code, you can read through the docs [here](https://docs.anthropic.com/en/docs/claude-code/quickstart), but the simple version is to use their "Native Install" method: - -{/* */} - - - - ```bash - curl -fsSL https://claude.ai/install.sh | bash - ``` - - - ```bash - irm https://claude.ai/install.ps1 | iex - ``` - - - ```bash - curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del - install.cmd - ``` - - -{/* */} - -You will then need to setup and login to Claude Code, which will require an Anthropic account. You can either connect it to an API key for direct billing or use one of the plans. You can learn more on the [Claude Code](https://www.anthropic.com/claude-code) page. - - - GitButler does not charge you for agent use, but Anthropic does. This goes directly through Claude - Code usage, we simply help manage the agent. - - -# Generating Code with an Agent - -Once your agent is setup, you can select a branch to work on, type in a prompt and we will run that though Claude Code, same as if you ran it in the terminal. - - - -While this is still running Claude Code, running through the GitButler UI will make sure that each agent works on the branch it is attached to. You can run multiple agents at once, each committing to their attached branches. - -### Model Selection - -There are a few different models that you can choose from for running your task. You can change your active model in the model selection dialog of the chat box. - - - -### Thinking Modes - -Claude Code also allows for selection of a "thinking mode". The lower modes are faster, the higher modes tend to take longer and be more expensive, but can produce better results. - - - -### Prompt Templates - -If you find that you're using similar prompts over and over, you can easily setup several prompt templates. Selecting one will seed the prompt with the contents of that template. - - - -You can also edit your available templates by selecting the "Edit templates" option, which opens up our JSON file in your editor of choice. The templates look something like this: - -````json -{ - "templates": [ - { - "label": "Bug Fix", - "template": "Please fix the bug in this code:\n\n```\n// Your code here\n```\n\nExpected behavior:\nActual behavior:\nSteps to reproduce:" - }, - { - "label": "Code Review", - "template": "Please review this code for:\n- Performance issues\n- Security vulnerabilities\n- Best practices\n- Code style\n\n```\n// Your code here\n```" - }, - { - "label": "Refactor", - "template": "Please refactor this code to improve:\n- Readability\n- Performance\n- Maintainability\n\n```\n// Your code here\n```\n\nRequirements:" - }, - { - "label": "Add Tests", - "template": "Please write comprehensive tests for this code:\n\n```\n// Your code here\n```\n\nTest cases should cover:\n- Happy path\n- Edge cases\n- Error conditions" - } - ] -} -```` - -### Context Clearing - -After a while, your context in a single branch can get long. If you no longer need all the context but want to keep your agent working on the same branch, you can clear it with the "Clear Context" button in the context menu. - - -# recovering-stuff.mdx - - -How to dig around our internal data to find (nearly) anything - -GitButler saves data in a few different ways. As we're still in beta, sometimes things might break and it may look like you've lost work, but you almost certainly haven't. We're pretty good about saving stuff a lot. Here's how to recover almost anything you had in your working directory or parallel branches. - -## GitButler References - -If everything crashes or the UI isn't working at all, you may be surprised to know that even though your parallel branches don't show up in a normal git branch output, we do actually constantly write them out as Git references (just not in refs/heads). - - -```bash title="Terminal" -❯ git for-each-ref | grep gitbutler -e63b3bac82835dc17083a785d25db8b4b46744b9 commit refs/gitbutler/add-can-create-method-to-notebook -98ef3cd6eea14ee4159a600e448271c0d777efe2 commit refs/gitbutler/add-conditional-blocks-for-image-and-video -c7e27b9f99f25160a4d5f07d5972c217bdd44319 commit refs/gitbutler/add-database-schema-conversion-script -4afdfed6c14b57491a9d295c31613fd79b92f63a commit refs/gitbutler/add-gems-for-test-group -``` - - -These references are just like git branches - they point to a commit that has the latest version of your branch. You can create other git branches off of them, you can push them to GitHub, etc. - -You will have one for each virtual branch (applied or unapplied) that you've created (that you haven't deleted). - -If you've committed everything on a virtual branch, the reference will just point to the latest commit. If you have work in progress on the branch, it will point to a WIP commit that includes those changes. - -So for example, if I have the following two parallel branches, one fully committed and one with work pending: - - - - -I can view the git branches like this: - -```bash title="Terminal" -❯ git show gitbutler/Convert-tables-to-utf8mb4 -commit 841e4db701ca41206c03f1f4fe345f7e27d05eab -Author: Scott Chacon -Date: Fri Feb 23 10:30:17 2024 +0100 - - my latest commit - -❯ git show gitbutler/Add-database-schema-conversion-script -commit d95e7f4da1611ea6bb8a80da06e66ca923fbff55 -Author: GitButler -Date: Fri Feb 23 10:30:18 2024 +0100 - - GitButler WIP Commit - - This is a WIP commit for the virtual branch 'Add database schema conversion script' - - This commit is used to store the state of the virtual branch - while you are working on it. It is not meant to be used for - anything else. -``` - -See how the `Add-database-schema-conversion-script` reference points to a "WIP commit"? The tree of that commit has all those changed files in it as though we had committed them. - -If you don't want to search through all your refs with `for-each-refs`, you can also just run a normal `git log` command and we'll show you what references we've written and which modified files are in each one: - -```bash title="Terminal" -❯ git log -commit 2d8afe0ea811b5f24b9a6f84f6d024bb323a2db5 (HEAD -> gitbutler/workspace) -Author: GitButler -Date: Fri Feb 23 10:30:18 2024 +0100 - - GitButler Integration Commit - - This is an integration commit for the parallel branches that GitButler is tracking. - - Due to GitButler managing multiple parallel branches, you cannot switch back and - forth between git branches and parallel branches easily. - - If you switch to another branch, GitButler will need to be reinitialized. - If you commit on this branch, GitButler will throw it away. - - Here are the branches that are currently applied: - - Add database schema conversion script (refs/gitbutler/Add-database-schema-conversion-script) - - butler/Gemfile - - butler/README.md - - butler/db/schema.rb - - butler/db/migrate/20240209144600_change_mysql_charset.rb - - .pscale.yml - - Convert tables to utf8mb4 (refs/gitbutler/Convert-tables-to-utf8mb4) - branch head: 841e4db701ca41206c03f1f4fe345f7e27d05eab - - butler/create_column_conversions.rb - - Your previous branch was: refs/heads/sc-branch-comments - - The sha for that commit was: 5e16e99667db9d26f78110df807853a896120ff3 - - For more information about what we're doing here, check out our docs: - https://docs.gitbutler.com/features/branch-management/integration-branch -``` - -You can see the two `gitbutler` refs under the "Here are the branches that are currently applied" section. - -Again, these are real git refs, just not under `refs/heads` so that we don't pollute your `git branch` output. But if GitButler crashes at some point, you can still push them to GitHub or whatever you want. Here is an example pushing my virtual branch to a GitHub branch called `convert-tables`: - -```bash title="Terminal" -❯ git push origin refs/gitbutler/Convert-tables-to-utf8mb4:refs/heads/convert-tables -Enumerating objects: 6, done. -Counting objects: 100% (6/6), done. -Delta compression using up to 10 threads -Compressing objects: 100% (4/4), done. -Writing objects: 100% (4/4), 474 bytes | 474.00 KiB/s, done. -Total 4 (delta 2), reused 1 (delta 0), pack-reused 0 -remote: Resolving deltas: 100% (2/2), completed with 2 local objects. -remote: -remote: Create a pull request for 'convert-tables' on GitHub by visiting: -remote: https://github.com/gitbutlerapp/web/pull/new/convert-tables -remote: -To github.com:gitbutlerapp/web.git - * [new branch] refs/gitbutler/Convert-tables-to-utf8mb4 -> convert-tables -``` - -## GitButler Operations Log - -Ok, let's say that your work was not in one of those refs for some reason. Maybe you hit some weird bug and it completely changed everything in a way where now you're sitting on the couch in the dark with a glass of whisky, slowly mumbling the word "GitButler..." and plotting your revenge. - -Most of the time, we'll have whatever you're looking for in our operations log. - -The easiest way to access this is to use the built in Project History UI: [Project History](/features/timeline) - -However, let's dig into how this works, just in case you want to check it out yourself. - -Every time that GitButler does some possibly data-changing operation, we store a snapshot of your project state in our operations log before the operation happens so you can undo it if you want to. This is stored as a Git commit history that is parallel to your projects (ie, no common parents). - -You can inspect this by looking at the `.git/gitbutler/operations-log.toml` file. - -```bash title="Terminal" -❯ tree .git/gitbutler -.git/gitbutler -├── operations-log.toml -└── virtual_branches.toml - -1 directory, 2 files - -❯ cat .git/gitbutler/operations-log.toml -head_sha = "16e47cb1d091ca9dd44327fef2f5305b09403a95" - -[modified_at] -secs_since_epoch = 1717663406 -nanos_since_epoch = 560458000 -``` - -If we look at this commit, we can see the history of all of the project history snapshots that GitButler is keeping: - -```bash title="Terminal" -❯ git log 16e47cb1d091ca9dd44327fef2f5305b09403a9 -2 -commit 16e47cb1d091ca9dd44327fef2f5305b09403a95 -Author: GitButler -Date: Thu Jun 6 10:43:26 2024 +0200 - - CreateBranch - - Version: 1 - Operation: CreateBranch - name: Virtual branch - -commit 2c95aa06d76b3230f1a51d9f89a211770d93ae51 -Author: GitButler -Date: Thu Jun 6 10:28:30 2024 +0200 - - UpdateWorkspaceBase - - Version: 1 - Operation: UpdateWorkspaceBase -``` - -You can see that before creating a branch or updating our workspace with upstream work, we're recording the state of our project so we have an undo point. So what data are we keeping here in addition to this trailer information? - -Let's look at the tree of one of these commits: - -```bash title="Terminal" -❯ git cat-file -p 16e47cb1d091ca9dd44327fef2f5305b09403a95^{tree} -040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 conflicts -040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 index -040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 target_tree -100644 blob d839dca7e14f5833ad737b4adbf337bd20489927 virtual_branches.toml -040000 tree a0821552c0e7d5defe369d577af5e3a87b442469 virtual_branches -``` - -The parallel branches toml file has the interesting metadata: - -```bash title="Terminal" -❯ git cat-file -p 16e47cb1d091ca9dd44^{tree}:virtual_branches.toml -[default_target] -branchName = "master" -remoteName = "origin" -remoteUrl = "git@github.com:gitbutlerapp/gitbutler.git" -sha = "e00e54af7f903ef84600079a45490a7f07e4702e" -pushRemoteName = "origin" - -[branch_targets] - -[branches.09ef54c4-1081-4a52-8182-a5ec725016b6] -id = "09ef54c4-1081-4a52-8182-a5ec725016b6" -name = "commit signing settings" -notes = "" -applied = false -upstream = "refs/remotes/origin/commit-signing-settings" -upstream_head = "b60a66452dfecef74103346af6a3291ad677d246" -created_timestamp_ms = "1717489406268" -updated_timestamp_ms = "1717489406268" -tree = "b28e7eefdd7b6f36456516b696146a2ea7638ca4" -head = "b60a66452dfecef74103346af6a3291ad677d246" -ownership = "" -order = 4 -selected_for_changes = 1717489406268 -``` - -The virtual_branches tree has the actual contents of those computed branches in case we need to recreate them: - - - - - - - - - - - - - - - - - - - - - - - -This allows you to get contents of any file in any of your virtual branch states as well. - - -# gitlab-integration.mdx - - -Create your GitLab Merge requests without leaving GitButler. - -## Setting up the GitLab Integration - -In order to set up the GitLab integration, you will need two things. Firstly, a GitLab Personal Token and the Project ID for your project. +In order to set up the GitLab integration, you will need two things. Firstly, a GitLab Personal Token and the Project ID for your project. ### Creating a GitLab Personal Token @@ -1419,198 +1456,33 @@ On completion, you will be showen the following screen which contains your GitLa -### Finding your GitLab Project ID - -Navigate to the main page of the repository you want to configure the integration for. On the top left next to the "Fork" button, you will see three dots. Click on those three dots, and click on "Copy project ID". This will copy the GitLab Project ID to your clipboard. - - - -### Configuring GitButler - -Inside GitButler, navigate to the project settings by clicking on the small cog icon in the bottom left. Scroll down to the bottom of the "Project" tab where you will see a form for entering your GitLab details. The provided GitLab Personal Token will be stored securly in your operating system's keychain. - - - -### Custom GitLab Instances - -You may also provide a different Instance URL if you are using a self-hosted GitLab instance. - -Note that if you use a custom GitLab instance, you will likely need to configure a custom CSP (Content Security Policy) to allow GitButler to connect to it. You can find more information on how to do that in the [Custom Content Security Policy (CSP)](/troubleshooting/custom-csp) section of the documentation. - -## Usage - -You will now have a "Submit for Review" button on each branch which you can use to create a Merge Request. - - - -Once the Merge Request is created you will be able to see the status of it from within the client. Please note that we do not yet integrate with CI status. - - - - -# github-integration.mdx - - -GitButler integrates seamlessly with GitHub, allowing you to manage the pull requests associated with your branches directly from the GitButler client. - -You can setup multiple GitHub accounts and pick which account to use for specific projects. This makes it easy to manage work across different organizations or personal repositories. - -## Setting up GitHub Integration - -To set up GitHub integration, you need to connect your GitButler client to your GitHub account. This is done through the GitButler settings. - -Open the GitButler settings by clicking on the profile button in the sidebar, then navigate to the **Integrations** tab, then click on the **Add account** button for GitHub. - - - - -This will offer you to create an account out of the following options: -- **Device Flow**: This option will generate a code and ask you to open a browser window to authorize GitButler to access your GitHub account. This is the recommended option for most users. -- **Personal Access Token**: This option allows you to manually enter a personal access token from GitHub. This is useful for users who prefer not to use OAuth or need specific scopes for their token. -- **GitHub Enterprise**: This option allows you to connect to a GitHub Enterprise instance by providing the base URL for the API and a personal access token. - -We'll select the **Device Flow** option for this example. - - - -A code will be generated for you. Copy it to your clipboard. - - - -Next, click on the **Open GitHub activation page** button. This will open a browser window to the GitHub authorization page. - - - - -Once you are on the GitHub authorization page, paste the code into the input field and it should let you know that you are authorized. - - - -Return to the GitButler client and click on the **Check the status** button. -If everything went well, your account should be connected and you should see your GitHub username in the Integrations tab. - - - -You can always forget an account by clicking on the **Forget** button next to the account name. - - - -Alternatively, you can also connect your GitHub account using a Personal Access Token by selecting the **Personal Access Token** option when adding an account. -The permissions required for GitButler to manage pull requests are read access to *Metadata* and read and write access to *Pull Requests* -The required permissions might change in the future as new features are added. - - - -In the case of GitHub Enterprise, select the **GitHub Enterprise** option when adding an account. -This will ask you for the base URL of your GitHub Enterprise instance's API as well as a Personal Access Token with the same permissions as above. - -For example, if your GitHub Enterprise Server's hostname is **github.a-super-serious-company.com**, then set the base URL to **github.a-super-serious-company.com/api/v3**. - -See [GitHub's Octokit base URL documentation](https://github.com/octokit/octokit.js?tab=readme-ov-file#constructor-options) for more information. - -## Using GitButler to Manage Pull Requests - -Once you have set up GitHub integration, you can open your pull requests directly from the GitButler branch. - - - -When you create a new branch or commit changes, GitButler will automatically check if there are any associated pull requests on GitHub. You can view these pull requests in the "Pull Requests" tab in the sidebar of the Branches page. +### Finding your GitLab Project ID +Navigate to the main page of the repository you want to configure the integration for. On the top left next to the "Fork" button, you will see three dots. Click on those three dots, and click on "Copy project ID". This will copy the GitLab Project ID to your clipboard. -# timeline.mdx + +### Configuring GitButler -Undo nearly any of your actions or go back in time to an earlier state. +Inside GitButler, navigate to the project settings by clicking on the small cog icon in the bottom left. Scroll down to the bottom of the "Project" tab where you will see a form for entering your GitLab details. The provided GitLab Personal Token will be stored securly in your operating system's keychain. -## How it works + -Before GitButler does any major action, it records the state of everything (your virtual branch state, your uncommitted work, conflict state, etc) and stores it in your Git object database as snapshots. You can hit the 'revert' button on any of the entries and it will restore the state of all of these things to what they looked like when they were recorded, letting you go back in time. +### Custom GitLab Instances - +You may also provide a different Instance URL if you are using a self-hosted GitLab instance. -## Restoring State +Note that if you use a custom GitLab instance, you will likely need to configure a custom CSP (Content Security Policy) to allow GitButler to connect to it. You can find more information on how to do that in the [Custom Content Security Policy (CSP)](/troubleshooting/custom-csp) section of the documentation. -If you hover over any of the entries, you will see a button named "Revert" that will restore the state of things to right before you did that action. So if you revert one that says "Create Commit", it will put you where you were right before you made that commit. +## Usage - +You will now have a "Submit for Review" button on each branch which you can use to create a Merge Request. -## Recovering Content + -Occasionally, GitButler will also take snapshots of files that were changed recently, even if they weren't committed. If this, or any other action, sees changes in files, you can see which ones and view the change by clicking on the file name. +Once the Merge Request is created you will be able to see the status of it from within the client. Please note that we do not yet integrate with CI status. - + # ai-assistance.mdx @@ -1739,41 +1611,70 @@ Generates comprehensive PR descriptions when creating pull requests. - Review [troubleshooting guide](https://docs.gitbutler.com/troubleshooting/custom-csp) for advanced configurations -# branch-lanes.mdx +# gerrit-mode.mdx +Not _everyone_ uses GitHub or GitLab to review code and collaborate. If you use the [Gerrit](https://www.gerritcodereview.com/) code review tool, GitButler has a mode for you! In fact, GitButler is the best Gerrit client there is. -All of your branches - remote, local, and virtual / applied or not - are managed in the Branch Tab. This is where you can see all of your branches, apply them to your workspace, and manage your parallel branches. +## What is Gerrit -You can access the Branches tab by clicking on the "Branches" icon in the sidebar. +If you've never heard of Gerrit, it's used by large teams like the Android or Chrome projects to manage huge numbers of changes and users across large numbers of interdependent repositories. -The interface looks something like this: +Here is an example of incoming changesets on the [Android project](https://android-review.googlesource.com/q/status:open+-is:wip,50): -## Branch List +## How is Gerrit different than Pull/Merge Requests? -The first pane on the left shows you the parallel branches and stacks that you have as well as the other branches that you have available (legacy git branches, remote branches and PRs). +Good question. With GitHub or GitLab, when you send a pull/merge request, the review process is branch based. If you add more commits on top of your branch, the changes are squashed into one big unified diff for review. Most teams tend to avoid rebasing anything that was already shared. -All of these branches can be converted into parallel branches by clicking them and then clicking the "Apply to workspace" button on the top of the branch view (middle pane). +Gerrit is a commit based review system. Every review is based on exactly one commit. It's very common to edit shared commits and submit new versions of them to address feedback. -Local branches can also be fully deleted here. +This model works _very well_ with GitButler's easy [commit editing](/features/branch-management/commits) features. With any other Git client, interactive rebasing and amending tends to be quite painful and error prone, making it fairly difficult to work with Gerrit's model. With GitButler, it's ideal. Just drag and drop changes and update your changesets easily. -### Current Workspace Target +## How to turn on Gerrit Mode -The "Current workspace target" is the view of the target branch that you've set. It will show you essentially a `git log` of `origin/master` or whatever you set as your target branch, and it will show you if there are any commits upstream that you have not integrated locally yet. We will automatically check for new upstream changes every few minutes, but you can also click the update button to check immediately. +If you have a Gerrit remote, GitButler will automatically enable Gerrit Mode when the project is being added to GitButler. You can also enable it manually. +To manually turn on Gerrit Mode in GitButler, you just have to set a Git config option called `gitbutler.gerritMode` in the project you want to act in a Gerrit compatible fashion: + +``` +❯ cd my_project +❯ git config gitbutler.gerritMode 1 +``` + +## What is Gerrit Mode + +Now GitButler will change its behavior in the following ways: + +- When you commit, we will automatically inject a `Change-Id` trailer into the commit in the format that Gerrit expects. You do not need to [setup a `commit-msg` hook](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) like you do with other Git clients. +- When you push, it will not push to a matching branch name on the remote. Instead it will push to `refs/for/main` (or whatever the name of the target branch is set to be). +- After a push, we record the change url and show you the link and number for each commit automatically. + +We can also set some extra push options when we push, including: + +- [Topics](https://gerrit-review.googlesource.com/Documentation/cross-repository-changes.html) +- [Hashtags](https://gerrit-review.googlesource.com/Documentation/intro-user.html#hashtags) +- [WIP status](https://gerrit-review.googlesource.com/Documentation/intro-user.html#wip) + + @@ -1931,55 +1832,183 @@ Then you can change whatever you want and when you click "Save and exit", it wil This is useful for things like getting feedback on a series and being able to go into the appropriate commit, make the changes and continue, as opposed to squashing work. -# merging.mdx +# branch-lanes.mdx -By default, GitButler rebases the work on your parallel branches when you update your target branch (upstream) work. +All of your branches - remote, local, and virtual / applied or not - are managed in the Branch Tab. This is where you can see all of your branches, apply them to your workspace, and manage your parallel branches. -Often this works just fine and the commits are simply rebased. Occasionally, you will have conflicts with upstream work. +You can access the Branches tab by clicking on the "Branches" icon in the sidebar. -In this case, GitButler will not do what Git normally does, which is to stop at each conflicted commit and make you fix it before moving on. Instead, it will apply the changes that it can and store the commit as a "conflicted" commit and continue the rebasing process. +The interface looks something like this: -When you go to update from upstream, GitButler will show you all the branches that it will rebase and will let you know if any of them will have conflicts: + + +## Branch List + +The first pane on the left shows you the parallel branches and stacks that you have as well as the other branches that you have available (legacy git branches, remote branches and PRs). + +All of these branches can be converted into parallel branches by clicking them and then clicking the "Apply to workspace" button on the top of the branch view (middle pane). + +Local branches can also be fully deleted here. + +### Current Workspace Target + +The "Current workspace target" is the view of the target branch that you've set. It will show you essentially a `git log` of `origin/master` or whatever you set as your target branch, and it will show you if there are any commits upstream that you have not integrated locally yet. We will automatically check for new upstream changes every few minutes, but you can also click the update button to check immediately. -In this case, when you perform the rebase, that branch will then contain "conflicted" commits. They will be marked in the UI as conflicted and you can click on them to get a "resolve conflict" button to start the resolution process. + +# github-integration.mdx + + +GitButler integrates seamlessly with GitHub, allowing you to manage the pull requests associated with your branches directly from the GitButler client. + +You can setup multiple GitHub accounts and pick which account to use for specific projects. This makes it easy to manage work across different organizations or personal repositories. + +## Setting up GitHub Integration + +To set up GitHub integration, you need to connect your GitButler client to your GitHub account. This is done through the GitButler settings. + +Open the GitButler settings by clicking on the profile button in the sidebar, then navigate to the **Integrations** tab, then click on the **Add account** button for GitHub. + -When you click that, GitButler will remove the other parallel branches and other work from your working directory and check out just this commit with its conflict markers. It will show you a special "edit mode" screen, where you are directly editing this commit. +This will offer you to create an account out of the following options: +- **Device Flow**: This option will generate a code and ask you to open a browser window to authorize GitButler to access your GitHub account. This is the recommended option for most users. +- **Personal Access Token**: This option allows you to manually enter a personal access token from GitHub. This is useful for users who prefer not to use OAuth or need specific scopes for their token. +- **GitHub Enterprise**: This option allows you to connect to a GitHub Enterprise instance by providing the base URL for the API and a personal access token. + +We'll select the **Device Flow** option for this example. + + + +A code will be generated for you. Copy it to your clipboard. + + + +Next, click on the **Open GitHub activation page** button. This will open a browser window to the GitHub authorization page. + + + + +Once you are on the GitHub authorization page, paste the code into the input field and it should let you know that you are authorized. + + + +Return to the GitButler client and click on the **Check the status** button. +If everything went well, your account should be connected and you should see your GitHub username in the Integrations tab. + + + +You can always forget an account by clicking on the **Forget** button next to the account name. + + + +Alternatively, you can also connect your GitHub account using a Personal Access Token by selecting the **Personal Access Token** option when adding an account. +The permissions required for GitButler to manage pull requests are read access to *Metadata* and read and write access to *Pull Requests* +The required permissions might change in the future as new features are added. + + + +In the case of GitHub Enterprise, select the **GitHub Enterprise** option when adding an account. +This will ask you for the base URL of your GitHub Enterprise instance's API as well as a Personal Access Token with the same permissions as above. + +For example, if your GitHub Enterprise Server's hostname is **github.a-super-serious-company.com**, then set the base URL to **github.a-super-serious-company.com/api/v3**. + +See [GitHub's Octokit base URL documentation](https://github.com/octokit/octokit.js?tab=readme-ov-file#constructor-options) for more information. + +## Using GitButler to Manage Pull Requests + +Once you have set up GitHub integration, you can open your pull requests directly from the GitButler branch. + + + +When you create a new branch or commit changes, GitButler will automatically check if there are any associated pull requests on GitHub. You can view these pull requests in the "Pull Requests" tab in the sidebar of the Branches page. + + +# pushing-and-fetching.mdx + + +GitButler can authenticate with an upstream Git server in several different ways. - + You can just tell us to use the system Git executable, which you can setup however you want. You can use our built in SSH protocol with your own SSH key (this does not require you to have Git installed), or you can use the default [Git credentials helper](https://git-scm.com/doc/credential-helpers). -If you want to cancel this conflict resolution, you can just hit 'Cancel' and it will go back to your normal state. If you have fixed all the issues, you can click "Save and Exit" and it will commit the conflict resolution and if needed, rebase any further commits on that branch on top of your new work. +You can set your preference (and test if it works) in your project's "Git authentication" section: +Once that's done, GitButler will be able to automatically fetch upstream work and push new branches to your upstream server. + # moving-branches.mdx @@ -2067,330 +2096,221 @@ If you're using GitHub integration and the branch has an associated pull request - [Parallel Branches](/features/branch-management/virtual-branches) - Core concepts of GitButler's virtual branch system -# pushing-and-fetching.mdx - - -GitButler can authenticate with an upstream Git server in several different ways. - - You can just tell us to use the system Git executable, which you can setup however you want. You can use our built in SSH protocol with your own SSH key (this does not require you to have Git installed), or you can use the default [Git credentials helper](https://git-scm.com/doc/credential-helpers). - -You can set your preference (and test if it works) in your project's "Git authentication" section: - - - -Once that's done, GitButler will be able to automatically fetch upstream work and push new branches to your upstream server. - - -# overview.mdx - - -# Butler Review - - - We have paused work on Butler Review for now to concentrate more on the client experience. Review - will be coming back in our upcoming server functionality, stay tuned. - - -Butler Review is a new approach to code review that focuses on reviewing code -as a series of evolving patches rather than a unified diff of a whole branch. - - - -## Why Butler Review? - -Traditional code review tools like GitHub and GitLab show changes as a single -diff of the entire branch. This makes it hard to review changes in a branch -incrementally, especially when the branch is large. It also discourages creating -good commit or commit messages, since they are all sqaushed in review and -messages are difficult to find and unrelated to the code review UI. - -Butler Review approaches the problem differently, by making it easy to review -individual commits as patches and tracking changes to the series when you rebase -or amend the branch. - -This makes it easier to review changes incrementally and evolve a series rather -than pushing poor commits to the branch to address feedback. - -## Enabling Butler Review +# merging.mdx -To start using Butler Reviews, you need to enable the feature in your GitButler -client in the project settings. Click the gear icon in the bottom left corner of -the GitButler client and go to the Server tab. - +By default, GitButler rebases the work on your parallel branches when you update your target branch (upstream) work. -Once you enable Butler Review, you can start creating reviews for your branches. +Often this works just fine and the commits are simply rebased. Occasionally, you will have conflicts with upstream work. -## Creating a Review +In this case, GitButler will not do what Git normally does, which is to stop at each conflicted commit and make you fix it before moving on. Instead, it will apply the changes that it can and store the commit as a "conflicted" commit and continue the rebasing process. -Once you have enabled Butler Review for a project, you can create a review for -a branch by clicking the new "Create Butler Review" button in the branch header card. +When you go to update from upstream, GitButler will show you all the branches that it will rebase and will let you know if any of them will have conflicts: -Once you create a review, you will see a new card in the branch header that -shows the status of the review. +In this case, when you perform the rebase, that branch will then contain "conflicted" commits. They will be marked in the UI as conflicted and you can click on them to get a "resolve conflict" button to start the resolution process. -If you have GitHub integration enabled, you will see a dropdown to let you choose -to create a PR or a Butler Review. You can also create both, in either order and -they will be linked together. +When you click that, GitButler will remove the other parallel branches and other work from your working directory and check out just this commit with its conflict markers. It will show you a special "edit mode" screen, where you are directly editing this commit. -Once a Review has been opened, you will have a URL that you can share with your -team to get feedback on your changes. - -## Reviewing a Series - -When a reviewer opens a review, they will see a list of patches that make up the branch. +If you want to cancel this conflict resolution, you can just hit 'Cancel' and it will go back to your normal state. If you have fixed all the issues, you can click "Save and Exit" and it will commit the conflict resolution and if needed, rebase any further commits on that branch on top of your new work. - - Currently, all reviews are "unlisted", meaning that anyone with the URL can see the review. - In the future, we will implement fully public and fully private reviews, but currently all reviews - are unlisted. - -However, if someone has the URL, they will only be able to see the patch data, -they will not have access to all of your source code, nor will they be able to make changes, -only approve or request changes. - - - -Now the reviewer can hit "Start Review" to start reviewing the patches in the series. -It will start them at the "bottom", the first patch and they can work their way up. -The reviewer can also click on a patch to go directly to it. - -## Reviewing a Patch - -Once a reviewer starts reviewing a patch, they will see the changes in the commit -and a chat window to leave comments. - - -The reviewer can leave comments on the patch, approve the patch, or request changes. -The chat discussion is real time, so reviewers can discuss the changes with the author -as they review the patch. - -You can also select lines of code to comment on. This will highlight the line in the -diff and show the comment in the chat window. - -Every patch needs to be approved before the branch is considered approved. - -## Requesting Changes +# stacked-branches.mdx -A reviewer can either approve a patch or request changes. If they request changes, -the author can amend that specific commit and publish the changes to the review. -Reviewers will be able to see in the chat that a new version of the patch has been -published and they can review the changes again. +Create a stack of dependent branches to be reviewed and merged in order. - - Currently we don't have interdiffs, so reviewers will need to review the entire patch again. We - plan to add interdiffs in the very near future. - +## Overview -## Approving a Patch +GitButler allows you to create an ordered stack of branches where each branch depends on (and is based on) the previous one. +The application also supports creating the appropriate stacked Pull Requests (when used with a GitHub remote). +This is useful when you have multiple changesets that depend on each other but it is desirable to have them reviewed and merged separately (and in sequence). -Once a reviewer is happy with a patch, they can approve it. This will mark the patch -as approved and move the reviewer to the next patch in the series. +> All of the Pull Request stack orchestration is done locally in the client, which means that your repo content is not shared with a cloud service. -## Closing a Review + -Once the branch has been merged, it will automatically mark the review as closed. -The author can also manually close the review if they decide to abandon the series. +## Use cases +Using stacked branches (Pull Requests) can be helpful for shipping smaller changes more frequently. -# rules.mdx +### Breaking up a larger change into smaller ones +Consider a scenario where you are implementing a medium/large feature in your software project. +In the course of implementation you end up performing the following sub-tasks: -Rules are a powerful automation feature in GitButler that automatically assign file changes to specific branches based on conditions you define. Instead of manually dragging changes between lanes, you can set up rules that automatically route changes where they belong. +1. Refactor a part of the codebase to accommodate the new feature +2. Implement an API endpoint supporting the feature +3. Implement the frontend part of the feature consuming the API -## Overview +While the feature is considered complete only when all of the subtasks are implemented, reviewed and merged, in many cases it is considered beneficial +to ship each stage of the feature on its own, potentially behind a feature flag. Not only the risk of merge conflicts with colleagues is reduced, +but also eventual bugs are easier to track down / revert / fix as compared to a single large change. -When you're working on multiple branches simultaneously, you often know in advance which types of changes should go to which branch. For example, documentation updates might always go to a `docs` branch, while UI changes go to a `feature/ui-redesign` branch. +### More granular (easier) review process -Rules eliminate the manual work of assigning changes by automatically evaluating your uncommitted changes and routing them to the appropriate branch based on filters you define. +On GitHub at least, code reviews are performed on per-branch basis. While it is possible to view individual commits in a Pull Request, it is not possible to +approve and merge a subset of commits from the PR. -## How Rules Work +Utilizing stacked pull requests, means that the sub-tasks of a larger change are in their own PRs. +This way it is possible to approve and merge the initial part of a stack (e.g. a refactor) while still iterating on the remaining sub-tasks. -Rules are evaluated whenever files change in your working directory (the `fileSytemChange` trigger). Each rule consists of: +## Comparison to Parallel Branches -1. **Filters**: Conditions that determine which changes the rule applies to -2. **Action**: Assigns matching changes to a specific branch +Stacking and Parallel Branches are similar in that they allow you to separate code changes / commits into different branches. In both cases, +the changes are available in your working directory. -Multiple rules can exist, and they are evaluated in order. Within a single rule, multiple filters are combined with AND logic - all conditions must match for the rule to apply. +The main difference is that Parallel Branches are **independent** from one another, while stacked branches **depend** on the ones that come before it. +Because of this, the two features are not mutually exclusive but rather complementary. For example a bugfix change that is unrelated to a feature +can be put in a separate virtual branch. On the other hand, a change that depends on a previous change can be put in a stacked branch above the one it depends on. -## Creating a Rule +In fact GitButler implements stacked branches as Parallel Branches that are split into multiple dependent branches. -To create a rule: + -1. Open the **Rules** drawer at the bottom of the GitButler interface -2. Click the **+** button to add a new rule -3. Select the target branch where matching changes should be assigned: - - Specify a branch by name - - **Leftmost lane**: The leftmost branch in your workspace - - **Rightmost lane**: The rightmost branch in your workspace -4. (Optional) Add filters to specify which changes should match -5. Click **Save rule** +## Workflow -If you don't add any filters, the rule will match all changes. +By default, parallel branches in the app are simply stacks of one. +With version `0.14.0` or newer you can create a new dependent branch within a lane by clicking the `+` button above the branch name. - -

- Creating a rule that assigns changes to the leftmost lane -

+> The workflow below assumes a GitHub remote. If you are using a different forge, you can still use this functionality but will need to manually create/update the Pull/Merge Requests -## Filter Types +1. Creating a new dependent branch forms a stack within the lane. -Rules support several types of filters to match changes: + -### Path Matches Regex +2. New commits land in the top branch of the stack. -Matches file paths using a regular expression pattern. + -**Example use cases:** +3. Pushing is done for the stack as a whole. Note: The Pull Requests will be created in a way where each branch points to its parent - see [Automatic branch deletion](#automatic-branch-deletion) -- Match all TypeScript files: `.*\.ts$` -- Match files in a specific directory: `^src/components/.*` -- Match documentation files: `.*\.(md|mdx)$` + -### Content Matches Regex +4. Pull requests must be created one at a time starting from the bottom of the stack. -Matches the content of changed lines using a regular expression pattern. This filter only looks at added lines (lines that start with `+` in the diff). + -**Example use cases:** +5. The PRs will contain a footer with stack information, and as you add more PRs it will keep all up to date. -- Match changes containing TODOs: `TODO` -- Match changes with specific function calls: `console\.log` -- Match changes with certain patterns: `@deprecated` + - -

- Creating a rule that assigns changes containing "fix" to a specific branch -

+6. You can drag changes into commits to amend them (e.g. incorporating review feedback) as well as move and squash commits. -### Claude Code Session ID + + + -Matches changes that originated from a specific Claude Code session. This filter is automatically used when GitButler's AI features create branches and rules for you. +7. If a change in your stack is independent (e.g. an unrelated bugfix) it can be moved to a different virtual branch (or stack). + This works for both uncommitted changes and existing commits that you may want to relocate. -**Note**: Rules with Claude Code Session ID filters have lower priority than manually created rules. If a change matches both an AI-generated rule and a manual rule, the manual rule takes precedence. + - -

- AI-generated rules based on Claude Code sessions -

+8. Review/merge your PRs starting from the bottom up. After a PR/branch from your stack has been merged, it is reflected in the Stack and you should force push to reflect the changes + on the remote as well. -## Managing Rules + + -### Editing Rules +9. When all branches of a stack have been merged, the stack is complete. -To edit an existing rule: +## GitHub configuration for stacked PRs -1. Double-click the rule or click the elepsis menu (...) and select "Edit rule" -2. Modify the branch assignment or filters -3. Click **Save rule** +_TLDR:_ -### Deleting Rules +1. Enable automatic branch deletion [automatic branch deletion](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) + on GitHub. +2. If possible, consider using the the "Merge" strategy when merging PRs. -To delete a rule: +#### Automatic branch deletion -1. Click the elepsis menu (...) on the rule -2. Select "Delete rule" -3. Confirm the deletion +When reviewing a PR in a stack, it is important to be able to view only the changes in the branch that is being reviewed. +Of course, in pure Git terms, a stacked branch will contain all the changes from the branches below it. -**Note**: AI-generated rules and implicit rules cannot be edited. +In order to show only the expected Files changed and Commits for PRs in a stack, each PR is created to target the branch below it in the stack. +This is true for all but the bottom branch in the stack, which targets the default branch of the repository as usual. -## Understanding Rule Evaluation + -### Order Matters +> Every branch in the stack contains the commits from the branches below it. -Rules are evaluated in the order they appear in the Rules drawer (most recent first). The first matching rule determines where a change is assigned. +This of course does not mean that a Pull Request should be merged into its parent. +When the bottom branch is merged on GitHub, **if** the PR branch is deleted, +GitHub will automatically update any PRs that used to target it to target the default branch instead. -### AND Logic Within Rules + -When a rule has multiple filters, **all filters must match** for the rule to apply. For example, a rule with both "Path Matches Regex: `.*\.ts$`" and "Content Matches Regex: `TODO`" will only match TypeScript files that contain the text "TODO" in their changes. +If the newly merged branch from the bottom of the stack is not deleted, the next PR in line will still target it and there is a risk of accidentally merging it into the now out of date branch. +For this reason it is _highly recommended_ to [enable on GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) the automatic deletion of branches after merging. -### OR Logic Across Rules +_NB:_ If you merge the first PR but the branch is not deleted and then merge the second PR, +the app can still recover from this, see [Troubleshooting](#troubleshooting). -If you want to match changes that meet any of several conditions (OR logic), create separate rules for each condition. +#### Merge strategy -### Interaction with Hunk Dependencies +The app will support any merge strategy you wish to use - "Merge", "Rebase" or "Squash". However, due to the nature of merge, +the GitButler will be able to create a slightly better experience if the "Merge" strategy is used. +The reason for this is with merge commits you will be able to merge all the branches in the stack from GitHub without having to force push in the app. -Rules respect hunk dependencies (locks). If a change depends on a commit in a specific branch, it cannot be automatically reassigned by rules, even if it matches a rule's filters. +## Troubleshooting -## Best Practices +Firstly, if you run into any issue with the app (stacking or not), you can always get in touch either +on [Discord](https://discord.com/invite/MmFkmaJ42D) or via the in-app feedback icon (we will get back via email). +With that said, here are some workarounds for common issues. -1. **Start simple**: Begin with one or two basic path-matching rules before adding complex filters -2. **Order your rules**: Place more specific rules before general catch-all rules -3. **Test your regex**: Make sure your regular expressions match what you intend - it's easy to be too broad or too narrow -4. **Use catch-all rules carefully**: A rule with no filters will match everything, which can interfere with other rules -5. **Consider your workflow**: Rules work best when you have predictable patterns in how your work is organized -6. **Leverage leftmost/rightmost**: Using position-based targeting lets you reorganize lanes without updating rules +#### Accidentally merged a stack branch into an already merged branch before it -## Limitations +If you merged the bottom Pull Request into main but the branch was _not_ deleted, then the target of the next Pull Request would not be automatically updated. +Under these conditions merging that next Pull Request, means it would be merged into the original, now out of date, bottom PR. -- Rules can only assign changes to branches that exist in your workspace (applied branches) -- Implicit (AI-determined) rules cannot be edited through the UI -- Rules currently only support the `assign` action for filesystem changes +A mitigation for this is to rename the branch, push and re-create the Pull Request. -## Related Features +#### Accidentally merged a branch into a branch before it (not integrated into main/master yet) -- [Parallel Branches](/features/branch-management/virtual-branches): Understanding the branch system that rules work with -- [Branch Lanes](/features/branch-management/branch-lanes): How lanes are organized and how rules interact with lane positioning -- [AI Assistance](/features/branch-management/ai-assistance): How AI can create and manage rules automatically +Merging of branches in a stack should be done from the bottom up. With the GitHub interface, it is possible to incorrectly merge a Pull Request which is in the middle of the stack. +In this case it will merged in the parent branch. + +In order to recover from this situation you can simply force push the branches and then re-create the PR that was incorrectly merged. # signing-commits.mdx @@ -2517,177 +2437,177 @@ Now paste in the public SSH key you copied from GitButler, name it and make sure /> -# stacked-branches.mdx +# rules.mdx -Create a stack of dependent branches to be reviewed and merged in order. +Rules are a powerful automation feature in GitButler that automatically assign file changes to specific branches based on conditions you define. Instead of manually dragging changes between lanes, you can set up rules that automatically route changes where they belong. ## Overview -GitButler allows you to create an ordered stack of branches where each branch depends on (and is based on) the previous one. -The application also supports creating the appropriate stacked Pull Requests (when used with a GitHub remote). -This is useful when you have multiple changesets that depend on each other but it is desirable to have them reviewed and merged separately (and in sequence). - -> All of the Pull Request stack orchestration is done locally in the client, which means that your repo content is not shared with a cloud service. - - - -## Use cases - -Using stacked branches (Pull Requests) can be helpful for shipping smaller changes more frequently. - -### Breaking up a larger change into smaller ones - -Consider a scenario where you are implementing a medium/large feature in your software project. -In the course of implementation you end up performing the following sub-tasks: - -1. Refactor a part of the codebase to accommodate the new feature -2. Implement an API endpoint supporting the feature -3. Implement the frontend part of the feature consuming the API - -While the feature is considered complete only when all of the subtasks are implemented, reviewed and merged, in many cases it is considered beneficial -to ship each stage of the feature on its own, potentially behind a feature flag. Not only the risk of merge conflicts with colleagues is reduced, -but also eventual bugs are easier to track down / revert / fix as compared to a single large change. - -### More granular (easier) review process - -On GitHub at least, code reviews are performed on per-branch basis. While it is possible to view individual commits in a Pull Request, it is not possible to -approve and merge a subset of commits from the PR. +When you're working on multiple branches simultaneously, you often know in advance which types of changes should go to which branch. For example, documentation updates might always go to a `docs` branch, while UI changes go to a `feature/ui-redesign` branch. -Utilizing stacked pull requests, means that the sub-tasks of a larger change are in their own PRs. -This way it is possible to approve and merge the initial part of a stack (e.g. a refactor) while still iterating on the remaining sub-tasks. +Rules eliminate the manual work of assigning changes by automatically evaluating your uncommitted changes and routing them to the appropriate branch based on filters you define. -## Comparison to Parallel Branches +## How Rules Work -Stacking and Parallel Branches are similar in that they allow you to separate code changes / commits into different branches. In both cases, -the changes are available in your working directory. +Rules are evaluated whenever files change in your working directory (the `fileSytemChange` trigger). Each rule consists of: -The main difference is that Parallel Branches are **independent** from one another, while stacked branches **depend** on the ones that come before it. -Because of this, the two features are not mutually exclusive but rather complementary. For example a bugfix change that is unrelated to a feature -can be put in a separate virtual branch. On the other hand, a change that depends on a previous change can be put in a stacked branch above the one it depends on. +1. **Filters**: Conditions that determine which changes the rule applies to +2. **Action**: Assigns matching changes to a specific branch -In fact GitButler implements stacked branches as Parallel Branches that are split into multiple dependent branches. +Multiple rules can exist, and they are evaluated in order. Within a single rule, multiple filters are combined with AND logic - all conditions must match for the rule to apply. - +## Creating a Rule -## Workflow +To create a rule: -By default, parallel branches in the app are simply stacks of one. -With version `0.14.0` or newer you can create a new dependent branch within a lane by clicking the `+` button above the branch name. +1. Open the **Rules** drawer at the bottom of the GitButler interface +2. Click the **+** button to add a new rule +3. Select the target branch where matching changes should be assigned: + - Specify a branch by name + - **Leftmost lane**: The leftmost branch in your workspace + - **Rightmost lane**: The rightmost branch in your workspace +4. (Optional) Add filters to specify which changes should match +5. Click **Save rule** -> The workflow below assumes a GitHub remote. If you are using a different forge, you can still use this functionality but will need to manually create/update the Pull/Merge Requests +If you don't add any filters, the rule will match all changes. -1. Creating a new dependent branch forms a stack within the lane. + +

+ Creating a rule that assigns changes to the leftmost lane +

- +## Filter Types -2. New commits land in the top branch of the stack. +Rules support several types of filters to match changes: - +### Path Matches Regex -3. Pushing is done for the stack as a whole. Note: The Pull Requests will be created in a way where each branch points to its parent - see [Automatic branch deletion](#automatic-branch-deletion) +Matches file paths using a regular expression pattern. - +**Example use cases:** -4. Pull requests must be created one at a time starting from the bottom of the stack. +- Match all TypeScript files: `.*\.ts$` +- Match files in a specific directory: `^src/components/.*` +- Match documentation files: `.*\.(md|mdx)$` - +### Content Matches Regex -5. The PRs will contain a footer with stack information, and as you add more PRs it will keep all up to date. +Matches the content of changed lines using a regular expression pattern. This filter only looks at added lines (lines that start with `+` in the diff). - +**Example use cases:** -6. You can drag changes into commits to amend them (e.g. incorporating review feedback) as well as move and squash commits. +- Match changes containing TODOs: `TODO` +- Match changes with specific function calls: `console\.log` +- Match changes with certain patterns: `@deprecated` - - - + +

+ Creating a rule that assigns changes containing "fix" to a specific branch +

-7. If a change in your stack is independent (e.g. an unrelated bugfix) it can be moved to a different virtual branch (or stack). - This works for both uncommitted changes and existing commits that you may want to relocate. +### Claude Code Session ID - +Matches changes that originated from a specific Claude Code session. This filter is automatically used when GitButler's AI features create branches and rules for you. -8. Review/merge your PRs starting from the bottom up. After a PR/branch from your stack has been merged, it is reflected in the Stack and you should force push to reflect the changes - on the remote as well. +**Note**: Rules with Claude Code Session ID filters have lower priority than manually created rules. If a change matches both an AI-generated rule and a manual rule, the manual rule takes precedence. - - + +

+ AI-generated rules based on Claude Code sessions +

-9. When all branches of a stack have been merged, the stack is complete. +## Managing Rules -## GitHub configuration for stacked PRs +### Editing Rules -_TLDR:_ +To edit an existing rule: -1. Enable automatic branch deletion [automatic branch deletion](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) - on GitHub. -2. If possible, consider using the the "Merge" strategy when merging PRs. +1. Double-click the rule or click the elepsis menu (...) and select "Edit rule" +2. Modify the branch assignment or filters +3. Click **Save rule** -#### Automatic branch deletion +### Deleting Rules -When reviewing a PR in a stack, it is important to be able to view only the changes in the branch that is being reviewed. -Of course, in pure Git terms, a stacked branch will contain all the changes from the branches below it. +To delete a rule: -In order to show only the expected Files changed and Commits for PRs in a stack, each PR is created to target the branch below it in the stack. -This is true for all but the bottom branch in the stack, which targets the default branch of the repository as usual. +1. Click the elepsis menu (...) on the rule +2. Select "Delete rule" +3. Confirm the deletion - +**Note**: AI-generated rules and implicit rules cannot be edited. -> Every branch in the stack contains the commits from the branches below it. +## Understanding Rule Evaluation -This of course does not mean that a Pull Request should be merged into its parent. -When the bottom branch is merged on GitHub, **if** the PR branch is deleted, -GitHub will automatically update any PRs that used to target it to target the default branch instead. +### Order Matters - +Rules are evaluated in the order they appear in the Rules drawer (most recent first). The first matching rule determines where a change is assigned. -If the newly merged branch from the bottom of the stack is not deleted, the next PR in line will still target it and there is a risk of accidentally merging it into the now out of date branch. -For this reason it is _highly recommended_ to [enable on GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) the automatic deletion of branches after merging. +### AND Logic Within Rules -_NB:_ If you merge the first PR but the branch is not deleted and then merge the second PR, -the app can still recover from this, see [Troubleshooting](#troubleshooting). +When a rule has multiple filters, **all filters must match** for the rule to apply. For example, a rule with both "Path Matches Regex: `.*\.ts$`" and "Content Matches Regex: `TODO`" will only match TypeScript files that contain the text "TODO" in their changes. -#### Merge strategy +### OR Logic Across Rules -The app will support any merge strategy you wish to use - "Merge", "Rebase" or "Squash". However, due to the nature of merge, -the GitButler will be able to create a slightly better experience if the "Merge" strategy is used. -The reason for this is with merge commits you will be able to merge all the branches in the stack from GitHub without having to force push in the app. +If you want to match changes that meet any of several conditions (OR logic), create separate rules for each condition. -## Troubleshooting +### Interaction with Hunk Dependencies -Firstly, if you run into any issue with the app (stacking or not), you can always get in touch either -on [Discord](https://discord.com/invite/MmFkmaJ42D) or via the in-app feedback icon (we will get back via email). -With that said, here are some workarounds for common issues. +Rules respect hunk dependencies (locks). If a change depends on a commit in a specific branch, it cannot be automatically reassigned by rules, even if it matches a rule's filters. -#### Accidentally merged a stack branch into an already merged branch before it +## Best Practices -If you merged the bottom Pull Request into main but the branch was _not_ deleted, then the target of the next Pull Request would not be automatically updated. -Under these conditions merging that next Pull Request, means it would be merged into the original, now out of date, bottom PR. +1. **Start simple**: Begin with one or two basic path-matching rules before adding complex filters +2. **Order your rules**: Place more specific rules before general catch-all rules +3. **Test your regex**: Make sure your regular expressions match what you intend - it's easy to be too broad or too narrow +4. **Use catch-all rules carefully**: A rule with no filters will match everything, which can interfere with other rules +5. **Consider your workflow**: Rules work best when you have predictable patterns in how your work is organized +6. **Leverage leftmost/rightmost**: Using position-based targeting lets you reorganize lanes without updating rules -A mitigation for this is to rename the branch, push and re-create the Pull Request. +## Limitations -#### Accidentally merged a branch into a branch before it (not integrated into main/master yet) +- Rules can only assign changes to branches that exist in your workspace (applied branches) +- Implicit (AI-determined) rules cannot be edited through the UI +- Rules currently only support the `assign` action for filesystem changes -Merging of branches in a stack should be done from the bottom up. With the GitHub interface, it is possible to incorrectly merge a Pull Request which is in the middle of the stack. -In this case it will merged in the parent branch. +## Related Features -In order to recover from this situation you can simply force push the branches and then re-create the PR that was incorrectly merged. +- [Parallel Branches](/features/branch-management/virtual-branches): Understanding the branch system that rules work with +- [Branch Lanes](/features/branch-management/branch-lanes): How lanes are organized and how rules interact with lane positioning +- [AI Assistance](/features/branch-management/ai-assistance): How AI can create and manage rules automatically # virtual-branches.mdx -Parallel branches are a powerful feature of GitButler that allow you to work on multiple branches at the same time, committing to them independently and simultaneously. This is a key part of the GitButler experience, allowing you to manage your work in a flexible and efficient way that is not possible with traditional Git tooling. +Parllel branches are a powerful feature of GitButler that allow you to work on multiple branches at the same time, committing to them independently and simultaneously. This is a key part of the GitButler experience, allowing you to manage your work in a flexible and efficient way that is not possible with traditional Git tooling. ## Overview @@ -2730,89 +2650,106 @@ There are currently three main ways to use AI tools with GitButler: Note that as of GitButler version `0.15.2` these features have to be enabled via an experimental feature flag. You can find that under `Global Settings` -> `Experimental` -> `GitButler Actions`. -# claude-code-hooks.mdx +# upstream-integration.mdx -If you are using Claude Code, you can use the new ["hooks"](https://docs.anthropic.com/en/docs/claude-code/hooks) functionality to manage the output of even multiple simultaneous instances, while isolating all the generated code into virtual or stacked branches automatically. In this case, there is no need to set up the MCP server, as the hooks will handle everything for you. +Sometimes you work on a branch and someone else pushes to the same upstream branch. Often you won't know this until you try to push and Git tells you something like this: -Here's a short video showing how GitButler works with Claude Code: + -https://youtu.be/AwwPwSc9qhA +In this scenario, GitButler gives you some nice tooling to help you know when this happens as early as possible and help you deal with it easily. + +If someone else has pushed to a branch that you're working on, you will see the upstream commits without having to integrate them. You can look at the commits without having to merge them into your branch or rebase your work on top of them. + + + +When you decide that you do want to integrate the changes, you have two options - rebase or interactively integrate. + +## Rebase the changes + +If you select "Rebase upstream changes", it will do the equivalent of a `git pull --rebase` which rebases the commits you have locally on top of the ones that the other person has pushed, so you end up with a state like this: + + + +Now you can push your commit back upstream without a force push. Easy peasy. + +## Interactively integrate the changes + +However, let's say that you want to do something more complex. Maybe the other implemented the same thing that you did and you want to drop one of them or one of yours, or squash commits together or reorder them. In any of these cases, you can choose the "Interactive integration" option and you get something that looks like this: + + + +Here you can reorder commits however you want, you can choose to skip some of them, you can squash some of them down, etc. Just make the commits look however you prefer and then hit the "Integrate changes" button and push your final result back to the server. + + +# cursor-hooks.mdx + +GitButler integrates seamlessly with Cursor through hooks that automatically manage your commits and branches while you're using AI coding features. This allows you to automatically maintain clean git history and organized parallel branches. + +Here's a short video showing how GitButler works with Cursor hooks: + +https://youtu.be/NOYK7LTFvZM Ok, let's get it set up. ## Install the GitButler CLI -First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](./mcp-server) for more details on how to install the CLI. +First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](mcp-server) for more details on how to install the CLI. ## Installing GitButler as a Hook -Hooks in Claude Code are defined in one of your settings files. - -``` -~/.claude/settings.json - User settings -.claude/settings.json - Project settings -.claude/settings.local.json - Local project settings (not committed) -``` +Once the command line tool is installed, you can add the `but cursor` commands as hooks. -Wherever you want to add GitButler to handle your commits automatically, you can add us as a hook by adding the following to the `hooks` array in whatever settings file you want to use: +You will need to create or edit your `~/.cursor/hooks.json` file (globally) or `[project]/.cursor/hooks.json` file (single project) to have `afterFileEdit` and `stop` hooks like this: ```json { + "version": 1, "hooks": { - "PreToolUse": [ - { - "matcher": "Edit|MultiEdit|Write", - "hooks": [ - { - "type": "command", - "command": "but claude pre-tool" - } - ] - } - ], - "PostToolUse": [ + "afterFileEdit": [ { - "matcher": "Edit|MultiEdit|Write", - "hooks": [ - { - "type": "command", - "command": "but claude post-tool" - } - ] + "command": "but cursor after-edit" } ], - "Stop": [ + "stop": [ { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "but claude stop" - } - ] + "command": "but cursor stop" } ] } } ``` -Essentially, you want to run the `but claude pre-tool` command before any code generation or editing, and the `but claude post-tool` command after it. The `but claude stop` command will run when you stop the agent, ensuring that all changes are committed and branches are updated accordingly. - -You also might want to add to your "memories" to ask Claude not to try commiting using Git as it will be handled by GitButler. You can do something like this: - -``` -❯ cat ~/.claude/CLAUDE.md -## Development Workflow -- Never use the git commit command after a task is finished. -``` - -## Using GitButler with Claude Code - -With the hooks setup, Claude will tell GitButler when it has generated code or edited files and in which session, which helps GitButler to try to isolate the changes into a single branch per session. +## Using GitButler with Cursor -For example, if you have three sessions of Claude Code running at the same time, each will be communicating with GitButler at each step and GitButler will be assigning each change to the correct branch automatically. +Once the hooks are setup, Cursor will automatically call GitButler when it edits files and when it's done with a task, which will trigger GitButler to: -When the agent is done, GitButler will commit all the changes and write a more sophisticated commit message based on what you had prompted your agent. +- Create a branch if the chat session is new +- Assign edits to an active branch +- Commit with a message based on the prompt when a task is done # mcp-server.mdx @@ -3003,53 +2940,6 @@ You can see all of these steps in the "Actions" section of the GitButler interfa In the near future, we will also be able to do more interesting things like auto-absorbing changes into existing commits, creating new branches based on the prompt theme, creating stacked branches, and more. -# cursor-hooks.mdx - -GitButler integrates seamlessly with Cursor through hooks that automatically manage your commits and branches while you're using AI coding features. This allows you to automatically maintain clean git history and organized parallel branches. - -Here's a short video showing how GitButler works with Cursor hooks: - -https://youtu.be/NOYK7LTFvZM - -Ok, let's get it set up. - -## Install the GitButler CLI - -First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](mcp-server) for more details on how to install the CLI. - -## Installing GitButler as a Hook - -Once the command line tool is installed, you can add the `but cursor` commands as hooks. - -You will need to create or edit your `~/.cursor/hooks.json` file (globally) or `[project]/.cursor/hooks.json` file (single project) to have `afterFileEdit` and `stop` hooks like this: - -```json -{ - "version": 1, - "hooks": { - "afterFileEdit": [ - { - "command": "but cursor after-edit" - } - ], - "stop": [ - { - "command": "but cursor stop" - } - ] - } -} -``` - -## Using GitButler with Cursor - -Once the hooks are setup, Cursor will automatically call GitButler when it edits files and when it's done with a task, which will trigger GitButler to: - -- Create a branch if the chat session is new -- Assign edits to an active branch -- Commit with a message based on the prompt when a task is done - - # debugging.mdx @@ -3209,67 +3099,12 @@ If you're using an older distribution, you may be interested in trying our Flatp ### `Failed to create EGL image from DMABuf` -If you start GitButler from the command line and see a bunch of these or similar `EGL` / `DMABuf` related messages printed to the console and are only getting a white screen to render, you can try launching GitButler with the following environment variables: - -- `WEBKIT_DISABLE_DMABUF_RENDERER=1` -- `WEBKIT_DISABLE_COMPOSITING_MODE=1` - -This issue most likely stems from an incompatibility between your version of OpenGL (`mesa`) and `libwebkit2gtk-4.1`. - - -# upstream-integration.mdx - -Sometimes you work on a branch and someone else pushes to the same upstream branch. Often you won't know this until you try to push and Git tells you something like this: - - - -In this scenario, GitButler gives you some nice tooling to help you know when this happens as early as possible and help you deal with it easily. - -If someone else has pushed to a branch that you're working on, you will see the upstream commits without having to integrate them. You can look at the commits without having to merge them into your branch or rebase your work on top of them. - - - -When you decide that you do want to integrate the changes, you have two options - rebase or interactively integrate. - -## Rebase the changes - -If you select "Rebase upstream changes", it will do the equivalent of a `git pull --rebase` which rebases the commits you have locally on top of the ones that the other person has pushed, so you end up with a state like this: - - - -Now you can push your commit back upstream without a force push. Easy peasy. - -## Interactively integrate the changes - -However, let's say that you want to do something more complex. Maybe the other implemented the same thing that you did and you want to drop one of them or one of yours, or squash commits together or reorder them. In any of these cases, you can choose the "Interactive integration" option and you get something that looks like this: - - - -Here you can reorder commits however you want, you can choose to skip some of them, you can squash some of them down, etc. Just make the commits look however you prefer and then hit the "Integrate changes" button and push your final result back to the server. +If you start GitButler from the command line and see a bunch of these or similar `EGL` / `DMABuf` related messages printed to the console and are only getting a white screen to render, you can try launching GitButler with the following environment variables: + +- `WEBKIT_DISABLE_DMABUF_RENDERER=1` +- `WEBKIT_DISABLE_COMPOSITING_MODE=1` + +This issue most likely stems from an incompatibility between your version of OpenGL (`mesa`) and `libwebkit2gtk-4.1`. # contact-us.mdx @@ -3293,6 +3128,91 @@ There are a few ways to get in touch with us for feedback, bug reports, feature +# claude-code-hooks.mdx + +If you are using Claude Code, you can use the new ["hooks"](https://docs.anthropic.com/en/docs/claude-code/hooks) functionality to manage the output of even multiple simultaneous instances, while isolating all the generated code into virtual or stacked branches automatically. In this case, there is no need to set up the MCP server, as the hooks will handle everything for you. + +Here's a short video showing how GitButler works with Claude Code: + +https://youtu.be/AwwPwSc9qhA + +Ok, let's get it set up. + +## Install the GitButler CLI + +First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](./mcp-server) for more details on how to install the CLI. + +## Installing GitButler as a Hook + +Hooks in Claude Code are defined in one of your settings files. + +``` +~/.claude/settings.json - User settings +.claude/settings.json - Project settings +.claude/settings.local.json - Local project settings (not committed) +``` + +Wherever you want to add GitButler to handle your commits automatically, you can add us as a hook by adding the following to the `hooks` array in whatever settings file you want to use: + +```json +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Edit|MultiEdit|Write", + "hooks": [ + { + "type": "command", + "command": "but claude pre-tool" + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Edit|MultiEdit|Write", + "hooks": [ + { + "type": "command", + "command": "but claude post-tool" + } + ] + } + ], + "Stop": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "but claude stop" + } + ] + } + ] + } +} +``` + +Essentially, you want to run the `but claude pre-tool` command before any code generation or editing, and the `but claude post-tool` command after it. The `but claude stop` command will run when you stop the agent, ensuring that all changes are committed and branches are updated accordingly. + +You also might want to add to your "memories" to ask Claude not to try commiting using Git as it will be handled by GitButler. You can do something like this: + +``` +❯ cat ~/.claude/CLAUDE.md +## Development Workflow +- Never use the git commit command after a task is finished. +``` + +## Using GitButler with Claude Code + +With the hooks setup, Claude will tell GitButler when it has generated code or edited files and in which session, which helps GitButler to try to isolate the changes into a single branch per session. + +For example, if you have three sessions of Claude Code running at the same time, each will be communicating with GitButler at each step and GitButler will be assigning each change to the correct branch automatically. + +When the agent is done, GitButler will commit all the changes and write a more sophisticated commit message based on what you had prompted your agent. + + # open-source.mdx GitButler is a [Fair Source software project](https://blog.gitbutler.com/gitbutler-is-now-fair-source/), built on a vast foundation of open source software. We're committed to giving back to the community and supporting the projects that we rely on. @@ -3340,24 +3260,65 @@ Thanks, from the GitButler Crew! +# but-absorb.mdx + +The semantic for finding "the appropriate commit" is as follows: + +- If a change has a dependency to a particular commit, it will be amended into that particular commit +- If a change is staged to a particular lane (branch), it will be amended into a commit there +- If there are no commits in this branch, a new commit is created +- Changes are amended into the topmost commit of the leftmost (first) lane (branch) + +Optionally an identifier to an Uncommitted File or a Branch (stack) may be provided. + +- If an Uncommitted File id is provided, absorb will be performed for just that file +- If a Branch (stack) id is provided, absorb will be performed for all changes staged to that stack +- If no source is provided, absorb is performed for all uncommitted changes + +If `--dry-run` is specified, no changes will be made; instead, the absorption plan +(what changes would be absorbed by which commits) will be shown. + +If `--new` is specified, new commits will be created for absorbed changes +instead of amending existing commits. + +**Usage:** `but absorb [SOURCE] [OPTIONS]` + +## Arguments + +* `` — If the Source is an uncommitted change - the change will be absorbed. If the Source is a stack - anything staged to the stack will be absorbed accordingly. If not provided, everything that is uncommitted will be absorbed + +## Options + +* `--dry-run` — Show the absorption plan without making any changes +* `-n`, `--new` — Create new commits, instead of amending existing ones. This is useful when you want to preserve existing commits and add new ones for the absorbed changes + + + # but-alias.mdx -Aliases allow you to create shortcuts for commonly used commands. They are stored in git config under the but.alias.* namespace. +Aliases allow you to create shortcuts for commonly used commands. +They are stored in git config under the `but.alias.*` namespace. -Examples +## Examples List all configured aliases: - but alias +```text +but alias +``` Create a new alias: - but alias add st status - but alias add stv "status --verbose" +```text +but alias add st status +but alias add stv "status --verbose" +``` Remove an alias: - but alias remove st +```text +but alias remove st +``` **Usage:** `but alias ` @@ -3415,16 +3376,6 @@ Examples * `-g`, `--global` — Remove from global config (in ~/.gitconfig) instead of local -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - # but-amend.mdx @@ -3438,24 +3389,147 @@ Wrapper for `but rub `. * `` — File ID to amend (required) * `` — Commit ID to amend into (required) -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# but-apply.mdx + +If you want to apply an unapplied branch to your workspace so you +can work on it, you can run `but apply `. + +This will apply the changes in that branch into your working directory +as a parallel applied branch. + +## Examples + +Apply by branch name: + +```text +but apply my-feature-branch +``` + +**Usage:** `but apply ` + +## Arguments + +* `` — Name of the branch to apply (required) + + + +# but-commit.mdx + +The `but commit` command allows you to create a new commit +on a specified branch (stack) with the current uncommitted changes. + +If there is only one branch applied, it will commit to that branch by default. + +If there are multiple branches applied, you must specify which branch to +commit to, or if in interactive mode, you will be prompted to select one. + +By default, all uncommitted changes and all changes already staged to that +branch will be included in the commit. If you only want to commit the changes +that are already staged to that branch, you can use the `--only` flag. + +It will not commit changes staged to other branches. + +Use `but commit empty --before ` or `but commit empty --after ` +to insert a blank commit. This is useful for creating a placeholder +commit that you can amend changes into later using `but mark`, `but rub` or `but absorb`. + +**Usage:** `but commit [BRANCH] [OPTIONS]` + +## Subcommands + +### `but commit empty` + +Insert a blank commit before or after the specified commit. + +This is useful for creating a placeholder commit that you can +then amend changes into later using `but mark`, `but rub` or `but absorb`. + +You can modify the empty commit message at any time using `but reword`. + +This allows for a more Jujutsu style workflow where you create commits +first and then fill them in as you work. Create an empty commit, mark it +for auto-commit, and then just work on your changes. Write the commit +message whenever you prefer. + +## Examples + +Insert at the top of the first branch (no arguments): + +```text +but commit empty +``` + +Insert before a commit: + +```text +but commit empty ab +``` + +Explicitly insert before a commit: + +```text +but commit empty --before ab +``` + +Insert after a commit (at the top of the stack if target is a branch): + +```text +but commit empty --after ab +``` + +**Usage:** `but commit empty [TARGET] [OPTIONS]` + +**Arguments:** + +* `` — The target commit or branch to insert relative to. + +If a target is provided without --before or --after, defaults to --before behavior. If no arguments are provided at all, inserts at the top of the first branch. + +**Options:** + +* `--before` `` — Insert the blank commit before this commit or branch +* `--after` `` — Insert the blank commit after this commit or branch + +## Options + +* `-m`, `--message` `` — Commit message +* `--message-file` `` — Read commit message from file +* `-c`, `--create` — Whether to create a new branch for this commit. If the branch name given matches an existing branch, that branch will be used instead. If no branch name is given, a new branch with a generated name will be created +* `-o`, `--only` — Only commit staged files, not unstaged files +* `-n`, `--no-hooks` — Bypass pre-commit hooks +* `-i`, `--ai` `` — Generate commit message using AI with optional user summary. Use --ai by itself or --ai="your instructions" (equals sign required for value) +* `-p`, `--changes` `` — Uncommitted file or hunk CLI IDs to include in the commit. Can be specified multiple times or as comma-separated values. If not specified, all uncommitted changes (or changes staged to the target branch) are committed + + + +# but-diff.mdx + +Without any arguments, it shows the diff of all uncommitted changes. +Optionally, a CLI ID argument can be provided, which chan show the diff specific to +- an uncommitted file +- a branch +- an entire stack +- a commit +- a file change within a commit + +**Usage:** `but diff [TARGET]` + +## Arguments -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `` — The CLI ID of the entity to show the diff for # but-branch.mdx -This includes creating, deleting, listing, showing details about, and applying and unapplying branches. +This includes creating, deleting, listing, and showing details about branches. By default without a subcommand, it will list the branches. +To apply or unapply branches, use `but apply` and `but unapply`. + **Usage:** `but branch ` ## Subcommands @@ -3559,125 +3633,70 @@ You can also choose to fetch and display review information, show files modified * `--ai` — Generate AI summary of the branch changes * `--check` — Check if the branch merges cleanly into upstream and identify conflicting commits -### `but branch apply` -Apply a branch to the workspace -If you want to apply an unapplied branch to your workspace so you -can work on it, you can run `but branch apply `. - -This will apply the changes in that branch into your working directory -as a parallel applied branch. - -**Usage:** `but branch apply ` - -**Arguments:** - -* `` — Name of the branch to apply (required) - -### `but branch unapply` - -Unapply a branch from the workspace - -If you want to unapply an applied branch from your workspace -(effectively stashing it) so you can work on other branches, -you can run `but branch unapply `. - -This will remove the changes in that branch from your working -directory and you can re-apply it later when needed. You will then -see the branch as unapplied in `but branch list`. - -**Usage:** `but branch unapply [OPTIONS]` - -**Arguments:** - -* `` — Name of the branch to unapply (required) - -**Options:** - -* `-f`, `--force` — Force unapply without confirmation - -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - - - -# but-absorb.mdx - -The semantic for finding "the appropriate commit" is as follows: +# but-discard.mdx -- If a change has a dependency to a particular commit, it will be amended into that particular commit -- If a change is staged to a particular lane (branch), it will be amended into a commit there -- If there are no commits in this branch, a new commit is created -- Changes are amended into the topmost commit of the leftmost (first) lane (branch) +This command permanently discards changes to files, restoring them to their +state in the HEAD commit. Use this to undo unwanted modifications. -Optionally an identifier to an Uncommitted File or a Branch (stack) may be provided. +The ID parameter should be a file ID as shown in `but status`. You can +discard a whole file or specific hunks within a file. -- If an Uncommitted File id is provided, absorb will be performed for just that file -- If a Branch (stack) id is provided, absorb will be performed for all changes staged to that stack -- If no source is provided, absorb is performed for all uncommitted changes +## Examples -If --dry-run is specified, no changes will be made; instead, the absorption plan (what changes would be absorbed by which commits) will be shown. +Discard all changes to a file: -If --new is specified, new commits will be created for absorbed changes instead of amending existing commits. +```text +but discard a1 +``` -**Usage:** `but absorb [SOURCE] [OPTIONS]` +**Usage:** `but discard ` ## Arguments -* `` — If the Source is an uncommitted change - the change will be absorbed. If the Source is a stack - anything staged to the stack will be absorbed accordingly. If not provided, everything that is uncommitted will be absorbed - -## Options - -* `--dry-run` — Show the absorption plan without making any changes -* `-n`, `--new` — Create new commits, instead of amending existing ones. This is useful when you want to preserve existing commits and add new ones for the absorbed changes - -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `` — The ID of the file or hunk to discard (as shown in but status) (required) # but-config.mdx -Without a subcommand, displays an overview of important settings including user information, target branch, forge configuration, and AI setup. +Without a subcommand, displays an overview of important settings including +user information, target branch, forge configuration, and AI setup. -Examples +## Examples View configuration overview: - but config +```text +but config +``` View/set user configuration: - but config user - but config user set name "John Doe" - but config user set email john@example.com +```text +but config user +but config user set name "John Doe" +but config user set email john@example.com +``` View/set forge configuration: - but config forge +```text +but config forge +``` View/set target branch: - but config target +```text +but config target +``` View/set metrics: - but config metrics +```text +but config metrics +``` **Usage:** `but config ` @@ -3722,281 +3741,85 @@ View configured forge accounts: but config forge -Authenticate with a forge: - - but config forge auth - -List authenticated accounts: - - but config forge list-users - -Forget an account: - - but config forge forget username - - -**Usage:** `but config forge` - -### `but config target` - -View or set the target branch. - -Without arguments, displays the current target branch. With a branch name, sets the target branch. - -Examples - -View current target: - - but config target - -Set target branch: - - but config target origin/main - - -**Usage:** `but config target [BRANCH]` - -**Arguments:** - -* `` — New target branch to set (e.g., "origin/main") - -### `but config metrics` - -View or set metrics collection. - -GitButler uses metrics to help us know what is useful and improve it. Privacy policy: https://gitbutler.com/privacy - -Without arguments, displays the current setting. - -Examples - -View metrics configuration: - - but config metrics - -Enable metrics: - - but config metrics enable - -Disable metrics: - - but config metrics disable - - -**Usage:** `but config metrics [STATUS]` - -**Arguments:** - -* `` — Whether metrics are enabled - -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - - - -# but-commit.mdx - -The `but commit` command allows you to create a new commit -on a specified branch (stack) with the current uncommitted changes. - -If there is only one branch applied, it will commit to that branch by default. - -If there are multiple branches applied, you must specify which branch to -commit to, or if in interactive mode, you will be prompted to select one. - -By default, all uncommitted changes and all changes already staged to that -branch will be included in the commit. If you only want to commit the changes -that are already staged to that branch, you can use the `--only` flag. - -It will not commit changes staged to other branches. - -Use `but commit empty --before ` or `but commit empty --after ` -to insert a blank commit. This is useful for creating a placeholder -commit that you can amend changes into later using `but mark`, `but rub` or `but absorb`. - -**Usage:** `but commit [BRANCH] [OPTIONS]` - -## Subcommands - -### `but commit empty` - -Insert a blank commit before or after the specified commit. - -This is useful for creating a placeholder commit that you can -then amend changes into later using `but mark`, `but rub` or `but absorb`. - -You can modify the empty commit message at any time using `but reword`. - -This allows for a more Jujutsu style workflow where you create commits -first and then fill them in as you work. Create an empty commit, mark it -for auto-commit, and then just work on your changes. Write the commit -message whenever you prefer. - -## Examples - -Insert at the top of the first branch (no arguments): - -```text -but commit empty -``` - -Insert before a commit: - -```text -but commit empty ab -``` - -Explicitly insert before a commit: - -```text -but commit empty --before ab -``` - -Insert after a commit (at the top of the stack if target is a branch): - -```text -but commit empty --after ab -``` - -**Usage:** `but commit empty [TARGET] [OPTIONS]` - -**Arguments:** - -* `` — The target commit or branch to insert relative to. - -If a target is provided without --before or --after, defaults to --before behavior. If no arguments are provided at all, inserts at the top of the first branch. - -**Options:** - -* `--before` `` — Insert the blank commit before this commit or branch -* `--after` `` — Insert the blank commit after this commit or branch - -## Arguments - -* `` — Branch CLI ID or name to derive the stack to commit to - -## Options - -* `-m`, `--message` `` — Commit message -* `-f`, `--file` `` — Read commit message from file -* `-c`, `--create` — Whether to create a new branch for this commit. If the branch name given matches an existing branch, that branch will be used instead. If no branch name is given, a new branch with a generated name will be created -* `-o`, `--only` — Only commit staged files, not unstaged files -* `-n`, `--no-hooks` — Bypass pre-commit hooks -* `-i`, `--ai` `` — Generate commit message using AI with optional user summary -* `-F`, `--files` `` — Uncommitted file or hunk CLI IDs to include in the commit. Can be specified multiple times or as comma-separated values. If not specified, all uncommitted changes (or changes staged to the target branch) are committed - -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-j`, `--json` — Whether to use JSON output format - - - -# but-diff.mdx - -Without any arguments, it shows the diff of all uncommitted changes. Optionally, a CLI ID argument can be provided, which chan show the diff specific to - -- an uncommitted file -- a branch -- an entire stack -- a commit -- a file change within a commit - -**Usage:** `but diff [TARGET]` +Authenticate with a forge: -## Arguments + but config forge auth -* `` — The CLI ID of the entity to show the diff for +List authenticated accounts: -## Platform Options + but config forge list-users -These options are available for all `but` commands: +Forget an account: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. + but config forge forget username -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +**Usage:** `but config forge` +### `but config target` -# but-gui.mdx +View or set the target branch. -Running but gui will launch the GitButler graphical user interface in the current directory's GitButler project. +Without arguments, displays the current target branch. With a branch name, sets the target branch. -This provides a visual way to manage branches, commits, and uncommitted changes, complementing the command-line interface. +Examples -You can also just run but . as a shorthand to open the GUI. +View current target: -**Usage:** `but gui` + but config target -## Platform Options +Set target branch: -These options are available for all `but` commands: + but config target origin/main -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +**Usage:** `but config target [BRANCH]` +**Arguments:** +* `` — New target branch to set (e.g., "origin/main") -# but-merge.mdx +### `but config metrics` -If the target branch is local (`gb-local`), finds the local branch that the target -references (e.g., `gb-local/master` becomes `master`) and merges the specified -branch into that local branch. After merging, runs the equivalent of `but pull` -to update all branches. +View or set metrics collection. -## Examples +GitButler uses metrics to help us know what is useful and improve it. Privacy policy: https://gitbutler.com/privacy -Merge a branch by its CLI ID: +Without arguments, displays the current setting. -```text -but merge bu -``` +Examples -Merge a branch by name: +View metrics configuration: -```text -but merge my-feature-branch -``` + but config metrics -**Usage:** `but merge ` +Enable metrics: -## Arguments + but config metrics enable -* `` — Branch ID or name to merge (required) +Disable metrics: + + but config metrics disable -## Platform Options -These options are available for all `but` commands: +**Usage:** `but config metrics [STATUS]` -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +**Arguments:** -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `` — Whether metrics are enabled # but-mark.mdx -Creates or removes a rule for auto-staging or auto-committing changes to the specified target entity. +Creates or removes a rule for auto-staging or auto-committing changes +to the specified target entity. -If you mark a branch, new unstaged changes that GitButler sees when you run any command will be automatically staged to that branch. +If you mark a branch, new unstaged changes that GitButler sees when +you run any command will be automatically staged to that branch. -If you mark a commit, new uncommitted changes will automatically be amended into the marked commit. +If you mark a commit, new uncommitted changes will automatically be +amended into the marked commit. **Usage:** `but mark [OPTIONS]` @@ -4008,45 +3831,59 @@ If you mark a commit, new uncommitted changes will automatically be amended into * `-d`, `--delete` — Deletes a mark -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# but-gui.mdx -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +Running `but gui` will launch the GitButler graphical user interface +in the current directory's GitButler project. +This provides a visual way to manage branches, commits, and uncommitted +changes, complementing the command-line interface. +You can also just run `but .` as a shorthand to open the GUI. -# but-discard.mdx +**Usage:** `but gui` -This command permanently discards changes to files, restoring them to their state in the HEAD commit. Use this to undo unwanted modifications. -The ID parameter should be a file ID as shown in but status. You can discard a whole file or specific hunks within a file. -Examples +# but-move.mdx -Discard all changes to a file: +By default, commits are moved to be before (below) the target. +Use `--after` to move the commit after (above) the target instead. - but discard a1 +When moving to a branch, the commit is placed at the top of that branch's stack. -**Usage:** `but discard ` +## Examples -## Arguments +Move a commit before another commit: -* `` — The ID of the file or hunk to discard (as shown in but status) (required) +```text +but move abc123 def456 +``` + +Move a commit after another commit: + +```text +but move abc123 def456 --after +``` + +Move a commit to a different branch (places at top): + +```text +but move abc123 my-feature-branch +``` + +**Usage:** `but move [OPTIONS]` -## Platform Options +## Arguments -These options are available for all `but` commands: +* `` — Commit ID to move (required) +* `` — Target commit ID or branch name (required) -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +## Options -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `-a`, `--after` — Move the commit after (above) the target instead of before (below) @@ -4119,157 +3956,153 @@ which you can find by running `but oplog` or `but oplog list`. * `-f`, `--force` — Skip confirmation prompt -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +# but-pick.mdx -# but-move.mdx +This command allows you to pick individual commits from unapplied branches +and apply them to your current workspace branches. -By default, commits are moved to be before (below) the target. Use --after to move the commit after (above) the target instead. +The source can be: +- A commit SHA (full or short) +- A CLI ID (e.g., "c5" from `but status`) +- An unapplied branch name (shows interactive commit selection) -When moving to a branch, the commit is placed at the top of that branch's stack. +If no target branch is specified: +- In interactive mode: prompts you to select a target branch +- If only one branch exists: automatically uses that branch +- In non-interactive mode: fails with an error -Examples +## Examples -Move a commit before another commit: +Pick a specific commit into a branch: - but move abc123 def456 +```text +but pick abc1234 my-feature +``` -Move a commit after another commit: +Pick using a CLI ID: - but move abc123 def456 --after +```text +but pick c5 my-feature +``` -Move a commit to a different branch (places at top): +Interactively select commits from an unapplied branch: - but move abc123 my-feature-branch +```text +but pick feature-branch +``` -**Usage:** `but move [OPTIONS]` +**Usage:** `but pick [TARGET_BRANCH]` ## Arguments -* `` — Commit ID to move (required) -* `` — Target commit ID or branch name (required) - -## Options - -* `-a`, `--after` — Move the commit after (above) the target instead of before (below) +* `` — The commit SHA, CLI ID, or unapplied branch name to cherry-pick from (required) +* `` — The target virtual branch to apply the commit(s) to -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# but-pr.mdx -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +If you are authenticated with a forge using but config forge auth, you can use the but pr commands to create pull requests (or merge requests) on the remote repository for your branches. +Running but pr without a subcommand defaults to but pr new, which will prompt you to select a branch to create a PR for. +**Usage:** `but pr ` -# but-pull.mdx +## Subcommands -This fetches the latest changes from the remote and rebases all applied branches -on top of the updated target branch. +### `but pr new` -You should run this regularly to keep your branches up to date with the latest -changes from the main development line. +Create a new pull request for a branch. If no branch is specified, you will be prompted to select one. If there is only one branch without a PR, you will be asked to confirm -You can run `but pull --check` first to see if your branches can be cleanly -merged into the target branch before running the update. +**Usage:** `but pr new [BRANCH] [OPTIONS]` -**Usage:** `but pull [OPTIONS]` +**Arguments:** -## Options +* `` — The branch to create a PR for -* `-c`, `--check` — Only check the status without updating (equivalent to the old but base check) +**Options:** -## Platform Options +* `-m`, `--message` `` — PR title and description. The first line is the title, the rest is the description +* `-F`, `--file` `` — Read PR title and description from file. The first line is the title, the rest is the description +* `-f`, `--with-force` — Force push even if it's not fast-forward (defaults to true) (default: `true`) +* `-s`, `--skip-force-push-protection` — Skip force push protection checks +* `-r`, `--run-hooks` — Run pre-push hooks (defaults to true) (default: `true`) +* `-t`, `--default` — Use the default content for the PR title and description, skipping any prompts. If the branch contains only a single commit, the commit message will be used (default: `false`) -These options are available for all `but` commands: +### `but pr template` -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +Configure the template to use for PR descriptions. This will list all available templates found in the repository and allow you to select one -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +**Usage:** `but pr template [TEMPLATE_PATH]` +**Arguments:** +* `` — Path to the PR template file within the repository -# but-pick.mdx -This command allows you to pick individual commits from unapplied branches -and apply them to your current workspace branches. -The source can be: -- A commit SHA (full or short) -- A CLI ID (e.g., "c5" from `but status`) -- An unapplied branch name (shows interactive commit selection) +# but-merge.mdx -If no target branch is specified: -- In interactive mode: prompts you to select a target branch -- If only one branch exists: automatically uses that branch -- In non-interactive mode: fails with an error +If the target branch is local (`gb-local`), finds the local branch that the target +references (e.g., `gb-local/master` becomes `master`) and merges the specified +branch into that local branch. After merging, runs the equivalent of `but pull` +to update all branches. ## Examples -Pick a specific commit into a branch: +Merge a branch by its CLI ID: ```text -but pick abc1234 my-feature +but merge bu ``` -Pick using a CLI ID: +Merge a branch by name: ```text -but pick c5 my-feature +but merge my-feature-branch ``` -Interactively select commits from an unapplied branch: +**Usage:** `but merge ` -```text -but pick feature-branch -``` +## Arguments -**Usage:** `but pick [TARGET_BRANCH]` +* `` — Branch ID or name to merge (required) -## Arguments -* `` — The commit SHA, CLI ID, or unapplied branch name to cherry-pick from (required) -* `` — The target virtual branch to apply the commit(s) to -## Platform Options +# but-pull.mdx + +This fetches the latest changes from the remote and rebases all applied branches +on top of the updated target branch. + +You should run this regularly to keep your branches up to date with the latest +changes from the main development line. + +You can run `but pull --check` first to see if your branches can be cleanly +merged into the target branch before running the update. -These options are available for all `but` commands: +**Usage:** `but pull [OPTIONS]` -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +## Options -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `-c`, `--check` — Only check the status without updating (equivalent to the old but base check) # but-push.mdx -but push will update the remote with the latest commits from the applied branch(es). +`but push` will update the remote with the latest commits from the +applied branch(es). Without a branch ID: - - Interactive mode: Lists all branches with unpushed commits and prompts for selection - Non-interactive mode: Automatically pushes all branches with unpushed commits With a branch ID: - -- but push bu - push the branch with CLI ID "bu" -- but push feature-branch - push the branch named "feature-branch" +- `but push bu` - push the branch with CLI ID "bu" +- `but push feature-branch` - push the branch named "feature-branch" **Usage:** `but push [BRANCH_ID] [OPTIONS]` @@ -4284,12 +4117,29 @@ With a branch ID: * `-r`, `--run-hooks` — Run pre-push hooks (default: `true`) * `-d`, `--dry-run` — Show what would be pushed without actually pushing -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-j`, `--json` — Whether to use JSON output format +# but-reword.mdx + +You can easily change the commit message of any of your commits by +running `but reword ` and providing a new message in the +editor. + +This will rewrite the commit with the new message and then rebase any +dependent commits on top of it. + +You can also use `but reword ` to rename the branch. + +**Usage:** `but reword [OPTIONS]` + +## Arguments + +* `` — Commit ID to edit the message for, or branch ID to rename (required) + +## Options + +* `-m`, `--message` `` — The new commit message or branch name. If not provided, opens an editor +* `-f`, `--format` — Format the existing commit message to 72-char line wrapping without opening an editor @@ -4334,81 +4184,88 @@ This discards all changes made during resolution and restores the workspace to i **Usage:** `but resolve cancel` -## Arguments - -* `` — Commit ID to enter resolution mode for (when no subcommand is provided) - -## Platform Options - -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - - - -# but-reword.mdx +# but-setup.mdx -You can easily change the commit message of any of your commits by -running `but reword ` and providing a new message in the -editor. +This command will: +- Add the repository to the global GitButler project registry +- Switch to the gitbutler/workspace branch (if not already on it) +- Set up a default target branch (the remote's HEAD) +- Add a gb-local remote if no push remote exists -This will rewrite the commit with the new message and then rebase any -dependent commits on top of it. +If you have an existing Git repository and want to start using GitButler +with it, you can run this command to set up the necessary configuration +and data structures. -You can also use `but reword ` to rename the branch. +## Examples -**Usage:** `but reword [OPTIONS]` +Initialize a new git repository and set up GitButler: -## Arguments +```text +but setup --init +``` -* `` — Commit ID to edit the message for, or branch ID to rename (required) +**Usage:** `but setup [OPTIONS]` ## Options -* `-m`, `--message` `` — The new commit message or branch name. If not provided, opens an editor -* `-f`, `--format` — Format the existing commit message to 72-char line wrapping without opening an editor +* `--init` — Initialize a new git repository with an empty commit if one doesn't exist. -## Platform Options +This is useful when running in non-interactive environments (like CI/CD) +where you want to ensure a git repository exists before setting up GitButler. -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-j`, `--json` — Whether to use JSON output format +# but-rub.mdx +The `rub` command is a simple verb that helps you do a number of editing +operations by doing combinations of two things. -# but-rub.mdx +For example, you can "rub" a file onto a branch to stage that file to +the branch. You can also "rub" a commit onto another commit to squash +them together. You can rub a commit onto a branch to move that commit. +You can rub a file from one commit to another. -The rub command is a simple verb that helps you do a number of editing operations by doing combinations of two things. +## Operations Matrix -For example, you can "rub" a file onto a branch to stage that file to the branch. You can also "rub" a commit onto another commit to squash them together. You can rub a commit onto a branch to move that commit. You can rub a file from one commit to another. +Each cell shows what happens when you rub SOURCE → TARGET: -Non-exhaustive list of operations: +```text +SOURCE ↓ / TARGET → │ zz (unassigned) │ Commit │ Branch │ Stack +─────────────────────┼─────────────────┼────────────┼─────────────┼──────────── +File/Hunk │ Unstage │ Amend │ Stage │ Stage +Commit │ Undo │ Squash │ Move │ - +Branch (all changes) │ Unstage all │ Amend all │ Reassign │ Reassign +Stack (all changes) │ Unstage all │ - │ Reassign │ Reassign +Unassigned (zz) │ - │ Amend all │ Stage all │ Stage all +File-in-Commit │ Uncommit │ Move │ Uncommit to │ - +``` - │Source │Target - ──────┼───────────┼────── - Amend │File,Branch│Commit - Squash│Commit │Commit - Stage │File,Branch│Branch - Move │Commit │Branch +Legend: +- `zz` is a special target meaning "unassigned" (no branch) +- `-` means the operation is not supported +- "all changes" / "all" refers to all uncommitted changes from that source -Examples +## Examples Squashing two commits into one (combining the commit messages): - but rub 3868155 abe3f53f +```text +but rub 3868155 abe3f53f +``` Amending a commit with the contents of a modified file: - but rub README.md abe3f53f +```text +but rub README.md abe3f53f +``` Moving a commit from one branch to another: - but rub 3868155 feature-branch +```text +but rub 3868155 feature-branch +``` **Usage:** `but rub ` @@ -4417,41 +4274,41 @@ Moving a commit from one branch to another: * `` — The source entity to combine (required) * `` — The target entity to combine with the source (required) -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - # but-show.mdx -When given a commit ID, displays the full commit message, author information, committer information (if different from author), and the list of files modified. +When given a commit ID, displays the full commit message, author information, +committer information (if different from author), and the list of files modified. -When given a branch name, displays the branch name and a list of all commits on that branch. Use --verbose to show full commit messages and files changed. +When given a branch name, displays the branch name and a list of all commits +on that branch. Use --verbose to show full commit messages and files changed. -Examples +## Examples Show commit details by short commit ID: - but show a1b2c3d +```text +but show a1b2c3d +``` Show commit details by CLI ID: - but show c5 +```text +but show c5 +``` Show branch commits by branch name: - but show my-feature-branch +```text +but show my-feature-branch +``` Show branch with full commit details: - but show my-feature-branch --verbose +```text +but show my-feature-branch --verbose +``` **Usage:** `but show [OPTIONS]` @@ -4463,52 +4320,42 @@ Show branch with full commit details: * `-v`, `--verbose` — Show full commit messages and files changed for each commit -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# but-stage.mdx -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +Wrapper for `but rub `. +**Usage:** `but stage ` +## Arguments -# but-setup.mdx +* `` — File or hunk ID to stage (required) +* `` — Branch ID to stage to (required) -This command will: -- Add the repository to the global GitButler project registry -- Switch to the gitbutler/workspace branch (if not already on it) -- Set up a default target branch (the remote's HEAD) -- Add a gb-local remote if no push remote exists -If you have an existing Git repository and want to start using GitButler with it, you can run this command to set up the necessary configuration and data structures. +# but-squash.mdx -Examples +Can be invoked in three ways: +1. Using commit identifiers: `but squash ` or `but squash ...` + - Squashes all commits except the last into the last commit +2. Using a commit range: `but squash ..` + - Squashes all commits in the range into the last commit in the range +3. Using a branch name: `but squash ` + - Squashes all commits in the branch into the bottom-most commit -Initialize a new git repository and set up GitButler: +**Usage:** `but squash [COMMITS] [OPTIONS]` - but setup --init +## Arguments -**Usage:** `but setup [OPTIONS]` +* `` — Commit identifiers, a range (commit1..commit2), or a branch name ## Options -* `--init` — Initialize a new git repository with an empty commit if one doesn't exist. - -This is useful when running in non-interactive environments (like CI/CD) where you want to ensure a git repository exists before setting up GitButler. - -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `-d`, `--drop-message` — Drop source commit messages and keep only the target commit's message +* `-m`, `--message` `` — Provide a new commit message for the resulting commit +* `-i`, `--ai` `` — Generate commit message using AI with optional user summary or instructions. Use --ai by itself or --ai="your instructions" (equals sign required for value) @@ -4542,28 +4389,38 @@ but skill install --global Install the GitButler CLI skill files for Coding agents -By default, installs the skill into the current repository. The command will prompt you to select a skill folder format (Claude Code, OpenCode, Codex, GitHub Copilot, Cursor, Windsurf) unless you specify a custom path with --path. +By default, installs the skill into the current repository. The command +will prompt you to select a skill folder format (Claude Code, OpenCode, Codex, GitHub Copilot, +Cursor, Windsurf) unless you specify a custom path with --path. -Use --global to install the skill in a global location instead of the current repository. +Use --global to install the skill in a global location instead of the +current repository. -Examples +## Examples Install in current repository (prompts for format): - but skill install +```text +but skill install +``` Install globally (prompts for format): - but skill install --global +```text +but skill install --global +``` Install to a custom path: - but skill install --path .claude/skills/gitbutler +```text +but skill install --path .claude/skills/gitbutler +``` Auto-detect installation location (update existing installation): - but skill install --detect - +```text +but skill install --detect +``` **Usage:** `but skill install [OPTIONS]` @@ -4577,22 +4434,28 @@ Auto-detect installation location (update existing installation): Check if installed GitButler skills are up to date with the CLI version -Scans for installed skill files and compares their version with the current CLI version. By default, checks both local (repository) and global installations. +Scans for installed skill files and compares their version with the current +CLI version. By default, checks both local (repository) and global installations. -Examples +## Examples Check all installed skills: - but skill check +```text +but skill check +``` Check and automatically update outdated skills: - but skill check --update +```text +but skill check --update +``` Check only global installations: - but skill check --global - +```text +but skill check --global +``` **Usage:** `but skill check [OPTIONS]` @@ -4602,141 +4465,88 @@ Check only global installations: * `-l`, `--local` — Only check local installations (in current repository) * `-u`, `--update` — Automatically update any outdated skills found -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - - - -# but-squash.mdx - -Can be invoked in three ways: -1. Using commit identifiers: `but squash ` or `but squash ...` - - Squashes all commits except the last into the last commit -2. Using a commit range: `but squash ..` - - Squashes all commits in the range into the last commit in the range -3. Using a branch name: `but squash ` - - Squashes all commits in the branch into the bottom-most commit - -**Usage:** `but squash [COMMITS] [OPTIONS]` - -## Arguments - -* `` — Commit identifiers, a range (commit1..commit2), or a branch name - -## Options - -* `-d`, `--drop-message` — Drop source commit messages and keep only the target commit's message -* `-m`, `--message` `` — Provide a new commit message for the resulting commit -* `-i`, `--ai` `` — Generate commit message using AI with optional user summary or instructions - -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format - - - -# but-pr.mdx - -If you are authenticated with a forge using but config forge auth, you can use the but pr commands to create pull requests (or merge requests) on the remote repository for your branches. - -Running but pr without a subcommand defaults to but pr new, which will prompt you to select a branch to create a PR for. - -**Usage:** `but pr ` - -## Subcommands -### `but pr new` -Create a new pull request for a branch. If no branch is specified, you will be prompted to select one. If there is only one branch without a PR, you will be asked to confirm +# but-teardown.mdx -**Usage:** `but pr new [BRANCH] [OPTIONS]` +This command: +- Creates an oplog snapshot of the current state +- Finds the first active branch and checks it out +- Cherry-picks any dangling commits from gitbutler/workspace +- Provides instructions on how to return to GitButler mode -**Arguments:** +This is useful when you want to temporarily or permanently leave GitButler +management and work with standard Git commands. -* `` — The branch to create a PR for +## Examples -**Options:** +Exit GitButler mode: -* `-m`, `--message` `` — PR title and description. The first line is the title, the rest is the description -* `-F`, `--file` `` — Read PR title and description from file. The first line is the title, the rest is the description -* `-f`, `--with-force` — Force push even if it's not fast-forward (defaults to true) (default: `true`) -* `-s`, `--skip-force-push-protection` — Skip force push protection checks -* `-r`, `--run-hooks` — Run pre-push hooks (defaults to true) (default: `true`) -* `-t`, `--default` — Use the default content for the PR title and description, skipping any prompts. If the branch contains only a single commit, the commit message will be used (default: `false`) +```text +but teardown +``` -### `but pr template` +**Usage:** `but teardown` -Configure the template to use for PR descriptions. This will list all available templates found in the repository and allow you to select one -**Usage:** `but pr template [TEMPLATE_PATH]` -**Arguments:** +# but-unapply.mdx -* `` — Path to the PR template file within the repository +If you want to unapply an applied branch from your workspace +(effectively stashing it) so you can work on other branches, +you can run `but unapply `. -## Platform Options +This will remove the changes in that branch from your working +directory and you can re-apply it later when needed. You will then +see the branch as unapplied in `but branch list`. -These options are available for all `but` commands: +The identifier can be: +- A CLI ID pointing to a stack or branch (e.g., "bu" from `but status`) +- A branch name -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +If a branch name (or an identifier pointing to a branch) is provided, +the entire stack containing that branch will be unapplied. -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +## Examples +Unapply by branch name: +```text +but unapply my-feature-branch +``` -# but-stage.mdx +Unapply by CLI ID: -Wrapper for `but rub `. +```text +but unapply bu +``` -**Usage:** `but stage ` +**Usage:** `but unapply [OPTIONS]` ## Arguments -* `` — File or hunk ID to stage (required) -* `` — Branch ID to stage to (required) - -## Platform Options - -These options are available for all `but` commands: +* `` — CLI ID or name of the branch/stack to unapply (required) -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +## Options -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `-f`, `--force` — Force unapply without confirmation # but-undo.mdx -This is a shorthand for restoring to the last oplog entry before the current one. It allows you to quickly undo the most recent operation. +This is a shorthand for restoring to the last oplog entry before the +current one. It allows you to quickly undo the most recent operation. **Usage:** `but undo` -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# but-unmark.mdx + +This will unmark anything that has been marked by the `but mark` command. -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +**Usage:** `but unmark` @@ -4750,46 +4560,38 @@ Wrapper for `but rub zz`. * `` — Commit ID or file-in-commit ID to uncommit (required) -## Platform Options - -These options are available for all `but` commands: - -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. - -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +# but-status.mdx -# but-teardown.mdx - -This command: - -- Creates an oplog snapshot of the current state -- Finds the first active branch and checks it out -- Cherry-picks any dangling commits from gitbutler/workspace -- Provides instructions on how to return to GitButler mode - -This is useful when you want to temporarily or permanently leave GitButler management and work with standard Git commands. +This shows unstaged files, files staged to stacks, all applied +branches (stacked or parallel), commits on each of those branches, +upstream commits that are unintegrated, commit status (pushed or local), +and base branch information. -Examples +## Examples -Exit GitButler mode: +Normal usage: - but teardown +```text +but status +``` -**Usage:** `but teardown` +Shorthand with listing files modified -## Platform Options +```text +but status -f +``` -These options are available for all `but` commands: +**Usage:** `but status [OPTIONS]` -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +## Options -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +* `-f` — Determines whether the committed files should be shown as well (default: `false`) +* `-v`, `--verbose` — Show verbose output with commit author and timestamp (default: `false`) +* `-r`, `--refresh-prs` — Forces a sync of pull requests from the forge before showing status (default: `false`) +* `-u`, `--upstream` — Show detailed list of upstream commits that haven't been integrated yet (default: `false`) +* `--no-hint` — Disable hints about available commands at the end of output (default: `false`) @@ -4837,49 +4639,91 @@ Note: Currently only supported on macOS. For other platforms, download from http Examples: but update install Auto-detect channel and install latest but update install nightly Install latest nightly build but update install release Install latest stable release but update install 0.18.7 Install specific version -## Platform Options -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# installation.mdx -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +How to install and setup the GitButler CLI. +## Installing the `but` CLI +Ok, first thing is first, let's get our `but` CLI installed. Currently there are two ways to do this. -# but-status.mdx +### Via the Desktop Client -This shows unstaged files, files staged to stacks, all applied branches (stacked or parallel), commits on each of those branches, upstream commits that are unintegrated, commit status (pushed or local), and base branch information. +If you have the desktop client installed, you can go into your global settings and click on the "Install CLI" button in the "general" section. -Examples + + +### Curl install + +You can install the CLI by running the following command in your terminal: + +```bash +curl -fsSL https://gitbutler.com/install.sh | sh +``` + +## Setup + +If you go into any existing Git repository and run `but setup`, it will make some neccesary changes to your setup in order for GitButler to manage your data. + +If you run almost any `but` command in an existing Git repository in an interactive terminal, it will ask you if you want to set it up and then run the command you were trying to run. So basically just run `but` anywhere to get started. + +At any time after this, you can run `but teardown` to undo the GitButler changes and go back to being a boring old Git project. It will not remove GitButler metadata, so feel free to go back and forth if you need to. + + +# ai-stuff.mdx + +There are a couple of different ways that the GitButler CLI can use or interact with AI tools. Some are via `--ai` options to commands to use AI to help with tasks, others are ways that coding agents can more easily use the CLI to accomplish tasks. + +## Dash Dash AI + +There are a few commands that will take a `--ai` option to use a configured AI provider to generate something. + +### `but commit --ai` + +Probably the most commonly used would be `but commit --ai`, which will take a look at the changes in the files you're committing and generate an example commit message for you. If you're not feeling like writing anything more than "did some stuff", this could be a nice option for you. + +This will automatically commit the work specified with the generated message, but you can also easily edit it with `but reword ` if you wish. + +### `but squash --ai` + +If you squash two commits together, by default it will simply concatenate the commit messages together, which is rarely what you probably want. You can easily edit the message afterwards, but if you want to let AI try to combine the messages for you, you can give `but squash --ai` a try. -Normal usage: + - but status +We're working on integrating AI features into many more of our commands, so keep an eye out. -Shorthand with listing files modified + - but status -f +## Skills -**Usage:** `but status [OPTIONS]` +If you're using an AI coding agent that can read skills, you can have GitButler automatically install a GitButler specific skill for various agents with `but skill install`. -## Options +```git +❯ but skill install -* `-f` — Determines whether the committed files should be shown as well (default: `false`) -* `-v`, `--verbose` — Show verbose output with commit author and timestamp (default: `false`) -* `-r`, `--refresh-prs` — Forces a sync of pull requests from the forge before showing status (default: `false`) -* `-u`, `--upstream` — Show detailed list of upstream commits that haven't been integrated yet (default: `false`) -* `--no-hint` — Disable hints about available commands at the end of output (default: `false`) +Select a skill folder format: -## Platform Options +? Which format would you like to use?: +> Claude Code - Claude Code CLI skill format (./.claude/skills/gitbutler) + OpenCode - OpenCode AI skill format (./.opencode/skills/gitbutler) + Codex - Codex skill format (./.codex/skills/gitbutler) + GitHub Copilot - GitHub Copilot local (repo) skill format (./.github/skills/gitbutler) + GitHub Copilot - GitHub Copilot global skill format (./.copilot/skills/gitbutler) +``` -These options are available for all `but` commands: +We keep these templates up to date, so if you update GitButler, you may want to update the skills too. -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-j`, `--json` — Whether to use JSON output format +## Hooks and MCP +You can also install explicit hooks or an MCP server if you prefer. You can read more about those options [over here](/features/ai-integration/ai-overview) # commands-overview.mdx @@ -4934,59 +4778,178 @@ These options are available for all `but` commands: - [undo](./but-undo): Undo the last operation by reverting to the previous snapshot -# but-unmark.mdx +# conclusion.mdx -This will unmark anything that has been marked by the but mark command. +Ok, that's a short guide to GitButler's command line interface. -**Usage:** `but unmark` +Join us in [Discord](https://discord.com/invite/MmFkmaJ42D) if you have any other questions or suggestions for how we can improve the tool. -## Platform Options +Thanks! -These options are available for all `but` commands: -* `-C`, `--current-dir` `` — Run as if gitbutler-cli was started in PATH instead of the current working directory (default: `.`) -* `-f`, `--format` `` — Explicitly control how output should be formatted. +# configuration.mdx -If unset and from a terminal, it defaults to human output, when redirected it's for shells. (default: `human`) -* `-j`, `--json` — Whether to use JSON output format +We've already covered `but config` a bit in dealing with forges and target branches. +You can also use it for some basic user configuration, such as setting your name and email address for commits and your default editor. +```cli [configuration-but-config-1, 286px] +but config user +``` -# installation.mdx +## Aliases -How to install and setup the GitButler CLI. +GitButler also has a built in aliasing system in case you want to provide some shorthands. -## Installing the `but` CLI +```cli [configuration-but-alias-1, 286px] +but alias +``` -Ok, first thing is first, let's get our `but` CLI installed. Currently there are two ways to do this. +To add a new alias, you can run `but alias add `, which you can also provide a `-g` or `--global` if you want it to be a global alias. This will put this data in your local or global Git config file. -### Via the Desktop Client +You will notice that there is a `default` alias, which is what runs when you just run `but` with no arguments. If you overwrite the `default` alias, you can set up something other than `status` to run by default. -If you have the desktop client installed, you can go into your global settings and click on the "Install CLI" button in the "general" section. - +# conflict-resolution.mdx -### Curl install +In this world nothing can be said to be certain, except death, taxes and merge conflicts. -You can install the CLI by running the following command in your terminal: +There are several different ways that you can run into merge conflicts when using Git (and thus, GitButler, or any other branching version control system). -```bash -curl -fsSL https://gitbutler.com/install.sh | sh +Perhaps there are changes that have been merged upstream that modified the same files as you did in your branch. Or maybe you uncommitted something that commits above it depended on. + +## First Class Conflicts in GitButler + +First, it's important to understand how GitButler deals with conflicts. While Git generally has to check out conflicts in your working directory and make you resolve them before you can commit, GitButler can partially apply a conflicting change and store the commit marked as "conflicted". + +This means that: + +- Rebases _always_ succeed, just sometimes it results with commits in a conflicted state. +- You can deal with conflicts in any order and at any time. + +So, let's take a look at what this looks like and how we can deal with conflicted commits when they arise. + +{/* restore [e53a4a85d83d] */} +{/* run git push -f origin 96ccca9:main */} + +```cli [conflict-resolution-but-status-1, 396px] +but status ``` -## Setup +Let's say that this is our status and we've decided to pull in from upstream. The changes that have been merged in by someone else upstream conflict with ours. When we run `but pull`, it will result in conflicts in our branch (but it will succeed). -If you go into any existing Git repository and run `but setup`, it will make some neccesary changes to your setup in order for GitButler to manage your data. +```cli [conflict-resolution-but-pull-1, 286px] +but pull +``` -If you run almost any `but` command in an existing Git repository in an interactive terminal, it will ask you if you want to set it up and then run the command you were trying to run. So basically just run `but` anywhere to get started. +Ok, the `pull` tells us that we have conflicts and it also gives us a cheat sheet for what to do to resolve them, which is essentially "run `but resolve`". -At any time after this, you can run `but teardown` to undo the GitButler changes and go back to being a boring old Git project. It will not remove GitButler metadata, so feel free to go back and forth if you need to. +So first let's see what our conflicted branch looks like with `but status`. + +```cli [conflict-resolution-but-status-2, 330px] +but status +``` + +Notice how we have _two_ commits that are conflicted, but one that is not. You could have any number of commits marked as conflicted in a branch, and you'll need to resolve each of them one by one. + +If we were to dig into the details here, a few things have actually happened. + +First of all, we have applied the upstream changes, so if we were to look at the files that conflict, we will see the upstream version rather than what we had done. + +Second, the commits that are not in a conflicted state are still applied - those changes are still in your working directory. In fact, even the conflicted commit's changes will be applied in the areas where they don't conflict. + +You could potentially have several conflicted commits in your branch. When you resolve one, everything above it is rebased and may introduce new conflicts or may resolve other conflicts, depending on the resolution. + +However, for now, let's look at a simple resolution flow. All you really need is one command: `but resolve`. + +If you run `but resolve`, it will look through all your applied branches for any conflicted commits. If it finds any, it will list them out and ask you which you want to start with and default to the lowest one on the first branch. + +```git +❯ but resolve +Found conflicted commits: + +Branch: update-homepage + ● 42165fe branding change: readme + ● 404b604 hero update - new branding + +Would you like to start resolving these conflicts? +Enter commit ID to resolve [default: 42165fe]: +``` + +If you hit enter, it will check out the conflict markers in that commit into your working directory. + +```git +❯ but resolve +You are currently in conflict resolution mode. + - resolve all conflicts + - finalize with but resolve finish + - OR cancel with but resolve cancel + +Conflicted files remaining: + ✗ README.md +Checking out conflicted commit 42165fe +``` + +So now you're in a special mode called "Edit Mode" in GitButler, where we've directly checked out a commit to work on. If you run any other commands, we'll warn you that you're currently in this mode. + +For the conflicts, we put in zdiff3 style headers, so you can see your side, their side and also the ancestor. For example, if we look at the conflicted README.md file + +```git +❯ head README.md +<<<<<< ours +# The Why Experience +|||||| ancestor +# Twitter Clone +====== +# X Clone +>>>>>> theirs +``` + +So you can see that we started with "Twitter Clone" and upstream changed it to "X Clone" and locally I changed the same line to "The Why Experience". Now I can resolve these three versions into a single line. + +If I do that and then again run `but status`, you can see that GitButler notices that the conflicts in the README file has been resolved. + +```git +❯ but st +Initiated a background sync... +You are currently in conflict resolution mode. + - resolve all conflicts + - finalize with but resolve finish + - OR cancel with but resolve cancel + +No conflicted files remaining! +Files resolved: + ✓ README.md +``` + +If you had other conflicted files, it would give you a list of what was still unresolved so you could work your way through the list. + +However, now that we've resolved everything, we can either run `but resolve finish` or just `but resolve` and it will move us to the next step. Technically you can just keep running `but resolve` and it will figure out what the next thing to do is. + +```git +❯ but resolve +You are currently in conflict resolution mode. + - resolve all conflicts + - finalize with but resolve finish + - OR cancel with but resolve cancel + +No conflicted files remaining! +Files resolved: + ✓ README.md + +All conflicts have been resolved! +Finalize the resolution now? [Y/n]: y + +Initiated a background sync... +✓ Conflict resolution finalized successfully! +The commit has been updated with your resolved changes. + +⚠ Warning: New conflicts were introduced during the rebase: + + ● 4f671a1 hero update - new branding + +Run but status to see all conflicted commits, or but resolve to resolve them. +``` # branching-and-commiting.mdx @@ -5046,7 +5009,7 @@ To do this, you can use the `but branch new ` command. {/* run git branch -D user-bookmarks */} -```cli [branching-and-commiting-but-branch-1, 110px] +```cli [branching-and-commiting-but-branch-1, 88px] but branch new user-bookmarks ``` @@ -5060,7 +5023,7 @@ but status Now we can commit our unassigned changes to that branch. You can simply assign your changes to the branch first to commit later (we'll cover that later in [Rubbing](./rubbing)), but for now let's keep it simple and just commit them directly using the `but commit` command. -```cli [branching-and-commiting-but-commit-1, 110px] +```cli [branching-and-commiting-but-commit-1, 88px] but commit -m 'all the user bookmarks' ``` @@ -5097,7 +5060,7 @@ To create a parallel branch, you simply create a new branch the same way we did {/* run echo 'test' > app/controllers/likes_controller.rb */} {/* run echo 'test' > app/models/like.rb */} -```cli [branching-and-commiting-but-branch-2, 110px] +```cli [branching-and-commiting-but-branch-2, 88px] but branch new liked-tweets ``` @@ -5109,7 +5072,7 @@ but status We can see our previous branch and the commit we made, our new empty branch and a couple of modified files. Now we can commit the unassigned changes to that branch with `but commit -m "liked tweets changes" liked-tweets` -```cli [branching-and-commiting-but-commit-2, 110px] +```cli [branching-and-commiting-but-commit-2, 88px] but commit -m "liked tweets changes" liked-tweets ``` @@ -5138,7 +5101,7 @@ To create a new stacked branch in GitButler, you can run `but branch new` with a {/* run git branch -D liked-tweets-stacked */} {/* restore [e32713a1f41c] */} -```cli [branching-and-commiting-but-branch-3, 110px] +```cli [branching-and-commiting-but-branch-3, 88px] but branch new -a user-bookmarks liked-tweets-stacked ``` @@ -5148,7 +5111,7 @@ but status Now we can commit to our stacked branch. -```cli [branching-and-commiting-but-commit-3, 110px] +```cli [branching-and-commiting-but-commit-3, 88px] but commit -m "liked tweets changes" liked-tweets-stacked ``` @@ -5209,7 +5172,7 @@ Now, if we want to create a commit in the `user-bookmarks` branch, we can either Or, we can make a commit with _only_ the assigned files in `user-bookmarks` by using the `-o` option to `but commit`. -```cli [branching-and-commiting-but-commit-4, 110px] +```cli [branching-and-commiting-but-commit-4, 88px] but commit -o -m "liked tweets view" bo ``` @@ -5221,7 +5184,7 @@ but st Now let's commit all the rest of the changes (assigned and unassigned) to our other branch: -```cli [branching-and-commiting-but-commit-5, 110px] +```cli [branching-and-commiting-but-commit-5, 88px] but commit -m 'bookmarks stuff' ch ``` @@ -5231,26 +5194,26 @@ but status ### Committing Specific Files or Hunks -Instead of staging files first and then committing with `-o`, you can also directly specify which files or hunks to include in a commit using the `-F` or `--files` option. This lets you commit only specific changes without having to assign them to a branch first. +Instead of staging files first and then committing with `-o`, you can also directly specify which files or hunks to include in a commit using the `-p` or `--changes` option. This lets you commit only specific changes without having to assign them to a branch first. For example, if you have multiple unassigned files and only want to commit some of them: ```bash -but commit -F h0,i0 -m "only these two files" user-bookmarks +but commit -p h0,i0 -m "only these two files" user-bookmarks ``` You can specify files in several ways: - **By CLI ID**: Use the short identifier shown in `but status` (e.g., `h0`, `i0`) -- **Space-separated**: `--files h0 i0 k0` -- **Comma-separated**: `-F h0,i0,k0` -- **By path**: `-F app/models/bookmark.rb` +- **Space-separated**: `--changes h0 i0 k0` +- **Comma-separated**: `-p h0,i0,k0` +- **By path**: `-p app/models/bookmark.rb` This also works with hunk IDs. When a file has multiple hunks (shown in `but status -f` or `but diff`), you can commit individual hunks rather than the entire file. This is useful when you have changes in the same file that belong to different logical commits. -If you don't specify `-F`, all uncommitted changes (or changes staged to the target branch) are committed. Use `-F` when you need fine-grained control over what goes into a commit. +If you don't specify `-p`, all uncommitted changes (or changes staged to the target branch) are committed. Use `-p` when you need fine-grained control over what goes into a commit. @@ -5276,186 +5239,163 @@ but status ``` -# configuration.mdx - -We've already covered `but config` a bit in dealing with forges and target branches. +# editing-commits.mdx -You can also use it for some basic user configuration, such as setting your name and email address for commits and your default editor. +While you can rub changes in and out of commits, you can also edit the commit +message of any commit in your workspace quite easily. -```cli [configuration-but-config-1, 308px] -but config user -``` +## Editing Commit Messages -## Aliases +You can edit commit messages with the `but describe` command. So if we have this status: -GitButler also has a built in aliasing system in case you want to provide some shorthands. +{/* restore [d69fffa7c6eb] */} -```cli [configuration-but-alias-1, 308px] -but alias +```cli [editing-commits-but-status-1, 330px] +but status ``` -To add a new alias, you can run `but alias add `, which you can also provide a `-g` or `--global` if you want it to be a global alias. This will put this data in your local or global Git config file. - -You will notice that there is a `default` alias, which is what runs when you just run `but` with no arguments. If you overwrite the `default` alias, you can set up something other than `status` to run by default. - - -# ai-stuff.mdx - -## Dash Dash AI - -`but squash --ai` +Then you can edit the message of any commit by running `but reword `, which will open up your editor of choice with the existing commit message and when you exit the editor, replace that message in the commit and rebase everything above it. -`but commit --ai` +The editor would look something like this: -## Skills +``` +add user changes -`but skill install` +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# Changes in this commit: +# modified: app/models/user.rb +# modified: config/routes.rb +# +~ +~ +~ +~ +``` -## Hooks and MCP +Pretty simple. -You can also install explicit hooks or an MCP server if you prefer. +## Changing Branch Names +Just like changing commit messages, you can also use `but reword` to change the name of a branch. So, in the above example, if we wanted to change the branch name from `user-bookmarks` to `feature-awesome-thing`, we can do this: -# conflict-resolution.mdx +```cli [editing-commits-but-reword-1, 88px] +but reword -m feature-awesome-thing us +``` -In this world nothing can be said to be certain, except death, taxes and merge conflicts. +Et voila. -There are several different ways that you can run into merge conflicts when using Git (and thus, GitButler, or any other branching version control system). +```cli [editing-commits-but-status-2, 330px] +but status +``` -Perhaps there are changes that have been merged upstream that modified the same files as you did in your branch. Or maybe you uncommitted something that commits above it depended on. +{/* TODO: Edit Mode */} -## First Class Conflicts in GitButler -First, it's important to understand how GitButler deals with conflicts. While Git generally has to check out conflicts in your working directory and make you resolve them before you can commit, GitButler can partially apply a conflicting change and store the commit marked as "conflicted". +# forges.mdx -This means that: +We've touched on how to update your local branches with `but pull`, but what about when you want to take your awesome new branches of work and put them on a server to get them integrated or collaborate with other people? -- Rebases _always_ succeed, just sometimes it results with commits in a conflicted state. -- You can deal with conflicts in any order and at any time. +The two main commands to get work out are `but push` and `but pr`. Let's start with `but push` as it's a little simpler. -So, let's take a look at what this looks like and how we can deal with conflicted commits when they arise. +## Pushing -{/* restore [e53a4a85d83d] */} -{/* run git push -f origin 96ccca9:main */} +The very simple example would be to simply run `but push `. -```cli [conflict-resolution-but-status-1, 308px] -but status ``` +❯ but push update-homepage -Let's say that this is our status and we've decided to pull in from upstream. The changes that have been merged in by someone else upstream conflict with ours. When we run `but pull`, it will result in conflicts in our branch (but it will succeed). +✓ Push completed successfully -```cli [conflict-resolution-but-pull-1, 308px] -but pull + update-homepage -> origin/update-homepage ((new branch) -> 1d31833) ``` -Ok, the `pull` tells us that we have conflicts and it also gives us a cheat sheet for what to do to resolve them, which is essentially "run `but resolve`". - -So first let's see what our conflicted branch looks like with `but status`. +You can also run `but push` by itself. If there is only one applied branch, it will push that one. If there are several applied branches, you can choose which to push or select 'all' to push all of them. -```cli [conflict-resolution-but-status-2, 330px] -but status -``` +You can also supply `-d` or `--dry-run` to see what _would_ be pushed up. -Notice how we have _two_ commits that are conflicted, but one that is not. You could have any number of commits marked as conflicted in a branch, and you'll need to resolve each of them one by one. +## Pull Requests -If we were to dig into the details here, a few things have actually happened. +That's the simple way to push branches to your default remote and update already pushed ones. -First of all, we have applied the upstream changes, so if we were to look at the files that conflict, we will see the upstream version rather than what we had done. +The other common thing to do is to open Pull Requests on GitHub. GitButler's CLI has a built in command for opening and updating PRs, called `but pr`. -Second, the commits that are not in a conflicted state are still applied - those changes are still in your working directory. In fact, even the conflicted commit's changes will be applied in the areas where they don't conflict. +Much like `but push`, if there is only one branch, it will open a PR for that, otherwise it will ask you which branch to open one for. Or you can be explicit with something like `but pr `. -You could potentially have several conflicted commits in your branch. When you resolve one, everything above it is rebased and may introduce new conflicts or may resolve other conflicts, depending on the resolution. +``` +❯ but pr +Do you want to open a new PR on branch 'sc-switch-wording-to-x'? [Y/n]: y +→ Pushing sc-switch-wording-to-x... + ✓ Pushed to origin +→ Creating PR for sc-switch-wording-to-x → main... -However, for now, let's look at a simple resolution flow. All you really need is one command: `but resolve`. +✓ Created PR #69 + Title: Switch Wording to X + Branch: sc-switch-wording-to-x + URL: https://github.com/schacon/why/pull/69 +``` -If you run `but resolve`, it will look through all your applied branches for any conflicted commits. If it finds any, it will list them out and ask you which you want to start with and default to the lowest one on the first branch. +Once it's opened, you'll get a URL you can view the pull request on. -```git -❯ but resolve -Found conflicted commits: +## Forge Authentication -Branch: update-homepage - ● 42165fe branding change: readme - ● 404b604 hero update - new branding +In order to open a PR on GitHub, you'll need to authenticate to that forge. You can see which authentications you have by running `but config`: -Would you like to start resolving these conflicts? -Enter commit ID to resolve [default: 42165fe]: +```cli [forges-but-config-1, 572px] +but config ``` -If you hit enter, it will check out the conflict markers in that commit into your working directory. - -```git -❯ but resolve -You are currently in conflict resolution mode. - - resolve all conflicts - - finalize with but resolve finish - - OR cancel with but resolve cancel +If you have not authenticated to a forge yet, you can run `but config forge auth`, which will ask you which type of authentication you would like to do: -Conflicted files remaining: - ✗ README.md -Checking out conflicted commit 42165fe +``` +❯ but config forge auth +? Select an authentication method: +> Device flow (OAuth) + Personal Access Token (PAT) + GitHub Enterprise ``` -So now you're in a special mode called "Edit Mode" in GitButler, where we've directly checked out a commit to work on. If you run any other commands, we'll warn you that you're currently in this mode. +Selecting one of the options will allow you to provide an authentication token for GitButler to use for opening and modifying PRs. -For the conflicts, we put in zdiff3 style headers, so you can see your side, their side and also the ancestor. For example, if we look at the conflicted README.md file + + Currently, GitButler only authenticates to GitHub servers, but support for Merge Requests on + GitLab and other forges is coming. + -```git -❯ head README.md -<<<<<< ours -# The Why Experience -|||||| ancestor -# Twitter Clone -====== -# X Clone ->>>>>> theirs -``` -So you can see that we started with "Twitter Clone" and upstream changed it to "X Clone" and locally I changed the same line to "The Why Experience". Now I can resolve these three versions into a single line. +# initializing-a-repository.mdx -If I do that and then again run `but status`, you can see that GitButler notices that the conflicts in the README file has been resolved. +If you run any `but` command in a repository that has never been seen by GitButler before, it will automatically ask you if you want to setup the repository for GitButler. -```git -❯ but st -Initiated a background sync... -You are currently in conflict resolution mode. - - resolve all conflicts - - finalize with but resolve finish - - OR cancel with but resolve cancel +It will guess most things needed, but everything can be changed later if it got anything wrong. The most important thing is to figure out the target branch - the main branch that you'll want to merge things into and you consider 'production' or 'golden'. Normally this is something like `origin/main`, but GitButler should be pretty good at guessing. -No conflicted files remaining! -Files resolved: - ✓ README.md +You can also run `but setup` manually to set everything up explicitly: + +```ansi but-setup-5faf7f36 +but setup ``` -If you had other conflicted files, it would give you a list of what was still unresolved so you could work your way through the list. +As the command says, it does a few things to prepare your repository for being managed by GitButler. -However, now that we've resolved everything, we can either run `but resolve finish` or just `but resolve` and it will move us to the next step. Technically you can just keep running `but resolve` and it will figure out what the next thing to do is. +Unlike a tool like [Jujutsu](https://docs.jj-vcs.dev/latest/git-compatibility/) or [Sapling](https://sapling-scm.com/docs/git/git_support_modes/), GitButler mainly operates on normal Git repositories, so nearly all Git commands will work with anything produced or managed by GitButler. You can think of it more like a new porcelain than a different system. -```git -❯ but resolve -You are currently in conflict resolution mode. - - resolve all conflicts - - finalize with but resolve finish - - OR cancel with but resolve cancel +However, one thing we need to do in order to enable having parallel applied branches is create a "megamerge" commit that automatically merges in the heads of all your applied branches, so that other tools `git status` will correctly show you what you expect. -No conflicted files remaining! -Files resolved: - ✓ README.md +This means that we do two things: -All conflicts have been resolved! -Finalize the resolution now? [Y/n]: y +- We create a new branch called `gitbutler/workspace` pointing to a constantly rewritten and ephemeral merge commit and check this branch out so HEAD is pointing to it (again, for `git status` reasons in tools like VSCode or whatever) +- We add custom `pre-commit` and `post-checkout` hooks (moving and continuing to call any existing hooks) to try to prevent you from accidentally committing on top of our managed mega-merge commit. -Initiated a background sync... -✓ Conflict resolution finalized successfully! -The commit has been updated with your resolved changes. + -⚠ Warning: New conflicts were introduced during the rebase: +The mega-merge workspace commit will soon only be needed once you actually have more than one branch applied, so at some point we won't automatically do it on setup, but we're working on it. - ● 4f671a1 hero update - new branding + -Run but status to see all conflicted commits, or but resolve to resolve them. -``` +Both of these things can be quickly and easily undone by running `but teardown`, doing any Git committing stuff you need to do and then re-running `but setup` to go back to GitButler tooling. + +You can also simply checkout a git branch with `git checkout ` and the `post-checkout` hook we installed should clean up after itself. # inspecting.mdx @@ -5514,7 +5454,7 @@ This output is actually _better_ than the default Git output for this, because I The `but branch` command, however, is built specifically to help you identify the branches you're looking for and give you some useful information about them. Let's give it a try: -```cli [inspecting-but-branch-1, 660px] +```cli [inspecting-but-branch-1, 638px] but branch ``` @@ -5534,7 +5474,7 @@ The point of this listing is to help you easily see what work you have available Running `but branch` defaults to running `but branch list`, which has a bunch of other options (filtering to only local or remote branches, not calculating mergability for speed, etc). The most useful option might be the filtering, for example, you can type a partial match string and it will filter the output: -```cli [inspecting-but-branch-2, 242px] +```cli [inspecting-but-branch-2, 220px] but branch list book ``` @@ -5550,7 +5490,7 @@ git log origin/main..feature-awesome-thing Now let's look at `but branch show` -```cli [inspecting-but-branch-3, 286px] +```cli [inspecting-but-branch-3, 264px] but branch show feature-awesome-thing ``` @@ -5562,7 +5502,7 @@ The real fun one is adding `--ai`, which will take a look at the changes and sum Let's run all of them at the same time: -```cli [inspecting-but-branch-4, 704px] +```cli [inspecting-but-branch-4, 682px] but branch show sc-branch-28 --ai -r -f ``` @@ -5570,7 +5510,7 @@ but branch show sc-branch-28 --ai -r -f If you want to look at a specific commit in any of these circumstances, you can use the `but show` command with the commit hash. -```cli [inspecting-but-show-1, 286px] +```cli [inspecting-but-show-1, 264px] but show a42580b96ed7b432 ``` @@ -5579,58 +5519,23 @@ but show a42580b96ed7b432 As long as we're talking about branches, let's show how to get rid of them. If you've merged one, it will by default not be shown anymore with `but branch` anyhow, but if you have one with some work on it that you want to abandon, you can also easily delete it with `but branch delete` (or `-d`). -# editing-commits.mdx - -While you can rub changes in and out of commits, you can also edit the commit -message of any commit in your workspace quite easily. - -## Editing Commit Messages - -You can edit commit messages with the `but describe` command. So if we have this status: - -{/* restore [d69fffa7c6eb] */} - -```cli [editing-commits-but-status-1, 330px] -but status -``` - -Then you can edit the message of any commit by running `but reword `, which will open up your editor of choice with the existing commit message and when you exit the editor, replace that message in the commit and rebase everything above it. - -The editor would look something like this: - -``` -add user changes - -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# -# Changes in this commit: -# modified: app/models/user.rb -# modified: config/routes.rb -# -~ -~ -~ -~ -``` - -Pretty simple. +# scripting.mdx -## Changing Branch Names +### JSON Errwhere -Just like changing commit messages, you can also use `but reword` to change the name of a branch. So, in the above example, if we wanted to change the branch name from `user-bookmarks` to `feature-awesome-thing`, we can do this: +All of the commands are designed to be very user friendly when we have an interactive terminal, but you can also very easily script everything by passing the `--json` or `-j` option to anything. For example, here is using `but show` on a commit. -```cli [editing-commits-but-reword-1, 110px] -but reword -m feature-awesome-thing us +```cli [scripting-but-show-1, 308px] +but show 2672465 ``` -Et voila. +Now with the `--json` option: -```cli [editing-commits-but-status-2, 330px] -but status +```cli [scripting-but-show-2, 682px] +but show --json 2672465 | jq ``` -{/* TODO: Edit Mode */} +You can do this with anything - committing, status, diffing, etc. Just throw a `-j` in there and you get parseable data (or, data your agent can very easily work with). # operations-log.mdx @@ -5649,7 +5554,7 @@ but oplog Undo the last operation: -```cli [operations-log-but-undo-1, 154px] +```cli [operations-log-but-undo-1, 132px] but undo ``` @@ -5661,137 +5566,42 @@ You can easily restore to any point in the operations history by running the `bu but oplog restore -f 6fdd8fb1d547 ``` -Restorations create a new oplog entry before running, so you can always easily undo it in the same manner. - - - -It can be a bit confusing as to what state it restores to. It will restore to what your project looked like _before_ the operation was run. So for example, if there is a `CreateCommit` operation and you restore to that SHA, it will put your state back to the moment before the commit happened. - - - -## Creating Snapshots - -You can also manually create snapshots of moments that you want to be able to revert to at any point, without some other operation needing to automatically save it. - -```cli [operations-log-but-oplog-3, 154px] -but oplog snapshot -``` - -Now you can copy that SHA and restore to that exact point at any time in the future. - - -# conclusion.mdx - -Ok, that's a short guide to GitButler's command line interface. - -Join us in [Discord](https://discord.com/invite/MmFkmaJ42D) if you have any other questions or suggestions for how we can improve the tool. - -Thanks! - - -# initializing-a-repository.mdx - -If you run any `but` command in a repository that has never been seen by GitButler before, it will automatically ask you if you want to setup the repository for GitButler. - -It will guess most things needed, but everything can be changed later if it got anything wrong. The most important thing is to figure out the target branch - the main branch that you'll want to merge things into and you consider 'production' or 'golden'. Normally this is something like `origin/main`, but GitButler should be pretty good at guessing. - -You can also run `but setup` manually to set everything up explicitly: - -```ansi but-setup-5faf7f36 -but setup -``` - -As the command says, it does a few things to prepare your repository for being managed by GitButler. - -Unlike a tool like [Jujutsu](https://docs.jj-vcs.dev/latest/git-compatibility/) or [Sapling](https://sapling-scm.com/docs/git/git_support_modes/), GitButler mainly operates on normal Git repositories, so nearly all Git commands will work with anything produced or managed by GitButler. You can think of it more like a new porcelain than a different system. - -However, one thing we need to do in order to enable having parallel applied branches is create a "megamerge" commit that automatically merges in the heads of all your applied branches, so that other tools `git status` will correctly show you what you expect. - -This means that we do two things: - -- We create a new branch called `gitbutler/workspace` pointing to a constantly rewritten and ephemeral merge commit and check this branch out so HEAD is pointing to it (again, for `git status` reasons in tools like VSCode or whatever) -- We add custom `pre-commit` and `post-checkout` hooks (moving and continuing to call any existing hooks) to try to prevent you from accidentally committing on top of our managed mega-merge commit. - - - -The mega-merge workspace commit will soon only be needed once you actually have more than one branch applied, so at some point we won't automatically do it on setup, but we're working on it. - - - -Both of these things can be quickly and easily undone by running `but teardown`, doing any Git committing stuff you need to do and then re-running `but setup` to go back to GitButler tooling. - -You can also simply checkout a git branch with `git checkout ` and the `post-checkout` hook we installed should clean up after itself. - - -# forges.mdx - -We've touched on how to update your local branches with `but pull`, but what about when you want to take your awesome new branches of work and put them on a server to get them integrated or collaborate with other people? - -The two main commands to get work out are `but push` and `but pr`. Let's start with `but push` as it's a little simpler. - -## Pushing - -The very simple example would be to simply run `but push `. - -``` -❯ but push update-homepage - -✓ Push completed successfully - - update-homepage -> origin/update-homepage ((new branch) -> 1d31833) -``` - -You can also run `but push` by itself. If there is only one applied branch, it will push that one. If there are several applied branches, you can choose which to push or select 'all' to push all of them. - -You can also supply `-d` or `--dry-run` to see what _would_ be pushed up. +Restorations create a new oplog entry before running, so you can always easily undo it in the same manner. -## Pull Requests + -That's the simple way to push branches to your default remote and update already pushed ones. +It can be a bit confusing as to what state it restores to. It will restore to what your project looked like _before_ the operation was run. So for example, if there is a `CreateCommit` operation and you restore to that SHA, it will put your state back to the moment before the commit happened. -The other common thing to do is to open Pull Requests on GitHub. GitButler's CLI has a built in command for opening and updating PRs, called `but pr`. + -Much like `but push`, if there is only one branch, it will open a PR for that, otherwise it will ask you which branch to open one for. Or you can be explicit with something like `but pr `. +## Creating Snapshots -``` -❯ but pr -Do you want to open a new PR on branch 'sc-switch-wording-to-x'? [Y/n]: y -→ Pushing sc-switch-wording-to-x... - ✓ Pushed to origin -→ Creating PR for sc-switch-wording-to-x → main... +You can also manually create snapshots of moments that you want to be able to revert to at any point, without some other operation needing to automatically save it. -✓ Created PR #69 - Title: Switch Wording to X - Branch: sc-switch-wording-to-x - URL: https://github.com/schacon/why/pull/69 +```cli [operations-log-but-oplog-3, 154px] +but oplog snapshot ``` -Once it's opened, you'll get a URL you can view the pull request on. - -## Forge Authentication +Now you can copy that SHA and restore to that exact point at any time in the future. -In order to open a PR on GitHub, you'll need to authenticate to that forge. You can see which authentications you have by running `but config`: -```cli [forges-but-config-1, 484px] -but config -``` +# tutorial-overview.mdx -If you have not authenticated to a forge yet, you can run `but config forge auth`, which will ask you which type of authentication you would like to do: +Using the GitButler CLI is meant to make a specific common workflow very simple, which is roughly: -``` -❯ but config forge auth -? Select an authentication method: -> Device flow (OAuth) - Personal Access Token (PAT) - GitHub Enterprise -``` +- Create a branch +- Do work on that branch +- Commit to that branch +- Optionally, create another branch if you find unrelated work you need to do +- Work on and commit to that branch +- Submit a branch for review +- Create a stacked branch if needed to continue on dependent work +- Update your base if work has been integrated to remove merged work +- Rinse and repeat -Selecting one of the options will allow you to provide an authentication token for GitButler to use for opening and modifying PRs. +Additionally, GitButler is very good at editing commits (amending fixup work, squashing, rewording messages, etc), it keeps a simple log of what you've done in case you need to go back in time, it makes collaborating on a branch with others easy, it has great GitHub/Lab integration and more. - - Currently, GitButler only authenticates to GitHub servers, but support for Merge Requests on - GitLab and other forges is coming. - +Let's walk through some of the things it can do and what a typical day using the GitButler CLI might look like. # rubbing.mdx @@ -5835,11 +5645,11 @@ but status If we want to update the first commit (`da42d06`) with the `README-es.md` changes and the last commit (`fdbd753`) with the `app/views/bookmarks/index.html.erb` changes, we can run the following two `rub` commands: -```cli [rubbing-but-rub-1, 110px] +```cli [rubbing-but-rub-1, 88px] but rub h0 da42d06 ``` -```cli [rubbing-but-rub-2, 110px] +```cli [rubbing-but-rub-2, 88px] but rub app/views/bookmarks/index.html.erb fdbd753 ``` @@ -5865,7 +5675,7 @@ but status We can absorb the top commit into the bottom one by running `but rub `: -```cli [rubbing-but-rub-3, 110px] +```cli [rubbing-but-rub-3, 88px] but rub 0f 08 ``` @@ -5891,7 +5701,7 @@ but status And we want to un-commit the first commit (`0fa2965`) as though we had never made it, you can rub to `zz`: -```cli [rubbing-but-rub-4, 110px] +```cli [rubbing-but-rub-4, 88px] but rub 0f zz ``` @@ -5915,7 +5725,7 @@ but status We can move the “second commit” commit to the `move-second-commit` branch with `but rub`: -```cli [rubbing-but-rub-5, 110px] +```cli [rubbing-but-rub-5, 88px] but rub 0f mo ``` @@ -5979,35 +5789,208 @@ but commit empty --after 6a Now we have a blank commit: -```cli [rubbing-but-status-13, 440px] +```cli [rubbing-but-status-13, 462px] but status -f ``` Now we can use the previous method of moving file changes from other commits into it, then edit the commit message with `but reword 54` (for more on the `reword` command, see [Editing Commits](editing-commits), coming up next). -# scripting.mdx +# getting-started.mdx -JSON! +This page is for coding agents that can read local instruction files and run +commands in your repository. The GitButler skill does not give the agent new +permissions. It tells the agent how to use `but` instead of driving Git through +checkout, stash, add, commit, and rebase commands. +## Install the `but` CLI -# tutorial-overview.mdx +If you already have GitButler Desktop installed, you can install the CLI from +the Desktop Client settings. For terminal-only setup, run: -Using the GitButler CLI is meant to make a specific common workflow very simple, which is roughly: +```sh +curl -fsSL https://gitbutler.com/install.sh | sh +``` -- Create a branch -- Do work on that branch -- Commit to that branch -- Optionally, create another branch if you find unrelated work you need to do -- Work on and commit to that branch -- Submit a branch for review -- Create a stacked branch if needed to continue on dependent work -- Update your base if work has been integrated to remove merged work -- Rinse and repeat +See [Installation and setup](/cli-guides/installation) for the full CLI install +options. -Additionally, GitButler is very good at editing commits (amending fixup work, squashing, rewording messages, etc), it keeps a simple log of what you've done in case you need to go back in time, it makes collaborating on a branch with others easy, it has great GitHub/Lab integration and more. +## Install the GitButler skill -Let's walk through some of the things it can do and what a typical day using the GitButler CLI might look like. +Run the installer from the same repository: + +```sh +but skill install +``` + +The installer prompts for scope first: current repository or global home +directory. It then prompts for the skill format. Current formats include Agent +Skills (`.agents/skills`), Claude Code, OpenCode, Codex, GitHub Copilot, Cursor, +and Windsurf. + +For custom paths, global installs, non-interactive updates, and skill checks, +see [`but skill`](/commands/but-skill). + +## Set up the repository + +GitButler currently needs the repository in workspace mode for its multi-branch +model: multiple GitButler branches in one working directory. + +From the repository where the agent will work, run: + +```sh +but setup +``` + +You can also skip this step and let the agent run `but setup` when it first +needs GitButler. For the full list of setup changes, see +[`but setup`](/commands/but-setup). + +GitButler is working toward a plain Git mode that switches into a workspace only +when multiple concurrent branches are needed. Follow +[gitbutlerapp/gitbutler#11866](https://github.com/gitbutlerapp/gitbutler/issues/11866) +for that work. + +## Add optional agent instructions + +The GitButler skill tells the agent how to use `but`. Your own instructions +tell the agent what behavior you want. + +Put project defaults in a repository instruction file such as `AGENTS.md` or +`CLAUDE.md`. Put personal defaults in a global instruction file such as +`~/.codex/AGENTS.md`, `~/.claude/CLAUDE.md`, Cursor rules, Copilot custom +instructions, or the equivalent for your tool. + +These files steer agent behavior; they are not access controls. Use your usual +repository permissions and branch protection for hard limits. + +Use this baseline to keep agent work isolated: + +```md +## Version control + +- Use GitButler (`but`) for version-control write operations, including + branching, committing, pushing, and history edits. +- Assume multiple agents may be working in this repository. Do not move, amend, + squash, discard, commit, push, or otherwise modify another agent's work unless + the user asks. +- Use a dedicated GitButler branch for each agent session, unless the user asks + for a different branch structure. Commit only changes that belong to that + session. +- Do not push or open pull requests unless the user asks. +- Keep commit messages and pull request descriptions succinct: explain what + changed, why it changed, and any important decision. +``` + +You can also tune the agent to: + +- amend local fixes into existing commits; +- create checkpoint commits and tidy them before review; +- create stacked pull requests for dependent work; +- follow your branch and commit naming conventions; +- publish, update from main, or create recovery points only when your policy + allows it. + +For copyable snippets, see +[Tuning agent behavior](/ai-agents/tuning-agent-behavior). + +For prompt examples that ask for specific branch and commit outcomes, see +[Useful requests](/ai-agents/useful-requests). + + +# parallel-agents.mdx + +Parallel agents do not require separate worktrees or pre-created branches. Once +agents use GitButler for version-control writes, you can start another coding +session in the same repository and prompt it like any other task: + +```text +Work on checkout validation. +``` + +When either session is ready, ask it to commit: + +```text +Commit your changes. +``` + +The agent uses GitButler to commit the changes for its task to its GitButler +branch. The branch routing is the agent's job; your prompt can stay small. + +If two sessions touch the same file or generated output, have the agents call +out the overlap before committing. + +You can also ask an agent to split independent work out of the current session. +For example, if a feature session also finds a small bug fix, the agent can +move the relevant changes or commits to a new branch and prepare a separate PR +instead of stacking the fix on the feature. + +For more background on the branch model, see +[Parallel branches](/features/branch-management/virtual-branches). + +The baseline `Version control` instructions from +[Getting started](/ai-agents/getting-started#add-optional-agent-instructions) +are useful if you want to steer commit behavior, but they are not a separate +parallel-agent setup step. + +## How this differs from worktrees + +Git has one checked-out branch per worktree. If you want two agents to work on +two branches at the same time, the usual Git answer is multiple worktrees. + +GitButler gives you a different option: multiple active branches in one +worktree, with each agent's commits organized onto the branch for its session. + +| | Multiple worktrees | GitButler parallel branches | +| --- | --- | --- | +| Workspace | One directory per agent | One shared working directory | +| Branches | One checked-out branch per worktree | Multiple active branches in one worktree | +| Isolation | Separate checkout | Shared filesystem and runtime state | +| Setup cost | Usually more directories, dependency installs, build outputs, and dev servers | Reuse one install and dev server when tasks can share runtime state | +| Version-control shape | Branches stay separate because work happens in separate directories | GitButler can commit the right subset of changes to each branch | +| Best fit | Competing attempts, incompatible checkout states, isolated runtimes | Unrelated features or fixes that can share one workspace | + +Use multiple worktrees when agents need incompatible checkout states, separate +runtime state, or competing attempts at the same task. Use GitButler parallel +branches when the tasks are independent enough to share one workspace and you +want less local overhead. + +## Handle dependencies explicitly + +Parallel agents work best when sessions start independent. If one session +starts depending on another, make that relationship explicit by stacking the +branches: + +```text +The notification settings work now depends on checkout validation. Stack your +branch on top of the checkout validation branch. +``` + +If an unrelated fix shows up inside a feature session, tell the agent to extract +it instead: + +```text +The cache invalidation fix is independent. Move it to a separate GitButler +branch and prepare a separate PR for it. +``` + +If the feature depends on the fix, put the fix on the lower branch and stack the +feature above it instead. For stacked PR policy, see +[Create stacked pull requests](/ai-agents/tuning-agent-behavior#create-stacked-pull-requests). + +## Know what is shared + +Parallel GitButler branches are not runtime isolation. The agents share one +filesystem, dependency install, generated files, and app state. That can surface +overlap and broken builds earlier, but it can also hide accidental +dependencies. + +Before shipping a branch independently, check whether it depends on another +active branch. If two agents start editing the same files or generated output, +decide whether to keep the work parallel, stack one branch on the other, or use +separate worktrees. + +For more request examples, see [Useful requests](/ai-agents/useful-requests). # updating-the-base.mdx @@ -6024,13 +6007,13 @@ When GitButler is first initialized in a project, you are asked to choose a bran You can always check your target branch setting with `but config`: -```cli [updating-the-base-but-config-1, 484px] +```cli [updating-the-base-but-config-1, 572px] but config ``` Or get more information with `but config target`: -```cli [updating-the-base-but-config-2, 330px] +```cli [updating-the-base-but-config-2, 308px] but config target ``` @@ -6079,7 +6062,7 @@ Technically, there could be more reachable commits, but we only show the first p Now let's say that we would like to pull in the upstream work and rebase our branches on top of the new upstream to update them. We can check what all would happen with `but pull --check`. -```cli [updating-the-base-but-pull-1, 330px] +```cli [updating-the-base-but-pull-1, 308px] but pull --check ``` @@ -6101,7 +6084,7 @@ When you feel like you want to get your active branches up to date, you can run Let's run it in our example. -```cli [updating-the-base-but-pull-2, 418px] +```cli [updating-the-base-but-pull-2, 396px] but pull ``` @@ -6110,3 +6093,358 @@ but status ``` OK, now we can see that our integrated branch was removed, our `gemfile-fixes` branch was successfully rebased and our `sc-branch-26` work is marked as conflicted. We'll see how to deal with that state in a minute. + + +# tuning-agent-behavior.mdx + +Add these optional bullets under the same `## Version control` section as the +baseline from +[Getting started](/ai-agents/getting-started#add-optional-agent-instructions). +Use this page as a menu: copy only the policies you want for the repository and +agent you are using. + +## Amend local fixes into the right commits + +Use this when you want the agent to fold follow-up fixes into unpublished local +commits when the new change clearly belongs with that commit's intent. With +GitButler, the agent can move the relevant change into the commit where it +belongs. + +```md +- For small cleanup or follow-up fixes, amend an unpublished local commit when + the change clearly belongs with that commit's intent. +- Do not create tiny fixup commits unless I ask. +- Use GitButler to move the relevant changes into the commit where they belong. +- Ask before rewriting pushed, reviewed, shared, or ambiguous history. +``` + +You do not need to tell the agent which command to use. The GitButler skill +gives it the relevant operations. For background, see +[`but absorb`](/commands/but-absorb) and [`but amend`](/commands/but-amend). + +## Commit checkpoints after each completed turn + +Use this when you want local savepoints while the agent works. The checkpoints +do not need to be the final review history. Before review, you can ask the +agent to tidy unpublished local history. + +```md +- Commit after a working checkpoint, when the requested change is complete and + relevant checks have passed or been reported. +- Treat checkpoint commits as local savepoints, not final review history. +- When I ask you to tidy the history, use GitButler to squash commits, reword + commits, and move changes between commits where appropriate. +- Only tidy unpublished local history unless I explicitly authorize changing + pushed or shared history. +``` + +## Create stacked pull requests + +Use this when you want dependent work reviewed as stacked pull requests. This is +useful when one agent session depends on another session's branch, or when an +agent is working on a branch that sits at the bottom of a stack. + +```md +- If this session depends on another in-flight branch, stack its branch on top + of that dependency instead of mixing the changes. +- If this session is working in a stack, put commits on the branch where they + belong. +- Ask before moving commits onto lower, pushed, reviewed, or shared branches. +- Use `but move` for branch stacking and restacking. Do not recreate branches + to simulate stacking. +- For stacked branches, create pull requests with `but pr`, not `gh`, so + GitButler keeps the right PR base branches and stack metadata. +``` + +For background, see [Stacked branches](/features/branch-management/stacked-branches), +[`but move`](/commands/but-move), and [`but pr`](/commands/but-pr). + +## Customize branch names + +Use this when your team has a naming convention for branches the agent creates. +This is only an example; replace the prefix and shape with your convention. + +```md +- When creating a GitButler branch for an agent session, use + `feature/-` when a ticket ID is available. +``` + +## Customize commit messages + +Use this when your team has a commit-message convention. This is only an +example; replace it with your preferred style. + +```md +- Use Conventional Commits, such as `feat: add branch naming policy` or + `fix: handle empty branch names`. +``` + +## Publish when you say "ship it" + +Use this when you want a short phrase to authorize the agent to finish the +version-control work for its session. This commits, pushes, and creates or +updates a pull request, so use it only when the agent is allowed to publish. + +```md +- When I say "ship it", commit this session's changes on its dedicated + GitButler branch, creating one if needed. +- Push the branch and open or update its pull request with GitButler. +- Reuse the existing branch or pull request for this session when one already + exists. +``` + +For background, see [`but push`](/commands/but-push) and +[`but pr`](/commands/but-pr). + +## Update from main automatically + +Use this when your project moves quickly and you want the agent to keep its +workspace current with the target branch, usually `main` or `master`. The +GitButler command for this is `but pull`, which fetches the target branch and +rebases applied branches onto the new target commit. This is a preference: in +some repositories, you may want the agent to ask before updating. + +Add the last bullet only if you want the agent to handle update conflicts. + +```md +- When GitButler status shows new changes on the target branch, run + `but pull --check`. +- If the check is clean and the update affects only this session's branches, + update the workspace with `but pull`. +- If the check reports conflicts or the update would affect another agent's + branch, ask before updating. +- If I ask you to handle update conflicts, use GitButler's conflict tools. Ask + before resolving semantic conflicts, dependency updates, generated files, or + conflicts involving another person's work. +``` + +You do not need to tell the agent which command to use. For background, see +[`but pull`](/commands/but-pull) and [`but resolve`](/commands/but-resolve). + +## Open draft pull requests by default + +Use this when the agent is allowed to publish work, but you still want review to +start in draft. Creating a draft pull request still publishes the branch. + +```md +- When I ask you to open a pull request, create it as a draft with GitButler + unless I say it is ready for review. +``` + +## Create a recovery point before large history edits + +Use this when you want the agent to be more cautious before reorganizing several +commits or branches. + +```md +- Before squashing, splitting, moving commits between branches, or reorganizing + multiple branches, run `but oplog snapshot -m ""`. +- Use GitButler history-edit commands such as `but move`, `but squash`, + `but reword`, `but absorb`, and `but amend` instead of raw Git rebases. +- If an operation makes the branch or history layout worse, stop and inspect the + operation log before attempting another fix. +- Prefer `but undo` or `but oplog restore` over trying to repair a bad state + with more history edits. +``` + +For command details, see [`but oplog`](/commands/but-oplog) and +[`but undo`](/commands/but-undo). + +## Split unrelated hunks + +Use this when agents tend to commit whole files even when one file contains +separate changes. + +```md +- If one file contains unrelated changes, split them by hunk instead of + committing the whole file. +- Keep tests with the behavior they verify. +- Split generated output, docs-only edits, or mechanical cleanup into separate + commits when each commit remains coherent on its own. +- If the split is ambiguous, summarize the options before committing. +``` + + +# useful-requests.mdx + +Once the GitButler skill is installed and your baseline version-control +instructions are in place, ask for the branch, commit, or pull request outcome +you want. You do not need to know the `but` commands or CLI IDs; the agent uses +those to build the structure you describe. + +Use these examples as one-off requests you can mix with normal coding prompts. +They are intentionally short; add whatever constraints matter in your repo. For +standing rules that always apply, see +[Tuning agent behavior](/ai-agents/tuning-agent-behavior). + +## Commit changes + +With the baseline instructions from +[Getting started](/ai-agents/getting-started#add-optional-agent-instructions), +the agent commits on the dedicated GitButler branch for its session. It commits +that session's changes there, not unrelated user or agent work. + +You can tell your agent: + +```text +Commit your changes. +``` + +Relevant command: [`but commit`](/commands/but-commit). + +## Clean up history + +GitButler gives the agent direct tools for moving commits, squashing commits, +rewording commits, and moving changes between commits. Describe the end result +you want instead of writing out an interactive rebase plan. + +Keep history cleanup to unpublished local work unless you explicitly authorize +rewriting pushed or shared branches. + +```text +Clean up the history. Squash WIP commits, split unrelated work, and reword +messages based on intent. Show me the plan before changing history or pushing. +``` + +Relevant commands: [`but move`](/commands/but-move), +[`but squash`](/commands/but-squash), [`but reword`](/commands/but-reword), +and [`but rub`](/commands/but-rub). + +## Split a large commit into smaller commits + +Use this when a commit is too large to review as one unit. Say how you want the +work grouped; the agent can create the intermediate commits and move the right +changes into them. + +This prompt is an example; replace the grouping rules with whatever matters for +your project. + +```text +Split this into smaller commits by concern. Keep tests with the behavior they +verify. +``` + +## Put uncommitted fixes into existing commits + +Use this after review feedback, test fixes, or a small follow-up edit that +belongs with an earlier local commit. + +```text +Amend your follow-up fixes into the appropriate local commits. +``` + +Relevant commands: [`but absorb`](/commands/but-absorb) and +[`but amend`](/commands/but-amend). + +## Take changes out of a commit + +Use this when something was committed by mistake, or when one commit contains a +change that belongs somewhere else. + +```text +Take the debug logging out of the commit and leave it uncommitted. +``` + +```text +Move the docs changes out of the feature commit and into a separate docs commit. +``` + +Relevant commands: [`but uncommit`](/commands/but-uncommit) and +[`but rub`](/commands/but-rub). + +## Create stacked pull requests + +Stacked pull requests help when one change depends on another, but reviewers can +still review the lower branch first. Creating draft PRs still pushes branches, +so use this only when the agent is allowed to publish. + +```text +Make the API work the base branch and stack the UI work on top. Create draft +PRs. +``` + +The agent can also stack or restack existing branches when the dependency +structure changes. If branches have already been pushed or reviewed, ask the +agent to show which PRs will change before restacking. If something in a stack +turns out to be independent, ask the agent to move it out into a separate +branch. + +For more background, see +[Stacked branches](/features/branch-management/stacked-branches), +[`but move`](/commands/but-move), and [`but pr`](/commands/but-pr). + +## Work in parallel + +Use parallel branches when the work does not depend on another branch. +GitButler lets multiple branches be active in the same workspace, so different +agents can work on their own branches without creating and managing separate +worktrees. + +This works best when the tasks do not depend on each other and are not editing +the same files. + +Stack branches only when one branch depends on another. For the fuller +multi-agent workflow, see [Parallel agents](/ai-agents/parallel-agents). + + +# review-agent-work.mdx + + +When your coding agent uses GitButler, it can do the version-control work for +you: create branches, commit changes, move work between commits, and reshape +local history. The agent usually does this through the GitButler CLI. + +You may still want to preview what it created or manually adjust the branch and +commit history before anything is pushed or turned into a PR. GitButler gives +you three ways to inspect and adjust that state: the TUI, the CLI, and the +Desktop Client GUI. Use this page to pick the surface you want. The detailed +CLI and Desktop workflows live in their own docs. + +## GitButler TUI + +Use the TUI when you want a terminal view of the workspace without switching to +the Desktop Client. It is useful for checking branch state, looking at what is +on a branch or still unassigned, and making small manual adjustments to branch +assignment, commit membership, or history shape. + +```sh +but tui +``` + + + +## GitButler CLI + +Use the CLI when you want exact output, scriptable commands, or the same view of +the repository state that the agent uses. + +For command details, start with the [CLI overview](/cli-overview). + +## GitButler Desktop Client + +Use the Desktop Client when you want a visual overview of branches, commits, +assigned changes, unassigned changes, parallel work, and stacked work. It is +also the visual surface for moving changes between branches and adjusting +commit history. + +```sh +but gui +``` + +For details, see the [Desktop Overview](/overview), +[Branch lanes](/features/branch-management/branch-lanes), and +[Commits](/features/branch-management/commits). + +## Operations history + +GitButler records version-control operations so you can inspect or undo local +history edits. If a branch reorganization does not look right, inspect the +operation history before making more changes. See +[Timeline](/features/timeline), [`but oplog`](/commands/but-oplog), and +[`but undo`](/commands/but-undo). From d13d57f370b8a64473b439e5387132ab530984cf Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Tue, 2 Jun 2026 22:49:50 +0200 Subject: [PATCH 2/2] Remove superseded AI integration docs --- app/.well-known/api-catalog/route.ts | 4 +- app/.well-known/mcp/server-card.json/route.ts | 37 - app/api/search/openapi/route.ts | 2 +- app/components/WebMcpTools.tsx | 2 +- app/utils/agent-ready.ts | 24 +- app/utils/discovery.ts | 4 +- .../docs/cli-guides/cli-tutorial/ai-stuff.mdx | 40 +- content/docs/commands/but-skill.mdx | 21 +- .../features/ai-integration/ai-overview.mdx | 20 - .../ai-integration/claude-code-hooks.mdx | 86 - .../features/ai-integration/cursor-hooks.mdx | 48 - .../features/ai-integration/mcp-server.mdx | 190 - .../docs/features/ai-integration/meta.json | 5 - .../docs/features/branch-management/rules.mdx | 32 +- content/docs/features/coding-agents.mdx | 151 - public/llms-full.txt | 4244 ++++++++--------- 16 files changed, 1928 insertions(+), 2982 deletions(-) delete mode 100644 app/.well-known/mcp/server-card.json/route.ts delete mode 100644 content/docs/features/ai-integration/ai-overview.mdx delete mode 100644 content/docs/features/ai-integration/claude-code-hooks.mdx delete mode 100644 content/docs/features/ai-integration/cursor-hooks.mdx delete mode 100644 content/docs/features/ai-integration/mcp-server.mdx delete mode 100644 content/docs/features/ai-integration/meta.json delete mode 100644 content/docs/features/coding-agents.mdx diff --git a/app/.well-known/api-catalog/route.ts b/app/.well-known/api-catalog/route.ts index b55007c..17c3dc0 100644 --- a/app/.well-known/api-catalog/route.ts +++ b/app/.well-known/api-catalog/route.ts @@ -13,10 +13,10 @@ export function GET(): Response { title: "Getting Started Guide" }, { - href: absoluteUrl("/features/ai-integration/mcp-server"), + href: absoluteUrl("/ai-agents/overview"), rel: "service-doc", type: "text/html", - title: "GitButler MCP Server" + title: "GitButler AI Agents" }, { href: absoluteUrl("/api/search/openapi"), diff --git a/app/.well-known/mcp/server-card.json/route.ts b/app/.well-known/mcp/server-card.json/route.ts deleted file mode 100644 index ebb8246..0000000 --- a/app/.well-known/mcp/server-card.json/route.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { absoluteUrl } from "@/app/utils/site" - -export function GET(): Response { - const document = { - name: "gitbutler-mcp", - description: - "GitButler's MCP server is exposed by the local `but mcp` command and helps coding agents checkpoint and organize repository changes.", - websiteUrl: absoluteUrl("/features/ai-integration/mcp-server"), - documentationUrl: absoluteUrl("/features/ai-integration/mcp-server"), - serverInfo: { - name: "GitButler MCP Server", - version: "1.0.0" - }, - transports: [ - { - type: "stdio", - command: "but", - args: ["mcp"] - } - ], - capabilities: { - tools: [ - { - name: "gitbutler_update_branches", - description: - "Record agent-generated file changes in GitButler so they can be grouped into branches, checkpoints, and commits." - } - ] - } - } - - return Response.json(document, { - headers: { - "cache-control": "public, max-age=3600" - } - }) -} diff --git a/app/api/search/openapi/route.ts b/app/api/search/openapi/route.ts index 3626d43..6f422db 100644 --- a/app/api/search/openapi/route.ts +++ b/app/api/search/openapi/route.ts @@ -49,7 +49,7 @@ export function GET(): Response { content: { type: "string" }, url: { type: "string", - examples: [absoluteUrl("/features/ai-integration/mcp-server")] + examples: [absoluteUrl("/ai-agents/overview")] } }, required: ["id", "type", "content", "url"] diff --git a/app/components/WebMcpTools.tsx b/app/components/WebMcpTools.tsx index f174aa6..a0e69e0 100644 --- a/app/components/WebMcpTools.tsx +++ b/app/components/WebMcpTools.tsx @@ -75,7 +75,7 @@ export default function WebMcpTools(): null { properties: { path: { type: "string", - description: "Docs path like /guide or /features/ai-integration/mcp-server." + description: "Docs path like /guide or /ai-agents/getting-started." } }, required: ["path"] diff --git a/app/utils/agent-ready.ts b/app/utils/agent-ready.ts index 6f6d61e..1ff2841 100644 --- a/app/utils/agent-ready.ts +++ b/app/utils/agent-ready.ts @@ -37,26 +37,26 @@ Use this skill when you need to explain the first-run GitButler workflow to a us ` }, { - id: "gitbutler-mcp-setup", - name: "GitButler MCP Setup", - description: "Configure a coding agent to use GitButler's MCP server from the CLI.", + id: "gitbutler-ai-agent-setup", + name: "GitButler AI Agent Setup", + description: "Configure a coding agent to use GitButler's `but` CLI and agent skill.", type: "documentation", - content: `# GitButler MCP Setup + content: `# GitButler AI Agent Setup -Use this skill when an agent needs to help a developer connect GitButler to Cursor, VS Code, or Claude Code. +Use this skill when an agent needs to help a developer organize coding-agent changes with GitButler. ## Recommended flow -1. Read the MCP setup guide at ${absoluteUrl("/features/ai-integration/mcp-server")} as markdown. -2. Confirm that the \`but\` CLI is installed before configuring the MCP server. -3. Use the documented \`but mcp\` stdio transport for agent integrations. -4. Suggest an automation rule that calls the GitButler MCP tool after file edits. +1. Read /ai-agents/getting-started as markdown. +2. Confirm that the \`but\` CLI is installed. +3. Install or update the GitButler agent skill with \`but skill install\`. +4. Add baseline version-control instructions so the agent uses GitButler for branching, committing, pushing, and history edits. ## Key references -- MCP server guide: ${absoluteUrl("/features/ai-integration/mcp-server")} -- AI overview: ${absoluteUrl("/features/ai-integration/ai-overview")} -- Claude Code hooks: ${absoluteUrl("/features/ai-integration/claude-code-hooks")} +- AI agents overview: ${absoluteUrl("/ai-agents/overview")} +- Getting started: ${absoluteUrl("/ai-agents/getting-started")} +- Tuning agent behavior: ${absoluteUrl("/ai-agents/tuning-agent-behavior")} ` }, { diff --git a/app/utils/discovery.ts b/app/utils/discovery.ts index c8b8dc6..87fc203 100644 --- a/app/utils/discovery.ts +++ b/app/utils/discovery.ts @@ -33,9 +33,9 @@ export function getDiscoveryLinks(): DiscoveryLink[] { type: "application/openapi+json" }, { - href: absoluteUrl("/features/ai-integration/mcp-server"), + href: absoluteUrl("/ai-agents/overview"), rel: "service-doc", - title: "GitButler MCP Server Docs", + title: "GitButler AI Agents Docs", type: "text/html" }, { diff --git a/content/docs/cli-guides/cli-tutorial/ai-stuff.mdx b/content/docs/cli-guides/cli-tutorial/ai-stuff.mdx index 53c1064..ff37943 100644 --- a/content/docs/cli-guides/cli-tutorial/ai-stuff.mdx +++ b/content/docs/cli-guides/cli-tutorial/ai-stuff.mdx @@ -1,33 +1,39 @@ --- title: Working with AI -description: How to use the GitButler CLI with AI and agents +description: Use AI-backed CLI options and install the GitButler skill for coding agents. --- -There are a couple of different ways that the GitButler CLI can use or interact with AI tools. Some are via `--ai` options to commands to use AI to help with tasks, others are ways that coding agents can more easily use the CLI to accomplish tasks. +Use `--ai` when you want the CLI to generate text for a single command. Use +`but skill install` when you want a coding agent to use GitButler's +version-control workflow. -## Dash Dash AI +## `--ai` options -There are a few commands that will take a `--ai` option to use a configured AI provider to generate something. +Supported commands can take `--ai` to generate text from your current changes. ### `but commit --ai` -Probably the most commonly used would be `but commit --ai`, which will take a look at the changes in the files you're committing and generate an example commit message for you. If you're not feeling like writing anything more than "did some stuff", this could be a nice option for you. +Use `but commit --ai` to generate a commit message from the changes you are +committing. -This will automatically commit the work specified with the generated message, but you can also easily edit it with `but reword ` if you wish. +This commits the selected work with the generated message. You can edit the +message afterward with `but reword `. ### `but squash --ai` -If you squash two commits together, by default it will simply concatenate the commit messages together, which is rarely what you probably want. You can easily edit the message afterwards, but if you want to let AI try to combine the messages for you, you can give `but squash --ai` a try. +Use `but squash --ai` to generate a combined commit message when squashing +commits. -We're working on integrating AI features into many more of our commands, so keep an eye out. +More commands will gain `--ai` support over time. -## Skills +## `but skill install` -If you're using an AI coding agent that can read skills, you can have GitButler automatically install a GitButler specific skill for various agents with `but skill install`. +If your coding agent can read skills, install the GitButler skill with +`but skill install`. ```git ❯ but skill install @@ -42,8 +48,16 @@ Select a skill folder format: GitHub Copilot - GitHub Copilot global skill format (./.copilot/skills/gitbutler) ``` -We keep these templates up to date, so if you update GitButler, you may want to update the skills too. +We keep these templates up to date, so if you update GitButler, you may want to +update the skill too. -## Hooks and MCP +## Agent workflow docs -You can also install explicit hooks or an MCP server if you prefer. You can read more about those options [over here](/features/ai-integration/ai-overview) +`but skill install` is only the install step. For the full workflow: + +- Start with [AI agents overview](/ai-agents/overview). +- Install and configure the skill with + [Getting started with AI agents](/ai-agents/getting-started). +- Use [Useful requests](/ai-agents/useful-requests) for prompt examples. +- Use [Tuning agent behavior](/ai-agents/tuning-agent-behavior) for standing + instructions. diff --git a/content/docs/commands/but-skill.mdx b/content/docs/commands/but-skill.mdx index 7082a79..aab9a27 100644 --- a/content/docs/commands/but-skill.mdx +++ b/content/docs/commands/but-skill.mdx @@ -1,10 +1,10 @@ --- title: "`but skill`" -description: "Manage Claude AI skills for GitButler." +description: "Manage GitButler skills for coding agents." --- -Skills provide enhanced AI capabilities for working with GitButler through -Claude Code and other AI assistants. +Skills give coding agents instructions for working with GitButler through the +`but` CLI. Use `but skill install` to install the GitButler skill files into your repository or globally. @@ -29,14 +29,14 @@ but skill install --global ### `but skill install` -Install the GitButler CLI skill files for Coding agents +Install the GitButler CLI skill files for coding agents. -By default, installs the skill into the current repository. The command -will prompt you to select a skill folder format (Claude Code, OpenCode, Codex, GitHub Copilot, -Cursor, Windsurf) unless you specify a custom path with --path. +By default, installs the skill into the current repository. The command prompts +you to select a skill folder format: Claude Code, OpenCode, Codex, GitHub +Copilot, Cursor, or Windsurf. -Use --global to install the skill in a global location instead of the -current repository. +Use `--path` to choose a custom location. Use `--global` to install the skill +in a global location instead of the current repository. ## Examples @@ -74,7 +74,7 @@ but skill install --detect ### `but skill check` -Check if installed GitButler skills are up to date with the CLI version +Check if installed GitButler skills are up to date with the CLI version. Scans for installed skill files and compares their version with the current CLI version. By default, checks both local (repository) and global installations. @@ -106,4 +106,3 @@ but skill check --global * `-g`, `--global` — Only check global installations (in home directory) * `-l`, `--local` — Only check local installations (in current repository) * `-u`, `--update` — Automatically update any outdated skills found - diff --git a/content/docs/features/ai-integration/ai-overview.mdx b/content/docs/features/ai-integration/ai-overview.mdx deleted file mode 100644 index d9a3c6c..0000000 --- a/content/docs/features/ai-integration/ai-overview.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: AI Overview -description: Overview of AI integrations with GitButler including MCP server and Claude Code hooks for automated commit management. ---- - -import ImageSection from "@/components/ImageSection" - -If you're using AI agent tools like Cursor, Windsurf, or Claude Code, GitButler can enhance your coding experience by managing commits, saving points, and more. These integrations allow you to focus on coding with your agents while GitButler handles the version control aspects. - -https://www.youtube.com/watch?v=J6xV_Wyz9zg - -There are currently three main ways to use AI tools with GitButler: - -1. **Our Coding Agent**: If you have Claude Code setup, you can use our [Code Agent](/features/coding-agents) as a GUI for running Claude Code directly. -2. **Using Hooks in Claude Code or Cursor**: This method allows you to use GitButler's CLI as hook commands to manage commits and branches in either Claude Code or Cursor. -3. **Using the MCP Server**: This method allows you to set up your AI agent to communicate with GitButler's MCP server, enabling features like automatic commits and save points. - -## Enabling the experimental feature flag - -Note that as of GitButler version `0.15.2` these features have to be enabled via an experimental feature flag. You can find that under `Global Settings` -> `Experimental` -> `GitButler Actions`. diff --git a/content/docs/features/ai-integration/claude-code-hooks.mdx b/content/docs/features/ai-integration/claude-code-hooks.mdx deleted file mode 100644 index e589e88..0000000 --- a/content/docs/features/ai-integration/claude-code-hooks.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Claude Code Hooks -description: Set up Claude Code hooks to automatically manage commits and branches when using GitButler with AI coding agents. ---- - -If you are using Claude Code, you can use the new ["hooks"](https://docs.anthropic.com/en/docs/claude-code/hooks) functionality to manage the output of even multiple simultaneous instances, while isolating all the generated code into virtual or stacked branches automatically. In this case, there is no need to set up the MCP server, as the hooks will handle everything for you. - -Here's a short video showing how GitButler works with Claude Code: - -https://youtu.be/AwwPwSc9qhA - -Ok, let's get it set up. - -## Install the GitButler CLI - -First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](./mcp-server) for more details on how to install the CLI. - -## Installing GitButler as a Hook - -Hooks in Claude Code are defined in one of your settings files. - -``` -~/.claude/settings.json - User settings -.claude/settings.json - Project settings -.claude/settings.local.json - Local project settings (not committed) -``` - -Wherever you want to add GitButler to handle your commits automatically, you can add us as a hook by adding the following to the `hooks` array in whatever settings file you want to use: - -```json -{ - "hooks": { - "PreToolUse": [ - { - "matcher": "Edit|MultiEdit|Write", - "hooks": [ - { - "type": "command", - "command": "but claude pre-tool" - } - ] - } - ], - "PostToolUse": [ - { - "matcher": "Edit|MultiEdit|Write", - "hooks": [ - { - "type": "command", - "command": "but claude post-tool" - } - ] - } - ], - "Stop": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "but claude stop" - } - ] - } - ] - } -} -``` - -Essentially, you want to run the `but claude pre-tool` command before any code generation or editing, and the `but claude post-tool` command after it. The `but claude stop` command will run when you stop the agent, ensuring that all changes are committed and branches are updated accordingly. - -You also might want to add to your "memories" to ask Claude not to try commiting using Git as it will be handled by GitButler. You can do something like this: - -``` -❯ cat ~/.claude/CLAUDE.md -## Development Workflow -- Never use the git commit command after a task is finished. -``` - -## Using GitButler with Claude Code - -With the hooks setup, Claude will tell GitButler when it has generated code or edited files and in which session, which helps GitButler to try to isolate the changes into a single branch per session. - -For example, if you have three sessions of Claude Code running at the same time, each will be communicating with GitButler at each step and GitButler will be assigning each change to the correct branch automatically. - -When the agent is done, GitButler will commit all the changes and write a more sophisticated commit message based on what you had prompted your agent. diff --git a/content/docs/features/ai-integration/cursor-hooks.mdx b/content/docs/features/ai-integration/cursor-hooks.mdx deleted file mode 100644 index e007518..0000000 --- a/content/docs/features/ai-integration/cursor-hooks.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Cursor Hooks -description: Set up Cursor hooks to automatically manage commits and branches when using GitButler with AI coding in Cursor. ---- - -GitButler integrates seamlessly with Cursor through hooks that automatically manage your commits and branches while you're using AI coding features. This allows you to automatically maintain clean git history and organized parallel branches. - -Here's a short video showing how GitButler works with Cursor hooks: - -https://youtu.be/NOYK7LTFvZM - -Ok, let's get it set up. - -## Install the GitButler CLI - -First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](mcp-server) for more details on how to install the CLI. - -## Installing GitButler as a Hook - -Once the command line tool is installed, you can add the `but cursor` commands as hooks. - -You will need to create or edit your `~/.cursor/hooks.json` file (globally) or `[project]/.cursor/hooks.json` file (single project) to have `afterFileEdit` and `stop` hooks like this: - -```json -{ - "version": 1, - "hooks": { - "afterFileEdit": [ - { - "command": "but cursor after-edit" - } - ], - "stop": [ - { - "command": "but cursor stop" - } - ] - } -} -``` - -## Using GitButler with Cursor - -Once the hooks are setup, Cursor will automatically call GitButler when it edits files and when it's done with a task, which will trigger GitButler to: - -- Create a branch if the chat session is new -- Assign edits to an active branch -- Commit with a message based on the prompt when a task is done diff --git a/content/docs/features/ai-integration/mcp-server.mdx b/content/docs/features/ai-integration/mcp-server.mdx deleted file mode 100644 index edc0732..0000000 --- a/content/docs/features/ai-integration/mcp-server.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: MCP Server -description: Configure GitButler's MCP server integration with AI agents like Cursor, VSCode, and Claude Code for automatic commit management. ---- - -import ImageSection from "@/components/ImageSection" - -If you use an AI agent (such as Cursor, Windsurf, Claude Code) to help you with your code, you can easily setup GitButler to manage your commits automatically, keep save points, and more. You know, _vibe_ commit... - -## Setting up your Agent to use GitButler - -The first step is to let your agent know about GitButler, which is done via MCP - you need to tell your agent to use the GitButler MCP server. - -### Installing the CLI - -GitButler provides a CLI that can be used to interact with the GitButler platform. Before you can setup AI Agent integration, you will need to install the CLI. - -This can be found by opening the GitButler global settings, and then clicking on the "Install CLI" button in the General settings. - - - -Now that you have the `but` CLI installed, your agent can use the CLI's MCP server to interact with GitButler. - -### Cursor - -To install the GitButler MCP server in Cursor, first go to the Cursor settings, and then click on the "Extensions" tab, then click on "Tools and Integrations" and click on "New MCP Server". - -This will open your `~/.cursor/mcp.json` file. - -Add the following to the `mcpServers` object: - -```json -{ - "mcpServers": { - "gitbutler": { - "command": "but", - "args": ["mcp"] - } - } -} -``` - -You should see the GitButler MCP server in the list of MCP servers and it should have the tool `gitbutler_update_branches` available. - -### VSCode - -To install the GitButler MCP server in VSCode, you need to select "MCP: List Servers" from the actions menu. Then select "Add Server". Select "stdio" as the server type. - -Now you can type your command (`but mcp`) and name it something. After this, it should open up your settings file and show you something like this: - -```json - "mcp": { - "servers": { - Running | Stop | Restart | 1 tools - "gitbutler-mcp": { - "type": "stdio", - "command": "but", - "args": ["mcp"] - } - } - } -``` - -However, if you have Cursor's MCP already setup, VSCode will notice and help you automatically reuse the settings. - - - -### Claude Code - -Adding an MCP server to Claude Code is done by running the `claude mcp add` command. - -``` -❯ claude mcp add gitbutler but mcp -Added stdio MCP server gitbutler with command: but mcp to local config - -❯ claude mcp list -gitbutler: but mcp -``` - -## Rules: How to configure auto committing - -Once you have installed the MCP server in your editor or agent, you can optionally configure it to automatically commit your changes. - -We've found that adding something like this to your rules works well: - -``` -If you generate code or modify files, run the gitbutler update branches MCP tool. -``` - -## How to add rules - -Cursor stores its rules in `~/.cursor/rules` file, but you can also manually set them by going to the Cursor Settings pane, clicking 'Rules' and adding them to the User Rules section. - -In VSCode's Copilot Agent Mode, you can use ["custom instructions"](https://code.visualstudio.com/docs/copilot/copilot-customization#_custom-instructions) to accomplish this. - -In Claude Code, they are now called "memories" and you can add them by hitting '#' and storing them in user memory (or local if you just want them in one project). - - - -Or directly in your `~/.claude/CLAUDE.md` rules file: - -``` -❯ cat ~/.claude/CLAUDE.md -## Development Workflow -- When you're done with a task where code was created or files edited, please run the gitbutler mcp update_branches command. -``` - -## Using GitButler with your agent - -If you've set up a rule/instruction/memory, then every time a chat session is completed, the agent will send the changes and prompt to GitButler and it will automatically commit the changes. - - - -If you're using Claude Code, it may look something like this: - - - -If you don't have the agent setup to automatically call our tool, then you can also just manually type 'update gitbutler branches' in the chat, but that's a little less magical. - -## GitButler interface - -There are two phases to GitButler's MCP agent interaction. The first is the agent sending the changes and prompt to GitButler, which GitButler will quickly record and then return a success to the agent. The second is GitButler processing that raw recorded change and attempting to process that change into a commit. - -### Recording the changes - -When your agent calls the `gitbutler_update_branches` tool, GitButler will record the changes and prompt and then immediately return to the agent, so the call should be very fast. - -So for instance, let's say that I prompted my coding agent to update my `README.md` file to add a list of contributing authors. When the agent is done, it should call the update branches MCP tool, which will record a commit that looks something like this: - - - -### Processing the changes - -Then, if you have AI tooling setup, GitButler will see that and turn it into a commit message like this: - - - -You can see all of these steps in the "Actions" section of the GitButler interface, which you can toggle by hitting the "Actions" button in the top right of the interface. - - - -In the near future, we will also be able to do more interesting things like auto-absorbing changes into existing commits, creating new branches based on the prompt theme, creating stacked branches, and more. diff --git a/content/docs/features/ai-integration/meta.json b/content/docs/features/ai-integration/meta.json deleted file mode 100644 index 55d80f4..0000000 --- a/content/docs/features/ai-integration/meta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "AI Agent Integrations", - "defaultOpen": false, - "pages": ["ai-overview", "mcp-server", "claude-code-hooks", "cursor-hooks"] -} diff --git a/content/docs/features/branch-management/rules.mdx b/content/docs/features/branch-management/rules.mdx index 2d17e37..73d4c35 100644 --- a/content/docs/features/branch-management/rules.mdx +++ b/content/docs/features/branch-management/rules.mdx @@ -3,8 +3,6 @@ title: Rules description: Automate change assignment with rules that match file patterns and automatically route changes to the right branch. --- -import ImageSection from "@/components/ImageSection"; - Rules are a powerful automation feature in GitButler that automatically assign file changes to specific branches based on conditions you define. Instead of manually dragging changes between lanes, you can set up rules that automatically route changes where they belong. ## Overview @@ -53,7 +51,7 @@ If you don't add any filters, the rule will match all changes. ## Filter Types -Rules support several types of filters to match changes: +Rules support filters that match file paths or changed line content. ### Path Matches Regex @@ -89,33 +87,13 @@ Matches the content of changed lines using a regular expression pattern. This fi Creating a rule that assigns changes containing "fix" to a specific branch

-### Claude Code Session ID - -Matches changes that originated from a specific Claude Code session. This filter is automatically used when GitButler's AI features create branches and rules for you. - -**Note**: Rules with Claude Code Session ID filters have lower priority than manually created rules. If a change matches both an AI-generated rule and a manual rule, the manual rule takes precedence. - - -

- AI-generated rules based on Claude Code sessions -

- ## Managing Rules ### Editing Rules To edit an existing rule: -1. Double-click the rule or click the elepsis menu (...) and select "Edit rule" +1. Double-click the rule or click the ellipsis menu (...) and select "Edit rule" 2. Modify the branch assignment or filters 3. Click **Save rule** @@ -123,12 +101,10 @@ To edit an existing rule: To delete a rule: -1. Click the elepsis menu (...) on the rule +1. Click the ellipsis menu (...) on the rule 2. Select "Delete rule" 3. Confirm the deletion -**Note**: AI-generated rules and implicit rules cannot be edited. - ## Understanding Rule Evaluation ### Order Matters @@ -159,11 +135,9 @@ Rules respect hunk dependencies (locks). If a change depends on a commit in a sp ## Limitations - Rules can only assign changes to branches that exist in your workspace (applied branches) -- Implicit (AI-determined) rules cannot be edited through the UI - Rules currently only support the `assign` action for filesystem changes ## Related Features - [Parallel Branches](/features/branch-management/virtual-branches): Understanding the branch system that rules work with - [Branch Lanes](/features/branch-management/branch-lanes): How lanes are organized and how rules interact with lane positioning -- [AI Assistance](/features/branch-management/ai-assistance): How AI can create and manage rules automatically diff --git a/content/docs/features/coding-agents.mdx b/content/docs/features/coding-agents.mdx deleted file mode 100644 index ca0d0e9..0000000 --- a/content/docs/features/coding-agents.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Code Agent Assistant -description: Use our Claude Code integration to assign coding agents to specific branches, even multiple parallel branches at one time ---- - -import ImageSection from "@/components/ImageSection" - -GitButler can also orchestrate your coding agents and help automatically manage, checkpoint and commit the work that they do for you. - - - Currently the only supported agent is [Claude Code](https://www.anthropic.com/claude-code), but we - are working on more agent support. - - -You can start a session by clicking the AI stars on a branch header, or use the shortcut for a new branch and AI session in the top right corner of the window. - - - -Each session is tied to a branch such that you can run them in parallel, and changes are assigned to the respective branch as long as they are mutually exclusive. Information about the branch is also added to the respective context, giving the agent knowledge of the work they contain. - -# Setup - -There is some basic setup that may need to be done the first time, if you've never used Claude Code before. - -### Installing Claude Code - -Before you can use the agents integration, you need to have Claude Code installed as we wrap the SDK that it provides. If we can't find the binary, you should see something like this: - - - -To install Claude Code, you can read through the docs [here](https://docs.anthropic.com/en/docs/claude-code/quickstart), but the simple version is to use their "Native Install" method: - -{/* */} - - - - ```bash - curl -fsSL https://claude.ai/install.sh | bash - ``` - - - ```bash - irm https://claude.ai/install.ps1 | iex - ``` - - - ```bash - curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del - install.cmd - ``` - - -{/* */} - -You will then need to setup and login to Claude Code, which will require an Anthropic account. You can either connect it to an API key for direct billing or use one of the plans. You can learn more on the [Claude Code](https://www.anthropic.com/claude-code) page. - - - GitButler does not charge you for agent use, but Anthropic does. This goes directly through Claude - Code usage, we simply help manage the agent. - - -# Generating Code with an Agent - -Once your agent is setup, you can select a branch to work on, type in a prompt and we will run that though Claude Code, same as if you ran it in the terminal. - - - -While this is still running Claude Code, running through the GitButler UI will make sure that each agent works on the branch it is attached to. You can run multiple agents at once, each committing to their attached branches. - -### Model Selection - -There are a few different models that you can choose from for running your task. You can change your active model in the model selection dialog of the chat box. - - - -### Thinking Modes - -Claude Code also allows for selection of a "thinking mode". The lower modes are faster, the higher modes tend to take longer and be more expensive, but can produce better results. - - - -### Prompt Templates - -If you find that you're using similar prompts over and over, you can easily setup several prompt templates. Selecting one will seed the prompt with the contents of that template. - - - -You can also edit your available templates by selecting the "Edit templates" option, which opens up our JSON file in your editor of choice. The templates look something like this: - -````json -{ - "templates": [ - { - "label": "Bug Fix", - "template": "Please fix the bug in this code:\n\n```\n// Your code here\n```\n\nExpected behavior:\nActual behavior:\nSteps to reproduce:" - }, - { - "label": "Code Review", - "template": "Please review this code for:\n- Performance issues\n- Security vulnerabilities\n- Best practices\n- Code style\n\n```\n// Your code here\n```" - }, - { - "label": "Refactor", - "template": "Please refactor this code to improve:\n- Readability\n- Performance\n- Maintainability\n\n```\n// Your code here\n```\n\nRequirements:" - }, - { - "label": "Add Tests", - "template": "Please write comprehensive tests for this code:\n\n```\n// Your code here\n```\n\nTest cases should cover:\n- Happy path\n- Edge cases\n- Error conditions" - } - ] -} -```` - -### Context Clearing - -After a while, your context in a single branch can get long. If you no longer need all the context but want to keep your agent working on the same branch, you can clear it with the "Clear Context" button in the context menu. diff --git a/public/llms-full.txt b/public/llms-full.txt index fc1e5da..cd67183 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -15,7 +15,6 @@ - [fetch-push](#fetch-push.mdx) - [fixing-conflicts-outside-gitbutler](#fixing-conflicts-outside-gitbutler.mdx) - [recovering-stuff](#recovering-stuff.mdx) -- [coding-agents](#coding-agents.mdx) - [gerrit-mode](#gerrit-mode.mdx) - [timeline](#timeline.mdx) - [github-integration](#github-integration.mdx) @@ -31,10 +30,6 @@ - [stacked-branches](#stacked-branches.mdx) - [upstream-integration](#upstream-integration.mdx) - [virtual-branches](#virtual-branches.mdx) -- [ai-overview](#ai-overview.mdx) -- [claude-code-hooks](#claude-code-hooks.mdx) -- [cursor-hooks](#cursor-hooks.mdx) -- [mcp-server](#mcp-server.mdx) - [debugging](#debugging.mdx) - [contact-us](#contact-us.mdx) - [open-source](#open-source.mdx) @@ -145,6 +140,34 @@ Merge conflicts are known almost as soon as they occur and can be communicated a Parallel branches can remain applied locally until they are merged into your upstream target branch. Once integrated by any fashion (squash merge, rebase, merge), the virtual branch is automatically disposed of, keeping cruft and overhead low. +# cli-overview.mdx + +In addition to the Desktop graphical client, GitButler ships with a command line interface that allows you to do all of the same powerful things that the GUI does, but from the terminal or via scripts or agents. + +https://www.youtube.com/watch?v=Jg8L3SbgZ3o + +This includes tooling for: + +- [managing stacked and parallel branches](cli-guides/cli-tutorial/branching-and-commiting) +- [inspecting and diffing](cli-guides/cli-tutorial/inspecting) +- [an operations log and restoration of older states](cli-guides/cli-tutorial/operations-log) +- [powerful commit editing](cli-guides/cli-tutorial/rubbing) +- [upstream management](cli-guides/cli-tutorial/updating-the-base) +- [conflict resolution](cli-guides/cli-tutorial/conflict-resolution) +- [working with forges](cli-guides/cli-tutorial/forges) +- [aliases and configuration](cli-guides/cli-tutorial/configuration) + +All with a simple command line tool. + +## Quick Reference + +For a quick reference of the most commonly used commands, check out our [**GitButler CLI Cheat Sheet**](/cli/cheat) - available as a web page or downloadable PDF. + +## Getting Started + +Feel free to get started with our [Tutorial](cli-guides/installation) or just dig into the available commands. + + # overview.mdx Use GitButler with coding agents when you want messy local changes to become @@ -200,204 +223,6 @@ it is best used to get from agent changes to clean local branches, commits, and PRs or MRs quickly. -# releases.mdx - - -GitButler is released on a regular basis in two separate tracks. Their version numbers are incremented independently. - -1. **Release** - stable releases -2. **Nightly** - development releases built at minimum 1x per day via GitHub Actions. - - - -You can find the download links and changelogs for the latest releases on our [GitHub Releases](https://github.com/gitbutlerapp/gitbutler/releases). - - -## Platforms - -We bundle and ship GitButler for Mac OS, Windows, and Linux. - -### Windows - -| Arch | Format | In-app updater | -| --- | --- | --- | -| `x86_64` | `msi` | | - -### Mac OS - -| Arch | Format | In-app updater | -| --- | --- | --- | -| `x86_64` | `dmg` | | -| `arm64` | `dmg` | | - -### Linux - -| Arch | Format | In-app updater | -| --- | --- | --- | -| `x86_64` | `deb` | | -| `x86_64` | `rpm` | | -| `x86_64` | `AppImage` | | - -> Support for the Linux releases are complicated a bit through a core dependency of our framework, `libwebkit2gtk`, which is used to provide the web view on Linux. Tauri v1 required `libwebkit2gtk-4.0` which is not available in Ubuntu 24.04 or Debian 13 and newer. -> -> We've recently upgraded to Tauri v2 (as of Nightly `0.5.845` and Release `0.13.9`), and it now requires `libwebkit2gtk-4.1`. This version of the package is not available in the repositories for Ubuntu 20.04 and older as well as Debian 11 and older. -> -> For more information, check out the [pinned issue](https://github.com/tauri-apps/tauri/issues/9662) in the Tauri repository. - - -# why-gitbutler.mdx - -The GitButler manifesto, as it were. - -Everyone loves a good manifesto. So, why is there a need for a new Git client in the world? Don't we have enough? Isn't the command line just fine? - -Having cofounded GitHub, trained dozens of corporate teams on distributed version control tools and literally written the book on Git, we have spent a lot of time and energy over the last decade thinking about the source code management tools that software developers use every day. - -GitHub has changed the way that millions of developers across the world collaborate and work with their source code, but as sophisticated and user friendly as that tool is in our daily coding lives, using GitHub or GitLab or Bitbucket still requires all of those developers to work with a command line tool that is confusing, difficult to use, error prone and not originally designed or built for the workflows and processes that most developers today use. That tool is Git. - -Sure, some small minority will use a GUI of some sort, but even those tools are mostly wrappers around the core concepts of Git itself, never reimagining what source code management could be or if Git itself is actually good at helping them with the tasks they face on a daily basis. I've never personally used one because they do little that Git itself doesn't and honestly it's generally easier to just do those tasks on the command line, where it's quick and efficient and I don't have to take my hands off the keyboard. - -But what if we broke down everything that you try to accomplish with Git, with source code management tools in general, reduce them down to first principles and imagine a tool that does all of those things better? Are you using Git because it's the best way you can imagine accomplishing those tasks, or are you using it because it's what is there, it's what works with GitHub, it's the only real option? - -The reality is that source code management tools have changed very little on a fundamental level in the last 40 years. If you look at the tools and commands and interface that RCS had in the 80s, or Subversion had in the 90s, is it really massively different than how you use Git today on a daily basis? - -Yes, Git has easy branching, acceptable merging, a nice network transport method to move your code around, but you're still making manual checkins, you're still trying to remember obscure arguments, you're still losing work when things get complicated. - -GitButler is rethinking everything between when you write code in your editor of choice and when you push that code to GitHub for review. Why are you making 'wip' commits when your SCM should be recording everything for you? Why are everyone's commit messages close to useless? Why is `git blame` the best way to get context on the code your team has written? Why can't you seamlessly transition work between computers? - -We are creating not only a new kind of Git client, but an entirely new way of thinking about managing the code that you work on. A tool that helps you at every step of the software development process. A code concierge, hard at work for you to ensure that you'll never lose a moment of work again. That you'll have all the context and support you'll need around every line of code you work on. - -Managing your source code can be different, smarter, leaps ahead of the 40 year old concepts that we're using today. - -Our goal is to make sure that nobody ever has to read Scott's book again. That you don't have to learn how to manage your source code management tool. - - - - -# index.mdx - -## Overview - -GitButler is a new Source Code Management system designed to manage your branches, record and backup your work, be your Git client, help with your code and much more. Our focus is everything after writing code in your editor and before sharing it on GitHub. We're focused on your working directory and how we can help with everything you do there. - -We ship a [desktop GUI client](/overview) and [a CLI](/cli-overview) that work together. - -### Desktop Client - - - -### Command Line Interface - - - -Here you will find documentation on the product and the way that we're running our beta and building our product with your help. - -## Getting Started - -Check out our [Getting Started](/guide) guide to get started with GitButler, or check out our helpful video overview: - -https://www.youtube.com/watch?v=DhJtNNhCNLM - -## Why We're Doing This - -Read about it over [Why GitButler](/why-gitbutler) Section. - -## What We Do - -The GitButler client is a powerful Git client. You can manage your branches, work on multiple things at once, push and fetch from your Git server, easily rebase and modify commits and more. We have a unique approach to merge conflicts that helps split up any conflicting work. It also keeps a timeline so that you can easily undo any operation. - -- [Parallel Branches](/features/branch-management/virtual-branches) -- [First Class Conflicts](/features/branch-management/merging) -- [Project History](/features/timeline) - - -# workspace-branch.mdx - -If you run some normal Git commands (like `git log`) while in GitButler mode, you'll see a few special branches that GitButler maintains behind the scenes. The one that most people get confused by is the `gitbutler/workspace` commit. - -There are a few different reasons that we need it, so let's take a quick look. - -If you run a normal `git log` on a GitButler managed repository, you will see something like this: - -```git -commit de56d20e282f7641d48d288b510141996c3c3cfc (HEAD -> gitbutler/workspace) -Author: GitButler -Date: Wed Sep 9 09:06:03 2020 +0800 - - GitButler Workspace Commit - - This is is a merge commit of the parallel branches in your workspace. - - For GitButler to manage multiple parallel branches, we maintain - this commit automatically so other tooling works properly. - - If you switch to another branch, GitButler will need to be - reinitialized. - - Here are the branches that are currently applied: - - - update-homepage (refs/gitbutler/update-homepage) - branch head: a32f33273948837078e5f5a4e1677ab6274a4629 - - For more information about what we're doing here, check out our docs: - https://docs.gitbutler.com/workspace-branch - -commit a32f33273948837078e5f5a4e1677ab6274a4629 (update-homepage) -Author: Scott Chacon -Date: Mon Jan 26 07:33:31 2026 +0500 - - hero update - new branding - -``` - -That first commit is a merge commit that we rebuild as you modify branches in GitButler. The reason that it exists is mainly because if you have more than one branch applied in your workspace, when other tools run `git status`, it will look strange, since Git has no concept of having several branches applied at once. - -## Status, Diff and Log - -To keep Git command output for things that look at the index and HEAD (such as status or diff) somewhat sane, we modify your index to look like the union of all the committed states of all your applied parallel branches. This makes git diff and git status behave more or less like you would expect. - -For instance, if you have two files on Branch A and two files on Branch B, then git status will simply list four files as modified. - -If you run git log, the first commit should be our custom commit message and the tree of that commit is the union of all the committed work on all your applied parallel branches, as though they were all merged together into one (something stock Git can understand). - -## Committing, Branching, Checking Out - -However, if you try to use something that writes to HEAD, like git commit or git checkout, then you might have some headaches. For this reason, we install custom Git hooks for `pre-commit` and `post-checkout` that will protect this from happening. - -If you try to commit when in GitButler managed mode, the `pre-commit` hook should disallow it and tell you how to fix it. - -```git -❯ git commit -am 'commit on the workspace branch' - -GITBUTLER_ERROR: Cannot commit directly to gitbutler/workspace branch. - -GitButler manages commits on this branch. Please use GitButler to commit your changes: - - Use the GitButler app to create commits - - Or run 'but commit' from the command line - -If you want to exit GitButler mode and use normal git: - - Run 'but teardown' to switch to a regular branch - - Or directly checkout another branch: git checkout - -If you no longer have the GitButler CLI installed, you can simply remove this hook and checkout another branch: - rm ".git/hooks/pre-commit" -``` - -If you want to get out of this mode, you can follow any of those instructions. The easiest is running `but teardown`, but simply switching directly to a normal Git branch will also do the trick. - - # guide.mdx Here is a quick overview of how to get started with GitButler. In this guide, we will: @@ -617,272 +442,202 @@ To do this, click the "Operations History" button in the sidebar, find the actio /> -# cli-overview.mdx +# releases.mdx -In addition to the Desktop graphical client, GitButler ships with a command line interface that allows you to do all of the same powerful things that the GUI does, but from the terminal or via scripts or agents. -https://www.youtube.com/watch?v=Jg8L3SbgZ3o +GitButler is released on a regular basis in two separate tracks. Their version numbers are incremented independently. -This includes tooling for: +1. **Release** - stable releases +2. **Nightly** - development releases built at minimum 1x per day via GitHub Actions. -- [managing stacked and parallel branches](cli-guides/cli-tutorial/branching-and-commiting) -- [inspecting and diffing](cli-guides/cli-tutorial/inspecting) -- [an operations log and restoration of older states](cli-guides/cli-tutorial/operations-log) -- [powerful commit editing](cli-guides/cli-tutorial/rubbing) -- [upstream management](cli-guides/cli-tutorial/updating-the-base) -- [conflict resolution](cli-guides/cli-tutorial/conflict-resolution) -- [working with forges](cli-guides/cli-tutorial/forges) -- [aliases and configuration](cli-guides/cli-tutorial/configuration) -All with a simple command line tool. + +You can find the download links and changelogs for the latest releases on our [GitHub Releases](https://github.com/gitbutlerapp/gitbutler/releases). + -## Quick Reference +## Platforms -For a quick reference of the most commonly used commands, check out our [**GitButler CLI Cheat Sheet**](/cli/cheat) - available as a web page or downloadable PDF. +We bundle and ship GitButler for Mac OS, Windows, and Linux. -## Getting Started +### Windows -Feel free to get started with our [Tutorial](cli-guides/installation) or just dig into the available commands. - - -# fetch-push.mdx +| Arch | Format | In-app updater | +| --- | --- | --- | +| `x86_64` | `msi` | | +### Mac OS -If you are having trouble pushing or fetching from a remote, this is likely related to git authentication. Here are a few configuration options you can try out, found in the project settings. +| Arch | Format | In-app updater | +| --- | --- | --- | +| `x86_64` | `dmg` | | +| `arm64` | `dmg` | | -## Configuring the auto-fetch frequency +### Linux -GitButler will periodically fetch from your configured remotes in order to display new branches etc. By default, this happens every every 15 minutes. +| Arch | Format | In-app updater | +| --- | --- | --- | +| `x86_64` | `deb` | | +| `x86_64` | `rpm` | | +| `x86_64` | `AppImage` | | -You can configure the interval or completely disable this behavior by editing the application's `settings.json` file: +> Support for the Linux releases are complicated a bit through a core dependency of our framework, `libwebkit2gtk`, which is used to provide the web view on Linux. Tauri v1 required `libwebkit2gtk-4.0` which is not available in Ubuntu 24.04 or Debian 13 and newer. +> +> We've recently upgraded to Tauri v2 (as of Nightly `0.5.845` and Release `0.13.9`), and it now requires `libwebkit2gtk-4.1`. This version of the package is not available in the repositories for Ubuntu 20.04 and older as well as Debian 11 and older. +> +> For more information, check out the [pinned issue](https://github.com/tauri-apps/tauri/issues/9662) in the Tauri repository. - - ```bash ~/Library/Application\ Support/gitbutler/settings.json ``` - ```bash C:\Users\[username]\AppData\Roaming\gitbutler\settings.json ``` - ```bash ~/.config/gitbutler/settings.json ``` - -The file is in JSONC format and follows the [following schema](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but-settings/assets/defaults.jsonc) +# index.mdx -```json - "fetch": { - "autoFetchIntervalMinutes": 15 - } -``` +## Overview -A negative value (e.g. -1) disables auto fetching. Note that if `fetch` is the only entry in the JSON file, you may want to enclose it in a top-level object. +GitButler is a new Source Code Management system designed to manage your branches, record and backup your work, be your Git client, help with your code and much more. Our focus is everything after writing code in your editor and before sharing it on GitHub. We're focused on your working directory and how we can help with everything you do there. -## Available authentication methods +We ship a [desktop GUI client](/overview) and [a CLI](/cli-overview) that work together. -GitButler can be configured to use several different git authentication methods. You can switch between them in your project settings. You can try multiple different options and see if any of them are appropriate for your setup. Note that if you are on Windows, the only applicable method is the "Git executable", therefore the application will now show this as a configuration option. +### Desktop Client -### Use a Git executable (default) - -The default way to push and fetch is for GitButler to use an existing system Git executable. This should use whatever authentication mechanism that Git uses for the remote that you're trying to push to or fetch from. - -### Use an existing SSH key - -If already have an SSH key set up (eg. `~/.ssh/id_rsa`), you can instruct GitButler to use it. In case the key is password protected, you can also provide the password to it (which will be stored locally). - -### Use locally generated SSH key - -This option generates a new SSH key which will be stored locally in the application [data dir](https://docs.gitbutler.com/development/debugging#data-files). For this to work you will need to add the new public key to your Git remote provider. +### Command Line Interface -### Use a git credential helper + -If your system is set up with a credential helper, GitButler can use that. For more info on git credential helpers, see this [article](https://git-scm.com/doc/credential-helpers). +Here you will find documentation on the product and the way that we're running our beta and building our product with your help. -### FIDO security keys (YubiKey, etc.) +## Getting Started -If you're using a FIDO key, check out this issue to see how people have set it up with the Git executable method: [#2661](https://github.com/gitbutlerapp/gitbutler/issues/2661) +Check out our [Getting Started](/guide) guide to get started with GitButler, or check out our helpful video overview: -### Keys managed by 1Password +https://www.youtube.com/watch?v=DhJtNNhCNLM -Keys stored in 1Password should properly use it as an SSH agent for authentication and signing commits if you use the Git executable option. (Previously tracked in [#2779](https://github.com/gitbutlerapp/gitbutler/issues/2779)) +## Why We're Doing This -### Host certificate checks +Read about it over [Why GitButler](/why-gitbutler) Section. -There is an option to ignore host certificate checks when authenticating with ssh. This may be a helpful option to enable in some cases. +## What We Do -## Other known issues +The GitButler client is a powerful Git client. You can manage your branches, work on multiple things at once, push and fetch from your Git server, easily rebase and modify commits and more. We have a unique approach to merge conflicts that helps split up any conflicting work. It also keeps a timeline so that you can easily undo any operation. -### Git remote servers with a non-standard SSH port -In some cases, the git remote may be setup on a port number other than 22. If the port is set in your `~/.ssh/config` file, GitButler will not be able to recognize that - tracked in GitHub issue [#2700](https://github.com/gitbutlerapp/gitbutler/issues/2700). +- [Parallel Branches](/features/branch-management/virtual-branches) +- [First Class Conflicts](/features/branch-management/merging) +- [Project History](/features/timeline) -As a workaround you may set your remote in the [SSH format](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols) (eg. `ssh://git@example.com:3022/foo/bar.git`) -Updating parallel branches when the respective remote has new commits -If you have added a remote branch to your active workspace in GitButler, or pushed a virtual branch to the remote, and new commits are added to the remote branch, there is currently no way to sync those new commits into the existing virtual branch in GitButler. This is being tracked in the GitHub issue [#2649](https://github.com/gitbutlerapp/gitbutler/issues/2649). +# why-gitbutler.mdx -The current workaround is to undo any local commits and then stash your local changes manually using [git stash](https://git-scm.com/docs/git-stash) and then delete the virtual branch that has upstream changes. Then you can update the trunk by clicking the update button next to the word "Trunk" in the sidebar on the left to make sure all new upstream changes are synced, then select the remote branch that has the new changes and click the "Apply +" button above the list of commits for the branch. Once the updated branch is applied to your working directory, you can manually `git stash pop` your stashed changes and then resolve any merge conflicts. +The GitButler manifesto, as it were. -### OAuth app access restrictions on your GitHub organization +Everyone loves a good manifesto. So, why is there a need for a new Git client in the world? Don't we have enough? Isn't the command line just fine? -If you're submitting code and PRs to a repository under an organization on GitHub, you may receive an error that, despite having correct authorization credentials, your organization has enabled OAuth app access restrictions. These restrictions are an organization-level security feature designed to prevent unauthorized third-party applications from accessing organization resources. +Having cofounded GitHub, trained dozens of corporate teams on distributed version control tools and literally written the book on Git, we have spent a lot of time and energy over the last decade thinking about the source code management tools that software developers use every day. -To solve this, go to Applications. Select the "Authorized OAuth Apps" tab, and look for "GitButler Client". If you don't find "GitButler Client", it's possible you haven't yet set GitButler up for personal use. If so, try creating a test commit on a test branch for a personal repository using GitButler, which you can delete after, then check the same tab as before. +GitHub has changed the way that millions of developers across the world collaborate and work with their source code, but as sophisticated and user friendly as that tool is in our daily coding lives, using GitHub or GitLab or Bitbucket still requires all of those developers to work with a command line tool that is confusing, difficult to use, error prone and not originally designed or built for the workflows and processes that most developers today use. That tool is Git. -If you see "GitButler Client", click on it and, under "Organization Access", across from the organization you wish to enable GitButler for, click either the "Request" or "Grant" button, depending on whether you are a contributor or owner, respectively. If you're a contributor clicking "Request", note that you'll need to wait for an organization owner to approve your access request before you can proceed. +Sure, some small minority will use a GUI of some sort, but even those tools are mostly wrappers around the core concepts of Git itself, never reimagining what source code management could be or if Git itself is actually good at helping them with the tasks they face on a daily basis. I've never personally used one because they do little that Git itself doesn't and honestly it's generally easier to just do those tasks on the command line, where it's quick and efficient and I don't have to take my hands off the keyboard. -Note for organization owners: To streamline this process for your team members, you can pre-approve GitButler for all organization members. This eliminates the need for individual access requests and approvals. This can be managed through your organization's OAuth app access settings. +But what if we broke down everything that you try to accomplish with Git, with source code management tools in general, reduce them down to first principles and imagine a tool that does all of those things better? Are you using Git because it's the best way you can imagine accomplishing those tasks, or are you using it because it's what is there, it's what works with GitHub, it's the only real option? -### Help on Discord -If none of the available options helps, feel free to hop on our [Discord](https://discord.gg/MmFkmaJ42D) and we will be happy to help you out. +The reality is that source code management tools have changed very little on a fundamental level in the last 40 years. If you look at the tools and commands and interface that RCS had in the 80s, or Subversion had in the 90s, is it really massively different than how you use Git today on a daily basis? +Yes, Git has easy branching, acceptable merging, a nice network transport method to move your code around, but you're still making manual checkins, you're still trying to remember obscure arguments, you're still losing work when things get complicated. +GitButler is rethinking everything between when you write code in your editor of choice and when you push that code to GitHub for review. Why are you making 'wip' commits when your SCM should be recording everything for you? Why are everyone's commit messages close to useless? Why is `git blame` the best way to get context on the code your team has written? Why can't you seamlessly transition work between computers? -# coding-agents.mdx +We are creating not only a new kind of Git client, but an entirely new way of thinking about managing the code that you work on. A tool that helps you at every step of the software development process. A code concierge, hard at work for you to ensure that you'll never lose a moment of work again. That you'll have all the context and support you'll need around every line of code you work on. +Managing your source code can be different, smarter, leaps ahead of the 40 year old concepts that we're using today. -GitButler can also orchestrate your coding agents and help automatically manage, checkpoint and commit the work that they do for you. +Our goal is to make sure that nobody ever has to read Scott's book again. That you don't have to learn how to manage your source code management tool. - - Currently the only supported agent is [Claude Code](https://www.anthropic.com/claude-code), but we - are working on more agent support. - + -You can start a session by clicking the AI stars on a branch header, or use the shortcut for a new branch and AI session in the top right corner of the window. - +# workspace-branch.mdx -Each session is tied to a branch such that you can run them in parallel, and changes are assigned to the respective branch as long as they are mutually exclusive. Information about the branch is also added to the respective context, giving the agent knowledge of the work they contain. +If you run some normal Git commands (like `git log`) while in GitButler mode, you'll see a few special branches that GitButler maintains behind the scenes. The one that most people get confused by is the `gitbutler/workspace` commit. -# Setup +There are a few different reasons that we need it, so let's take a quick look. -There is some basic setup that may need to be done the first time, if you've never used Claude Code before. +If you run a normal `git log` on a GitButler managed repository, you will see something like this: -### Installing Claude Code +```git +commit de56d20e282f7641d48d288b510141996c3c3cfc (HEAD -> gitbutler/workspace) +Author: GitButler +Date: Wed Sep 9 09:06:03 2020 +0800 -Before you can use the agents integration, you need to have Claude Code installed as we wrap the SDK that it provides. If we can't find the binary, you should see something like this: + GitButler Workspace Commit - + This is is a merge commit of the parallel branches in your workspace. -To install Claude Code, you can read through the docs [here](https://docs.anthropic.com/en/docs/claude-code/quickstart), but the simple version is to use their "Native Install" method: + For GitButler to manage multiple parallel branches, we maintain + this commit automatically so other tooling works properly. -{/* */} + If you switch to another branch, GitButler will need to be + reinitialized. - - - ```bash - curl -fsSL https://claude.ai/install.sh | bash - ``` - - - ```bash - irm https://claude.ai/install.ps1 | iex - ``` - - - ```bash - curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del - install.cmd - ``` - - -{/* */} + Here are the branches that are currently applied: -You will then need to setup and login to Claude Code, which will require an Anthropic account. You can either connect it to an API key for direct billing or use one of the plans. You can learn more on the [Claude Code](https://www.anthropic.com/claude-code) page. + - update-homepage (refs/gitbutler/update-homepage) + branch head: a32f33273948837078e5f5a4e1677ab6274a4629 - - GitButler does not charge you for agent use, but Anthropic does. This goes directly through Claude - Code usage, we simply help manage the agent. - + For more information about what we're doing here, check out our docs: + https://docs.gitbutler.com/workspace-branch -# Generating Code with an Agent +commit a32f33273948837078e5f5a4e1677ab6274a4629 (update-homepage) +Author: Scott Chacon +Date: Mon Jan 26 07:33:31 2026 +0500 -Once your agent is setup, you can select a branch to work on, type in a prompt and we will run that though Claude Code, same as if you ran it in the terminal. + hero update - new branding - +``` -While this is still running Claude Code, running through the GitButler UI will make sure that each agent works on the branch it is attached to. You can run multiple agents at once, each committing to their attached branches. +That first commit is a merge commit that we rebuild as you modify branches in GitButler. The reason that it exists is mainly because if you have more than one branch applied in your workspace, when other tools run `git status`, it will look strange, since Git has no concept of having several branches applied at once. -### Model Selection +## Status, Diff and Log -There are a few different models that you can choose from for running your task. You can change your active model in the model selection dialog of the chat box. +To keep Git command output for things that look at the index and HEAD (such as status or diff) somewhat sane, we modify your index to look like the union of all the committed states of all your applied parallel branches. This makes git diff and git status behave more or less like you would expect. - +For instance, if you have two files on Branch A and two files on Branch B, then git status will simply list four files as modified. -### Thinking Modes +If you run git log, the first commit should be our custom commit message and the tree of that commit is the union of all the committed work on all your applied parallel branches, as though they were all merged together into one (something stock Git can understand). -Claude Code also allows for selection of a "thinking mode". The lower modes are faster, the higher modes tend to take longer and be more expensive, but can produce better results. +## Committing, Branching, Checking Out - +However, if you try to use something that writes to HEAD, like git commit or git checkout, then you might have some headaches. For this reason, we install custom Git hooks for `pre-commit` and `post-checkout` that will protect this from happening. -### Prompt Templates +If you try to commit when in GitButler managed mode, the `pre-commit` hook should disallow it and tell you how to fix it. -If you find that you're using similar prompts over and over, you can easily setup several prompt templates. Selecting one will seed the prompt with the contents of that template. +```git +❯ git commit -am 'commit on the workspace branch' - +GITBUTLER_ERROR: Cannot commit directly to gitbutler/workspace branch. -You can also edit your available templates by selecting the "Edit templates" option, which opens up our JSON file in your editor of choice. The templates look something like this: +GitButler manages commits on this branch. Please use GitButler to commit your changes: + - Use the GitButler app to create commits + - Or run 'but commit' from the command line -````json -{ - "templates": [ - { - "label": "Bug Fix", - "template": "Please fix the bug in this code:\n\n```\n// Your code here\n```\n\nExpected behavior:\nActual behavior:\nSteps to reproduce:" - }, - { - "label": "Code Review", - "template": "Please review this code for:\n- Performance issues\n- Security vulnerabilities\n- Best practices\n- Code style\n\n```\n// Your code here\n```" - }, - { - "label": "Refactor", - "template": "Please refactor this code to improve:\n- Readability\n- Performance\n- Maintainability\n\n```\n// Your code here\n```\n\nRequirements:" - }, - { - "label": "Add Tests", - "template": "Please write comprehensive tests for this code:\n\n```\n// Your code here\n```\n\nTest cases should cover:\n- Happy path\n- Edge cases\n- Error conditions" - } - ] -} -```` +If you want to exit GitButler mode and use normal git: + - Run 'but teardown' to switch to a regular branch + - Or directly checkout another branch: git checkout -### Context Clearing +If you no longer have the GitButler CLI installed, you can simply remove this hook and checkout another branch: + rm ".git/hooks/pre-commit" +``` -After a while, your context in a single branch can get long. If you no longer need all the context but want to keep your agent working on the same branch, you can clear it with the "Clear Context" button in the context menu. +If you want to get out of this mode, you can follow any of those instructions. The easiest is running `but teardown`, but simply switching directly to a normal Git branch will also do the trick. # custom-csp.mdx @@ -947,293 +702,51 @@ Note that if `extraCsp` is the only entry in the JSON file, you may want to encl The changes will take effect the next time you start GitButler. -# recovering-stuff.mdx +# fixing-conflicts-outside-gitbutler.mdx +If you have ended up with conflicted commits and GitButler is completely +unresponsive, they can be recovered using plain git commands in the following +manner: -How to dig around our internal data to find (nearly) anything +## Consider hopping on a call with one of us. -GitButler saves data in a few different ways. As we're still in beta, sometimes things might break and it may look like you've lost work, but you almost certainly haven't. We're pretty good about saving stuff a lot. Here's how to recover almost anything you had in your working directory or parallel branches. +The resolution steps make use of some advanced git functions, if you are not +comfortable with any of the steps - we are more than happy to walk you through +any recovery processes. -## GitButler References +Join our Discord and let us know about your situation. One of us will help you +work through your problem either through text or via a call. -If everything crashes or the UI isn't working at all, you may be surprised to know that even though your parallel branches don't show up in a normal git branch output, we do actually constantly write them out as Git references (just not in refs/heads). +## Backup! +First, make a copy of your entire repo. We don't want to lose any data if we +make a mistake in recovery. -```bash title="Terminal" -❯ git for-each-ref | grep gitbutler -e63b3bac82835dc17083a785d25db8b4b46744b9 commit refs/gitbutler/add-can-create-method-to-notebook -98ef3cd6eea14ee4159a600e448271c0d777efe2 commit refs/gitbutler/add-conditional-blocks-for-image-and-video -c7e27b9f99f25160a4d5f07d5972c217bdd44319 commit refs/gitbutler/add-database-schema-conversion-script -4afdfed6c14b57491a9d295c31613fd79b92f63a commit refs/gitbutler/add-gems-for-test-group -``` +## Make a new branch +Conflicts often come up as part of a cherry pick so we want to re-perform +the rebase manually - resolving any conflicted commits as we go. -These references are just like git branches - they point to a commit that has the latest version of your branch. You can create other git branches off of them, you can push them to GitHub, etc. +I want the commits to sit on top of origin/master, so I'll run the following +commands to make a new and empty branch to re-build the branch on top of: -You will have one for each virtual branch (applied or unapplied) that you've created (that you haven't deleted). +``` +git switch -c reconstruction +git reset --hard origin/master +``` -If you've committed everything on a virtual branch, the reference will just point to the latest commit. If you have work in progress on the branch, it will point to a WIP commit that includes those changes. +## Looking at the commits -So for example, if I have the following two parallel branches, one fully committed and one with work pending: +We can now get an idea of what operations we need to perform to reconstruct the +branch. - +By running: +``` +git log --graph --oneline +``` -I can view the git branches like this: - -```bash title="Terminal" -❯ git show gitbutler/Convert-tables-to-utf8mb4 -commit 841e4db701ca41206c03f1f4fe345f7e27d05eab -Author: Scott Chacon -Date: Fri Feb 23 10:30:17 2024 +0100 - - my latest commit - -❯ git show gitbutler/Add-database-schema-conversion-script -commit d95e7f4da1611ea6bb8a80da06e66ca923fbff55 -Author: GitButler -Date: Fri Feb 23 10:30:18 2024 +0100 - - GitButler WIP Commit - - This is a WIP commit for the virtual branch 'Add database schema conversion script' - - This commit is used to store the state of the virtual branch - while you are working on it. It is not meant to be used for - anything else. -``` - -See how the `Add-database-schema-conversion-script` reference points to a "WIP commit"? The tree of that commit has all those changed files in it as though we had committed them. - -If you don't want to search through all your refs with `for-each-refs`, you can also just run a normal `git log` command and we'll show you what references we've written and which modified files are in each one: - -```bash title="Terminal" -❯ git log -commit 2d8afe0ea811b5f24b9a6f84f6d024bb323a2db5 (HEAD -> gitbutler/workspace) -Author: GitButler -Date: Fri Feb 23 10:30:18 2024 +0100 - - GitButler Integration Commit - - This is an integration commit for the parallel branches that GitButler is tracking. - - Due to GitButler managing multiple parallel branches, you cannot switch back and - forth between git branches and parallel branches easily. - - If you switch to another branch, GitButler will need to be reinitialized. - If you commit on this branch, GitButler will throw it away. - - Here are the branches that are currently applied: - - Add database schema conversion script (refs/gitbutler/Add-database-schema-conversion-script) - - butler/Gemfile - - butler/README.md - - butler/db/schema.rb - - butler/db/migrate/20240209144600_change_mysql_charset.rb - - .pscale.yml - - Convert tables to utf8mb4 (refs/gitbutler/Convert-tables-to-utf8mb4) - branch head: 841e4db701ca41206c03f1f4fe345f7e27d05eab - - butler/create_column_conversions.rb - - Your previous branch was: refs/heads/sc-branch-comments - - The sha for that commit was: 5e16e99667db9d26f78110df807853a896120ff3 - - For more information about what we're doing here, check out our docs: - https://docs.gitbutler.com/features/branch-management/integration-branch -``` - -You can see the two `gitbutler` refs under the "Here are the branches that are currently applied" section. - -Again, these are real git refs, just not under `refs/heads` so that we don't pollute your `git branch` output. But if GitButler crashes at some point, you can still push them to GitHub or whatever you want. Here is an example pushing my virtual branch to a GitHub branch called `convert-tables`: - -```bash title="Terminal" -❯ git push origin refs/gitbutler/Convert-tables-to-utf8mb4:refs/heads/convert-tables -Enumerating objects: 6, done. -Counting objects: 100% (6/6), done. -Delta compression using up to 10 threads -Compressing objects: 100% (4/4), done. -Writing objects: 100% (4/4), 474 bytes | 474.00 KiB/s, done. -Total 4 (delta 2), reused 1 (delta 0), pack-reused 0 -remote: Resolving deltas: 100% (2/2), completed with 2 local objects. -remote: -remote: Create a pull request for 'convert-tables' on GitHub by visiting: -remote: https://github.com/gitbutlerapp/web/pull/new/convert-tables -remote: -To github.com:gitbutlerapp/web.git - * [new branch] refs/gitbutler/Convert-tables-to-utf8mb4 -> convert-tables -``` - -## GitButler Operations Log - -Ok, let's say that your work was not in one of those refs for some reason. Maybe you hit some weird bug and it completely changed everything in a way where now you're sitting on the couch in the dark with a glass of whisky, slowly mumbling the word "GitButler..." and plotting your revenge. - -Most of the time, we'll have whatever you're looking for in our operations log. - -The easiest way to access this is to use the built in Project History UI: [Project History](/features/timeline) - -However, let's dig into how this works, just in case you want to check it out yourself. - -Every time that GitButler does some possibly data-changing operation, we store a snapshot of your project state in our operations log before the operation happens so you can undo it if you want to. This is stored as a Git commit history that is parallel to your projects (ie, no common parents). - -You can inspect this by looking at the `.git/gitbutler/operations-log.toml` file. - -```bash title="Terminal" -❯ tree .git/gitbutler -.git/gitbutler -├── operations-log.toml -└── virtual_branches.toml - -1 directory, 2 files - -❯ cat .git/gitbutler/operations-log.toml -head_sha = "16e47cb1d091ca9dd44327fef2f5305b09403a95" - -[modified_at] -secs_since_epoch = 1717663406 -nanos_since_epoch = 560458000 -``` - -If we look at this commit, we can see the history of all of the project history snapshots that GitButler is keeping: - -```bash title="Terminal" -❯ git log 16e47cb1d091ca9dd44327fef2f5305b09403a9 -2 -commit 16e47cb1d091ca9dd44327fef2f5305b09403a95 -Author: GitButler -Date: Thu Jun 6 10:43:26 2024 +0200 - - CreateBranch - - Version: 1 - Operation: CreateBranch - name: Virtual branch - -commit 2c95aa06d76b3230f1a51d9f89a211770d93ae51 -Author: GitButler -Date: Thu Jun 6 10:28:30 2024 +0200 - - UpdateWorkspaceBase - - Version: 1 - Operation: UpdateWorkspaceBase -``` - -You can see that before creating a branch or updating our workspace with upstream work, we're recording the state of our project so we have an undo point. So what data are we keeping here in addition to this trailer information? - -Let's look at the tree of one of these commits: - -```bash title="Terminal" -❯ git cat-file -p 16e47cb1d091ca9dd44327fef2f5305b09403a95^{tree} -040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 conflicts -040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 index -040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 target_tree -100644 blob d839dca7e14f5833ad737b4adbf337bd20489927 virtual_branches.toml -040000 tree a0821552c0e7d5defe369d577af5e3a87b442469 virtual_branches -``` - -The parallel branches toml file has the interesting metadata: - -```bash title="Terminal" -❯ git cat-file -p 16e47cb1d091ca9dd44^{tree}:virtual_branches.toml -[default_target] -branchName = "master" -remoteName = "origin" -remoteUrl = "git@github.com:gitbutlerapp/gitbutler.git" -sha = "e00e54af7f903ef84600079a45490a7f07e4702e" -pushRemoteName = "origin" - -[branch_targets] - -[branches.09ef54c4-1081-4a52-8182-a5ec725016b6] -id = "09ef54c4-1081-4a52-8182-a5ec725016b6" -name = "commit signing settings" -notes = "" -applied = false -upstream = "refs/remotes/origin/commit-signing-settings" -upstream_head = "b60a66452dfecef74103346af6a3291ad677d246" -created_timestamp_ms = "1717489406268" -updated_timestamp_ms = "1717489406268" -tree = "b28e7eefdd7b6f36456516b696146a2ea7638ca4" -head = "b60a66452dfecef74103346af6a3291ad677d246" -ownership = "" -order = 4 -selected_for_changes = 1717489406268 -``` - -The virtual_branches tree has the actual contents of those computed branches in case we need to recreate them: - - - - - - - - - - - - - - - - - - - - - - - -This allows you to get contents of any file in any of your virtual branch states as well. - - -# fixing-conflicts-outside-gitbutler.mdx - -If you have ended up with conflicted commits and GitButler is completely -unresponsive, they can be recovered using plain git commands in the following -manner: - -## Consider hopping on a call with one of us. - -The resolution steps make use of some advanced git functions, if you are not -comfortable with any of the steps - we are more than happy to walk you through -any recovery processes. - -Join our Discord and let us know about your situation. One of us will help you -work through your problem either through text or via a call. - -## Backup! - -First, make a copy of your entire repo. We don't want to lose any data if we -make a mistake in recovery. - -## Make a new branch - -Conflicts often come up as part of a cherry pick so we want to re-perform -the rebase manually - resolving any conflicted commits as we go. - -I want the commits to sit on top of origin/master, so I'll run the following -commands to make a new and empty branch to re-build the branch on top of: - -``` -git switch -c reconstruction -git reset --hard origin/master -``` - -## Looking at the commits - -We can now get an idea of what operations we need to perform to reconstruct the -branch. - -By running: - -``` -git log --graph --oneline -``` - -We can see all the commits that are in our branch. +We can see all the commits that are in our branch. For my branch, it looks as follows: @@ -1395,14 +908,414 @@ Once you have finished bringing all of your commits into your reconstruction branch, you can then push it to your remote via `git push`. -# timeline.mdx +# fetch-push.mdx -Undo nearly any of your actions or go back in time to an earlier state. +If you are having trouble pushing or fetching from a remote, this is likely related to git authentication. Here are a few configuration options you can try out, found in the project settings. -## How it works +## Configuring the auto-fetch frequency -Before GitButler does any major action, it records the state of everything (your virtual branch state, your uncommitted work, conflict state, etc) and stores it in your Git object database as snapshots. You can hit the 'revert' button on any of the entries and it will restore the state of all of these things to what they looked like when they were recorded, letting you go back in time. +GitButler will periodically fetch from your configured remotes in order to display new branches etc. By default, this happens every every 15 minutes. + +You can configure the interval or completely disable this behavior by editing the application's `settings.json` file: + + + ```bash ~/Library/Application\ Support/gitbutler/settings.json ``` + ```bash C:\Users\[username]\AppData\Roaming\gitbutler\settings.json ``` + ```bash ~/.config/gitbutler/settings.json ``` + + +The file is in JSONC format and follows the [following schema](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but-settings/assets/defaults.jsonc) + +```json + "fetch": { + "autoFetchIntervalMinutes": 15 + } +``` + +A negative value (e.g. -1) disables auto fetching. Note that if `fetch` is the only entry in the JSON file, you may want to enclose it in a top-level object. + +## Available authentication methods + +GitButler can be configured to use several different git authentication methods. You can switch between them in your project settings. You can try multiple different options and see if any of them are appropriate for your setup. Note that if you are on Windows, the only applicable method is the "Git executable", therefore the application will now show this as a configuration option. + + + +### Use a Git executable (default) + +The default way to push and fetch is for GitButler to use an existing system Git executable. This should use whatever authentication mechanism that Git uses for the remote that you're trying to push to or fetch from. + +### Use an existing SSH key + +If already have an SSH key set up (eg. `~/.ssh/id_rsa`), you can instruct GitButler to use it. In case the key is password protected, you can also provide the password to it (which will be stored locally). + +### Use locally generated SSH key + +This option generates a new SSH key which will be stored locally in the application [data dir](https://docs.gitbutler.com/development/debugging#data-files). For this to work you will need to add the new public key to your Git remote provider. + +### Use a git credential helper + +If your system is set up with a credential helper, GitButler can use that. For more info on git credential helpers, see this [article](https://git-scm.com/doc/credential-helpers). + +### FIDO security keys (YubiKey, etc.) + +If you're using a FIDO key, check out this issue to see how people have set it up with the Git executable method: [#2661](https://github.com/gitbutlerapp/gitbutler/issues/2661) + +### Keys managed by 1Password + +Keys stored in 1Password should properly use it as an SSH agent for authentication and signing commits if you use the Git executable option. (Previously tracked in [#2779](https://github.com/gitbutlerapp/gitbutler/issues/2779)) + +### Host certificate checks + +There is an option to ignore host certificate checks when authenticating with ssh. This may be a helpful option to enable in some cases. + +## Other known issues + +### Git remote servers with a non-standard SSH port +In some cases, the git remote may be setup on a port number other than 22. If the port is set in your `~/.ssh/config` file, GitButler will not be able to recognize that - tracked in GitHub issue [#2700](https://github.com/gitbutlerapp/gitbutler/issues/2700). + +As a workaround you may set your remote in the [SSH format](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols) (eg. `ssh://git@example.com:3022/foo/bar.git`) + +Updating parallel branches when the respective remote has new commits +If you have added a remote branch to your active workspace in GitButler, or pushed a virtual branch to the remote, and new commits are added to the remote branch, there is currently no way to sync those new commits into the existing virtual branch in GitButler. This is being tracked in the GitHub issue [#2649](https://github.com/gitbutlerapp/gitbutler/issues/2649). + +The current workaround is to undo any local commits and then stash your local changes manually using [git stash](https://git-scm.com/docs/git-stash) and then delete the virtual branch that has upstream changes. Then you can update the trunk by clicking the update button next to the word "Trunk" in the sidebar on the left to make sure all new upstream changes are synced, then select the remote branch that has the new changes and click the "Apply +" button above the list of commits for the branch. Once the updated branch is applied to your working directory, you can manually `git stash pop` your stashed changes and then resolve any merge conflicts. + +### OAuth app access restrictions on your GitHub organization + +If you're submitting code and PRs to a repository under an organization on GitHub, you may receive an error that, despite having correct authorization credentials, your organization has enabled OAuth app access restrictions. These restrictions are an organization-level security feature designed to prevent unauthorized third-party applications from accessing organization resources. + +To solve this, go to Applications. Select the "Authorized OAuth Apps" tab, and look for "GitButler Client". If you don't find "GitButler Client", it's possible you haven't yet set GitButler up for personal use. If so, try creating a test commit on a test branch for a personal repository using GitButler, which you can delete after, then check the same tab as before. + +If you see "GitButler Client", click on it and, under "Organization Access", across from the organization you wish to enable GitButler for, click either the "Request" or "Grant" button, depending on whether you are a contributor or owner, respectively. If you're a contributor clicking "Request", note that you'll need to wait for an organization owner to approve your access request before you can proceed. + +Note for organization owners: To streamline this process for your team members, you can pre-approve GitButler for all organization members. This eliminates the need for individual access requests and approvals. This can be managed through your organization's OAuth app access settings. + +### Help on Discord +If none of the available options helps, feel free to hop on our [Discord](https://discord.gg/MmFkmaJ42D) and we will be happy to help you out. + + + +# recovering-stuff.mdx + + +How to dig around our internal data to find (nearly) anything + +GitButler saves data in a few different ways. As we're still in beta, sometimes things might break and it may look like you've lost work, but you almost certainly haven't. We're pretty good about saving stuff a lot. Here's how to recover almost anything you had in your working directory or parallel branches. + +## GitButler References + +If everything crashes or the UI isn't working at all, you may be surprised to know that even though your parallel branches don't show up in a normal git branch output, we do actually constantly write them out as Git references (just not in refs/heads). + + +```bash title="Terminal" +❯ git for-each-ref | grep gitbutler +e63b3bac82835dc17083a785d25db8b4b46744b9 commit refs/gitbutler/add-can-create-method-to-notebook +98ef3cd6eea14ee4159a600e448271c0d777efe2 commit refs/gitbutler/add-conditional-blocks-for-image-and-video +c7e27b9f99f25160a4d5f07d5972c217bdd44319 commit refs/gitbutler/add-database-schema-conversion-script +4afdfed6c14b57491a9d295c31613fd79b92f63a commit refs/gitbutler/add-gems-for-test-group +``` + + +These references are just like git branches - they point to a commit that has the latest version of your branch. You can create other git branches off of them, you can push them to GitHub, etc. + +You will have one for each virtual branch (applied or unapplied) that you've created (that you haven't deleted). + +If you've committed everything on a virtual branch, the reference will just point to the latest commit. If you have work in progress on the branch, it will point to a WIP commit that includes those changes. + +So for example, if I have the following two parallel branches, one fully committed and one with work pending: + + + + +I can view the git branches like this: + +```bash title="Terminal" +❯ git show gitbutler/Convert-tables-to-utf8mb4 +commit 841e4db701ca41206c03f1f4fe345f7e27d05eab +Author: Scott Chacon +Date: Fri Feb 23 10:30:17 2024 +0100 + + my latest commit + +❯ git show gitbutler/Add-database-schema-conversion-script +commit d95e7f4da1611ea6bb8a80da06e66ca923fbff55 +Author: GitButler +Date: Fri Feb 23 10:30:18 2024 +0100 + + GitButler WIP Commit + + This is a WIP commit for the virtual branch 'Add database schema conversion script' + + This commit is used to store the state of the virtual branch + while you are working on it. It is not meant to be used for + anything else. +``` + +See how the `Add-database-schema-conversion-script` reference points to a "WIP commit"? The tree of that commit has all those changed files in it as though we had committed them. + +If you don't want to search through all your refs with `for-each-refs`, you can also just run a normal `git log` command and we'll show you what references we've written and which modified files are in each one: + +```bash title="Terminal" +❯ git log +commit 2d8afe0ea811b5f24b9a6f84f6d024bb323a2db5 (HEAD -> gitbutler/workspace) +Author: GitButler +Date: Fri Feb 23 10:30:18 2024 +0100 + + GitButler Integration Commit + + This is an integration commit for the parallel branches that GitButler is tracking. + + Due to GitButler managing multiple parallel branches, you cannot switch back and + forth between git branches and parallel branches easily. + + If you switch to another branch, GitButler will need to be reinitialized. + If you commit on this branch, GitButler will throw it away. + + Here are the branches that are currently applied: + - Add database schema conversion script (refs/gitbutler/Add-database-schema-conversion-script) + - butler/Gemfile + - butler/README.md + - butler/db/schema.rb + - butler/db/migrate/20240209144600_change_mysql_charset.rb + - .pscale.yml + - Convert tables to utf8mb4 (refs/gitbutler/Convert-tables-to-utf8mb4) + branch head: 841e4db701ca41206c03f1f4fe345f7e27d05eab + - butler/create_column_conversions.rb + + Your previous branch was: refs/heads/sc-branch-comments + + The sha for that commit was: 5e16e99667db9d26f78110df807853a896120ff3 + + For more information about what we're doing here, check out our docs: + https://docs.gitbutler.com/features/branch-management/integration-branch +``` + +You can see the two `gitbutler` refs under the "Here are the branches that are currently applied" section. + +Again, these are real git refs, just not under `refs/heads` so that we don't pollute your `git branch` output. But if GitButler crashes at some point, you can still push them to GitHub or whatever you want. Here is an example pushing my virtual branch to a GitHub branch called `convert-tables`: + +```bash title="Terminal" +❯ git push origin refs/gitbutler/Convert-tables-to-utf8mb4:refs/heads/convert-tables +Enumerating objects: 6, done. +Counting objects: 100% (6/6), done. +Delta compression using up to 10 threads +Compressing objects: 100% (4/4), done. +Writing objects: 100% (4/4), 474 bytes | 474.00 KiB/s, done. +Total 4 (delta 2), reused 1 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (2/2), completed with 2 local objects. +remote: +remote: Create a pull request for 'convert-tables' on GitHub by visiting: +remote: https://github.com/gitbutlerapp/web/pull/new/convert-tables +remote: +To github.com:gitbutlerapp/web.git + * [new branch] refs/gitbutler/Convert-tables-to-utf8mb4 -> convert-tables +``` + +## GitButler Operations Log + +Ok, let's say that your work was not in one of those refs for some reason. Maybe you hit some weird bug and it completely changed everything in a way where now you're sitting on the couch in the dark with a glass of whisky, slowly mumbling the word "GitButler..." and plotting your revenge. + +Most of the time, we'll have whatever you're looking for in our operations log. + +The easiest way to access this is to use the built in Project History UI: [Project History](/features/timeline) + +However, let's dig into how this works, just in case you want to check it out yourself. + +Every time that GitButler does some possibly data-changing operation, we store a snapshot of your project state in our operations log before the operation happens so you can undo it if you want to. This is stored as a Git commit history that is parallel to your projects (ie, no common parents). + +You can inspect this by looking at the `.git/gitbutler/operations-log.toml` file. + +```bash title="Terminal" +❯ tree .git/gitbutler +.git/gitbutler +├── operations-log.toml +└── virtual_branches.toml + +1 directory, 2 files + +❯ cat .git/gitbutler/operations-log.toml +head_sha = "16e47cb1d091ca9dd44327fef2f5305b09403a95" + +[modified_at] +secs_since_epoch = 1717663406 +nanos_since_epoch = 560458000 +``` + +If we look at this commit, we can see the history of all of the project history snapshots that GitButler is keeping: + +```bash title="Terminal" +❯ git log 16e47cb1d091ca9dd44327fef2f5305b09403a9 -2 +commit 16e47cb1d091ca9dd44327fef2f5305b09403a95 +Author: GitButler +Date: Thu Jun 6 10:43:26 2024 +0200 + + CreateBranch + + Version: 1 + Operation: CreateBranch + name: Virtual branch + +commit 2c95aa06d76b3230f1a51d9f89a211770d93ae51 +Author: GitButler +Date: Thu Jun 6 10:28:30 2024 +0200 + + UpdateWorkspaceBase + + Version: 1 + Operation: UpdateWorkspaceBase +``` + +You can see that before creating a branch or updating our workspace with upstream work, we're recording the state of our project so we have an undo point. So what data are we keeping here in addition to this trailer information? + +Let's look at the tree of one of these commits: + +```bash title="Terminal" +❯ git cat-file -p 16e47cb1d091ca9dd44327fef2f5305b09403a95^{tree} +040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 conflicts +040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 index +040000 tree b283f22f5abf4ed9c612c1b5b3b9a98ec25474b0 target_tree +100644 blob d839dca7e14f5833ad737b4adbf337bd20489927 virtual_branches.toml +040000 tree a0821552c0e7d5defe369d577af5e3a87b442469 virtual_branches +``` + +The parallel branches toml file has the interesting metadata: + +```bash title="Terminal" +❯ git cat-file -p 16e47cb1d091ca9dd44^{tree}:virtual_branches.toml +[default_target] +branchName = "master" +remoteName = "origin" +remoteUrl = "git@github.com:gitbutlerapp/gitbutler.git" +sha = "e00e54af7f903ef84600079a45490a7f07e4702e" +pushRemoteName = "origin" + +[branch_targets] + +[branches.09ef54c4-1081-4a52-8182-a5ec725016b6] +id = "09ef54c4-1081-4a52-8182-a5ec725016b6" +name = "commit signing settings" +notes = "" +applied = false +upstream = "refs/remotes/origin/commit-signing-settings" +upstream_head = "b60a66452dfecef74103346af6a3291ad677d246" +created_timestamp_ms = "1717489406268" +updated_timestamp_ms = "1717489406268" +tree = "b28e7eefdd7b6f36456516b696146a2ea7638ca4" +head = "b60a66452dfecef74103346af6a3291ad677d246" +ownership = "" +order = 4 +selected_for_changes = 1717489406268 +``` + +The virtual_branches tree has the actual contents of those computed branches in case we need to recreate them: + + + + + + + + + + + + + + + + + + + + + + + +This allows you to get contents of any file in any of your virtual branch states as well. + + +# gerrit-mode.mdx + +Not _everyone_ uses GitHub or GitLab to review code and collaborate. If you use the [Gerrit](https://www.gerritcodereview.com/) code review tool, GitButler has a mode for you! In fact, GitButler is the best Gerrit client there is. + +## What is Gerrit + +If you've never heard of Gerrit, it's used by large teams like the Android or Chrome projects to manage huge numbers of changes and users across large numbers of interdependent repositories. + +Here is an example of incoming changesets on the [Android project](https://android-review.googlesource.com/q/status:open+-is:wip,50): + + + +## How is Gerrit different than Pull/Merge Requests? + +Good question. With GitHub or GitLab, when you send a pull/merge request, the review process is branch based. If you add more commits on top of your branch, the changes are squashed into one big unified diff for review. Most teams tend to avoid rebasing anything that was already shared. + +Gerrit is a commit based review system. Every review is based on exactly one commit. It's very common to edit shared commits and submit new versions of them to address feedback. + +This model works _very well_ with GitButler's easy [commit editing](/features/branch-management/commits) features. With any other Git client, interactive rebasing and amending tends to be quite painful and error prone, making it fairly difficult to work with Gerrit's model. With GitButler, it's ideal. Just drag and drop changes and update your changesets easily. + +## How to turn on Gerrit Mode + +If you have a Gerrit remote, GitButler will automatically enable Gerrit Mode when the project is being added to GitButler. You can also enable it manually. +To manually turn on Gerrit Mode in GitButler, you just have to set a Git config option called `gitbutler.gerritMode` in the project you want to act in a Gerrit compatible fashion: + +``` +❯ cd my_project +❯ git config gitbutler.gerritMode 1 +``` + +## What is Gerrit Mode + +Now GitButler will change its behavior in the following ways: + +- When you commit, we will automatically inject a `Change-Id` trailer into the commit in the format that Gerrit expects. You do not need to [setup a `commit-msg` hook](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) like you do with other Git clients. +- When you push, it will not push to a matching branch name on the remote. Instead it will push to `refs/for/main` (or whatever the name of the target branch is set to be). +- After a push, we record the change url and show you the link and number for each commit automatically. + + + +We can also set some extra push options when we push, including: + +- [Topics](https://gerrit-review.googlesource.com/Documentation/cross-repository-changes.html) +- [Hashtags](https://gerrit-review.googlesource.com/Documentation/intro-user.html#hashtags) +- [WIP status](https://gerrit-review.googlesource.com/Documentation/intro-user.html#wip) + + + + +# timeline.mdx + + +Undo nearly any of your actions or go back in time to an earlier state. + +## How it works + +Before GitButler does any major action, it records the state of everything (your virtual branch state, your uncommitted work, conflict state, etc) and stores it in your Git object database as snapshots. You can hit the 'revert' button on any of the entries and it will restore the state of all of these things to what they looked like when they were recorded, letting you go back in time. -# gitlab-integration.mdx +# github-integration.mdx -Create your GitLab Merge requests without leaving GitButler. +GitButler integrates seamlessly with GitHub, allowing you to manage the pull requests associated with your branches directly from the GitButler client. -## Setting up the GitLab Integration +You can setup multiple GitHub accounts and pick which account to use for specific projects. This makes it easy to manage work across different organizations or personal repositories. -In order to set up the GitLab integration, you will need two things. Firstly, a GitLab Personal Token and the Project ID for your project. +## Setting up GitHub Integration -### Creating a GitLab Personal Token +To set up GitHub integration, you need to connect your GitButler client to your GitHub account. This is done through the GitButler settings. -To create a GitLab Personal Token, navigate to your GitLab preferences, and then click on the "Access tokens" tab. You will then see an "Add new token" button. Pressing this button will provide you with a form (as captured below) where you can specify the token name, expiration date, and scopes. We currently require the `api` scope. In this example, I've chosen to set the expiration date for the token to a year from now. +Open the GitButler settings by clicking on the profile button in the sidebar, then navigate to the **Integrations** tab, then click on the **Add account** button for GitHub. - -On completion, you will be showen the following screen which contains your GitLab Personal token. + - +This will offer you to create an account out of the following options: +- **Device Flow**: This option will generate a code and ask you to open a browser window to authorize GitButler to access your GitHub account. This is the recommended option for most users. +- **Personal Access Token**: This option allows you to manually enter a personal access token from GitHub. This is useful for users who prefer not to use OAuth or need specific scopes for their token. +- **GitHub Enterprise**: This option allows you to connect to a GitHub Enterprise instance by providing the base URL for the API and a personal access token. -### Finding your GitLab Project ID +We'll select the **Device Flow** option for this example. -Navigate to the main page of the repository you want to configure the integration for. On the top left next to the "Fork" button, you will see three dots. Click on those three dots, and click on "Copy project ID". This will copy the GitLab Project ID to your clipboard. + - +A code will be generated for you. Copy it to your clipboard. -### Configuring GitButler + -Inside GitButler, navigate to the project settings by clicking on the small cog icon in the bottom left. Scroll down to the bottom of the "Project" tab where you will see a form for entering your GitLab details. The provided GitLab Personal Token will be stored securly in your operating system's keychain. +Next, click on the **Open GitHub activation page** button. This will open a browser window to the GitHub authorization page. - -### Custom GitLab Instances + -You may also provide a different Instance URL if you are using a self-hosted GitLab instance. +Once you are on the GitHub authorization page, paste the code into the input field and it should let you know that you are authorized. -Note that if you use a custom GitLab instance, you will likely need to configure a custom CSP (Content Security Policy) to allow GitButler to connect to it. You can find more information on how to do that in the [Custom Content Security Policy (CSP)](/troubleshooting/custom-csp) section of the documentation. + -## Usage +Return to the GitButler client and click on the **Check the status** button. +If everything went well, your account should be connected and you should see your GitHub username in the Integrations tab. -You will now have a "Submit for Review" button on each branch which you can use to create a Merge Request. + - +You can always forget an account by clicking on the **Forget** button next to the account name. -Once the Merge Request is created you will be able to see the status of it from within the client. Please note that we do not yet integrate with CI status. + - +Alternatively, you can also connect your GitHub account using a Personal Access Token by selecting the **Personal Access Token** option when adding an account. +The permissions required for GitButler to manage pull requests are read access to *Metadata* and read and write access to *Pull Requests* +The required permissions might change in the future as new features are added. + + + +In the case of GitHub Enterprise, select the **GitHub Enterprise** option when adding an account. +This will ask you for the base URL of your GitHub Enterprise instance's API as well as a Personal Access Token with the same permissions as above. + +For example, if your GitHub Enterprise Server's hostname is **github.a-super-serious-company.com**, then set the base URL to **github.a-super-serious-company.com/api/v3**. + +See [GitHub's Octokit base URL documentation](https://github.com/octokit/octokit.js?tab=readme-ov-file#constructor-options) for more information. + +## Using GitButler to Manage Pull Requests + +Once you have set up GitHub integration, you can open your pull requests directly from the GitButler branch. + + + +When you create a new branch or commit changes, GitButler will automatically check if there are any associated pull requests on GitHub. You can view these pull requests in the "Pull Requests" tab in the sidebar of the Branches page. # ai-assistance.mdx @@ -1611,70 +1599,89 @@ Generates comprehensive PR descriptions when creating pull requests. - Review [troubleshooting guide](https://docs.gitbutler.com/troubleshooting/custom-csp) for advanced configurations -# gerrit-mode.mdx +# gitlab-integration.mdx -Not _everyone_ uses GitHub or GitLab to review code and collaborate. If you use the [Gerrit](https://www.gerritcodereview.com/) code review tool, GitButler has a mode for you! In fact, GitButler is the best Gerrit client there is. -## What is Gerrit +Create your GitLab Merge requests without leaving GitButler. -If you've never heard of Gerrit, it's used by large teams like the Android or Chrome projects to manage huge numbers of changes and users across large numbers of interdependent repositories. +## Setting up the GitLab Integration -Here is an example of incoming changesets on the [Android project](https://android-review.googlesource.com/q/status:open+-is:wip,50): +In order to set up the GitLab integration, you will need two things. Firstly, a GitLab Personal Token and the Project ID for your project. - +### Creating a GitLab Personal Token -## How is Gerrit different than Pull/Merge Requests? +To create a GitLab Personal Token, navigate to your GitLab preferences, and then click on the "Access tokens" tab. You will then see an "Add new token" button. Pressing this button will provide you with a form (as captured below) where you can specify the token name, expiration date, and scopes. We currently require the `api` scope. In this example, I've chosen to set the expiration date for the token to a year from now. -Good question. With GitHub or GitLab, when you send a pull/merge request, the review process is branch based. If you add more commits on top of your branch, the changes are squashed into one big unified diff for review. Most teams tend to avoid rebasing anything that was already shared. + -Gerrit is a commit based review system. Every review is based on exactly one commit. It's very common to edit shared commits and submit new versions of them to address feedback. +On completion, you will be showen the following screen which contains your GitLab Personal token. -This model works _very well_ with GitButler's easy [commit editing](/features/branch-management/commits) features. With any other Git client, interactive rebasing and amending tends to be quite painful and error prone, making it fairly difficult to work with Gerrit's model. With GitButler, it's ideal. Just drag and drop changes and update your changesets easily. + -## How to turn on Gerrit Mode +### Finding your GitLab Project ID -If you have a Gerrit remote, GitButler will automatically enable Gerrit Mode when the project is being added to GitButler. You can also enable it manually. -To manually turn on Gerrit Mode in GitButler, you just have to set a Git config option called `gitbutler.gerritMode` in the project you want to act in a Gerrit compatible fashion: +Navigate to the main page of the repository you want to configure the integration for. On the top left next to the "Fork" button, you will see three dots. Click on those three dots, and click on "Copy project ID". This will copy the GitLab Project ID to your clipboard. -``` -❯ cd my_project -❯ git config gitbutler.gerritMode 1 -``` + -## What is Gerrit Mode +### Configuring GitButler -Now GitButler will change its behavior in the following ways: +Inside GitButler, navigate to the project settings by clicking on the small cog icon in the bottom left. Scroll down to the bottom of the "Project" tab where you will see a form for entering your GitLab details. The provided GitLab Personal Token will be stored securly in your operating system's keychain. -- When you commit, we will automatically inject a `Change-Id` trailer into the commit in the format that Gerrit expects. You do not need to [setup a `commit-msg` hook](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) like you do with other Git clients. -- When you push, it will not push to a matching branch name on the remote. Instead it will push to `refs/for/main` (or whatever the name of the target branch is set to be). -- After a push, we record the change url and show you the link and number for each commit automatically. + + +### Custom GitLab Instances + +You may also provide a different Instance URL if you are using a self-hosted GitLab instance. + +Note that if you use a custom GitLab instance, you will likely need to configure a custom CSP (Content Security Policy) to allow GitButler to connect to it. You can find more information on how to do that in the [Custom Content Security Policy (CSP)](/troubleshooting/custom-csp) section of the documentation. + +## Usage + +You will now have a "Submit for Review" button on each branch which you can use to create a Merge Request. + + + +Once the Merge Request is created you will be able to see the status of it from within the client. Please note that we do not yet integrate with CI status. + + + + +# branch-lanes.mdx + + +All of your branches - remote, local, and virtual / applied or not - are managed in the Branch Tab. This is where you can see all of your branches, apply them to your workspace, and manage your parallel branches. + +You can access the Branches tab by clicking on the "Branches" icon in the sidebar. + +The interface looks something like this: -We can also set some extra push options when we push, including: +## Branch List -- [Topics](https://gerrit-review.googlesource.com/Documentation/cross-repository-changes.html) -- [Hashtags](https://gerrit-review.googlesource.com/Documentation/intro-user.html#hashtags) -- [WIP status](https://gerrit-review.googlesource.com/Documentation/intro-user.html#wip) +The first pane on the left shows you the parallel branches and stacks that you have as well as the other branches that you have available (legacy git branches, remote branches and PRs). + +All of these branches can be converted into parallel branches by clicking them and then clicking the "Apply to workspace" button on the top of the branch view (middle pane). + +Local branches can also be fully deleted here. + +### Current Workspace Target + +The "Current workspace target" is the view of the target branch that you've set. It will show you essentially a `git log` of `origin/master` or whatever you set as your target branch, and it will show you if there are any commits upstream that you have not integrated locally yet. We will automatically check for new upstream changes every few minutes, but you can also click the update button to check immediately. @@ -1832,183 +1839,55 @@ Then you can change whatever you want and when you click "Save and exit", it wil This is useful for things like getting feedback on a series and being able to go into the appropriate commit, make the changes and continue, as opposed to squashing work. -# branch-lanes.mdx - - -All of your branches - remote, local, and virtual / applied or not - are managed in the Branch Tab. This is where you can see all of your branches, apply them to your workspace, and manage your parallel branches. - -You can access the Branches tab by clicking on the "Branches" icon in the sidebar. - -The interface looks something like this: - - - -## Branch List - -The first pane on the left shows you the parallel branches and stacks that you have as well as the other branches that you have available (legacy git branches, remote branches and PRs). - -All of these branches can be converted into parallel branches by clicking them and then clicking the "Apply to workspace" button on the top of the branch view (middle pane). - -Local branches can also be fully deleted here. - -### Current Workspace Target - -The "Current workspace target" is the view of the target branch that you've set. It will show you essentially a `git log` of `origin/master` or whatever you set as your target branch, and it will show you if there are any commits upstream that you have not integrated locally yet. We will automatically check for new upstream changes every few minutes, but you can also click the update button to check immediately. - - - - -# github-integration.mdx - - -GitButler integrates seamlessly with GitHub, allowing you to manage the pull requests associated with your branches directly from the GitButler client. - -You can setup multiple GitHub accounts and pick which account to use for specific projects. This makes it easy to manage work across different organizations or personal repositories. - -## Setting up GitHub Integration - -To set up GitHub integration, you need to connect your GitButler client to your GitHub account. This is done through the GitButler settings. - -Open the GitButler settings by clicking on the profile button in the sidebar, then navigate to the **Integrations** tab, then click on the **Add account** button for GitHub. - - - - -This will offer you to create an account out of the following options: -- **Device Flow**: This option will generate a code and ask you to open a browser window to authorize GitButler to access your GitHub account. This is the recommended option for most users. -- **Personal Access Token**: This option allows you to manually enter a personal access token from GitHub. This is useful for users who prefer not to use OAuth or need specific scopes for their token. -- **GitHub Enterprise**: This option allows you to connect to a GitHub Enterprise instance by providing the base URL for the API and a personal access token. - -We'll select the **Device Flow** option for this example. - - - -A code will be generated for you. Copy it to your clipboard. - - - -Next, click on the **Open GitHub activation page** button. This will open a browser window to the GitHub authorization page. +# merging.mdx - +By default, GitButler rebases the work on your parallel branches when you update your target branch (upstream) work. -Once you are on the GitHub authorization page, paste the code into the input field and it should let you know that you are authorized. +Often this works just fine and the commits are simply rebased. Occasionally, you will have conflicts with upstream work. - +In this case, GitButler will not do what Git normally does, which is to stop at each conflicted commit and make you fix it before moving on. Instead, it will apply the changes that it can and store the commit as a "conflicted" commit and continue the rebasing process. -Return to the GitButler client and click on the **Check the status** button. -If everything went well, your account should be connected and you should see your GitHub username in the Integrations tab. +When you go to update from upstream, GitButler will show you all the branches that it will rebase and will let you know if any of them will have conflicts: -You can always forget an account by clicking on the **Forget** button next to the account name. +In this case, when you perform the rebase, that branch will then contain "conflicted" commits. They will be marked in the UI as conflicted and you can click on them to get a "resolve conflict" button to start the resolution process. -Alternatively, you can also connect your GitHub account using a Personal Access Token by selecting the **Personal Access Token** option when adding an account. -The permissions required for GitButler to manage pull requests are read access to *Metadata* and read and write access to *Pull Requests* -The required permissions might change in the future as new features are added. +When you click that, GitButler will remove the other parallel branches and other work from your working directory and check out just this commit with its conflict markers. It will show you a special "edit mode" screen, where you are directly editing this commit. -In the case of GitHub Enterprise, select the **GitHub Enterprise** option when adding an account. -This will ask you for the base URL of your GitHub Enterprise instance's API as well as a Personal Access Token with the same permissions as above. - -For example, if your GitHub Enterprise Server's hostname is **github.a-super-serious-company.com**, then set the base URL to **github.a-super-serious-company.com/api/v3**. - -See [GitHub's Octokit base URL documentation](https://github.com/octokit/octokit.js?tab=readme-ov-file#constructor-options) for more information. - -## Using GitButler to Manage Pull Requests - -Once you have set up GitHub integration, you can open your pull requests directly from the GitButler branch. +If you want to cancel this conflict resolution, you can just hit 'Cancel' and it will go back to your normal state. If you have fixed all the issues, you can click "Save and Exit" and it will commit the conflict resolution and if needed, rebase any further commits on that branch on top of your new work. - -When you create a new branch or commit changes, GitButler will automatically check if there are any associated pull requests on GitHub. You can view these pull requests in the "Pull Requests" tab in the sidebar of the Branches page. - - -# pushing-and-fetching.mdx - - -GitButler can authenticate with an upstream Git server in several different ways. - - You can just tell us to use the system Git executable, which you can setup however you want. You can use our built in SSH protocol with your own SSH key (this does not require you to have Git installed), or you can use the default [Git credentials helper](https://git-scm.com/doc/credential-helpers). - -You can set your preference (and test if it works) in your project's "Git authentication" section: - - -Once that's done, GitButler will be able to automatically fetch upstream work and push new branches to your upstream server. - # moving-branches.mdx @@ -2096,221 +1975,163 @@ If you're using GitHub integration and the branch has an associated pull request - [Parallel Branches](/features/branch-management/virtual-branches) - Core concepts of GitButler's virtual branch system -# merging.mdx - - -By default, GitButler rebases the work on your parallel branches when you update your target branch (upstream) work. - -Often this works just fine and the commits are simply rebased. Occasionally, you will have conflicts with upstream work. - -In this case, GitButler will not do what Git normally does, which is to stop at each conflicted commit and make you fix it before moving on. Instead, it will apply the changes that it can and store the commit as a "conflicted" commit and continue the rebasing process. - -When you go to update from upstream, GitButler will show you all the branches that it will rebase and will let you know if any of them will have conflicts: - - - -In this case, when you perform the rebase, that branch will then contain "conflicted" commits. They will be marked in the UI as conflicted and you can click on them to get a "resolve conflict" button to start the resolution process. - - - -When you click that, GitButler will remove the other parallel branches and other work from your working directory and check out just this commit with its conflict markers. It will show you a special "edit mode" screen, where you are directly editing this commit. - - - -If you want to cancel this conflict resolution, you can just hit 'Cancel' and it will go back to your normal state. If you have fixed all the issues, you can click "Save and Exit" and it will commit the conflict resolution and if needed, rebase any further commits on that branch on top of your new work. - - - - -# stacked-branches.mdx - +# rules.mdx -Create a stack of dependent branches to be reviewed and merged in order. +Rules are a powerful automation feature in GitButler that automatically assign file changes to specific branches based on conditions you define. Instead of manually dragging changes between lanes, you can set up rules that automatically route changes where they belong. ## Overview -GitButler allows you to create an ordered stack of branches where each branch depends on (and is based on) the previous one. -The application also supports creating the appropriate stacked Pull Requests (when used with a GitHub remote). -This is useful when you have multiple changesets that depend on each other but it is desirable to have them reviewed and merged separately (and in sequence). - -> All of the Pull Request stack orchestration is done locally in the client, which means that your repo content is not shared with a cloud service. - - - -## Use cases - -Using stacked branches (Pull Requests) can be helpful for shipping smaller changes more frequently. - -### Breaking up a larger change into smaller ones - -Consider a scenario where you are implementing a medium/large feature in your software project. -In the course of implementation you end up performing the following sub-tasks: - -1. Refactor a part of the codebase to accommodate the new feature -2. Implement an API endpoint supporting the feature -3. Implement the frontend part of the feature consuming the API +When you're working on multiple branches simultaneously, you often know in advance which types of changes should go to which branch. For example, documentation updates might always go to a `docs` branch, while UI changes go to a `feature/ui-redesign` branch. -While the feature is considered complete only when all of the subtasks are implemented, reviewed and merged, in many cases it is considered beneficial -to ship each stage of the feature on its own, potentially behind a feature flag. Not only the risk of merge conflicts with colleagues is reduced, -but also eventual bugs are easier to track down / revert / fix as compared to a single large change. +Rules eliminate the manual work of assigning changes by automatically evaluating your uncommitted changes and routing them to the appropriate branch based on filters you define. -### More granular (easier) review process +## How Rules Work -On GitHub at least, code reviews are performed on per-branch basis. While it is possible to view individual commits in a Pull Request, it is not possible to -approve and merge a subset of commits from the PR. +Rules are evaluated whenever files change in your working directory (the `fileSytemChange` trigger). Each rule consists of: -Utilizing stacked pull requests, means that the sub-tasks of a larger change are in their own PRs. -This way it is possible to approve and merge the initial part of a stack (e.g. a refactor) while still iterating on the remaining sub-tasks. +1. **Filters**: Conditions that determine which changes the rule applies to +2. **Action**: Assigns matching changes to a specific branch -## Comparison to Parallel Branches +Multiple rules can exist, and they are evaluated in order. Within a single rule, multiple filters are combined with AND logic - all conditions must match for the rule to apply. -Stacking and Parallel Branches are similar in that they allow you to separate code changes / commits into different branches. In both cases, -the changes are available in your working directory. +## Creating a Rule -The main difference is that Parallel Branches are **independent** from one another, while stacked branches **depend** on the ones that come before it. -Because of this, the two features are not mutually exclusive but rather complementary. For example a bugfix change that is unrelated to a feature -can be put in a separate virtual branch. On the other hand, a change that depends on a previous change can be put in a stacked branch above the one it depends on. +To create a rule: -In fact GitButler implements stacked branches as Parallel Branches that are split into multiple dependent branches. +1. Open the **Rules** drawer at the bottom of the GitButler interface +2. Click the **+** button to add a new rule +3. Select the target branch where matching changes should be assigned: + - Specify a branch by name + - **Leftmost lane**: The leftmost branch in your workspace + - **Rightmost lane**: The rightmost branch in your workspace +4. (Optional) Add filters to specify which changes should match +5. Click **Save rule** - +If you don't add any filters, the rule will match all changes. -## Workflow + +

+ Creating a rule that assigns changes to the leftmost lane +

-By default, parallel branches in the app are simply stacks of one. -With version `0.14.0` or newer you can create a new dependent branch within a lane by clicking the `+` button above the branch name. +## Filter Types -> The workflow below assumes a GitHub remote. If you are using a different forge, you can still use this functionality but will need to manually create/update the Pull/Merge Requests +Rules support filters that match file paths or changed line content. -1. Creating a new dependent branch forms a stack within the lane. +### Path Matches Regex - +Matches file paths using a regular expression pattern. -2. New commits land in the top branch of the stack. +**Example use cases:** - +- Match all TypeScript files: `.*\.ts$` +- Match files in a specific directory: `^src/components/.*` +- Match documentation files: `.*\.(md|mdx)$` -3. Pushing is done for the stack as a whole. Note: The Pull Requests will be created in a way where each branch points to its parent - see [Automatic branch deletion](#automatic-branch-deletion) +### Content Matches Regex - +Matches the content of changed lines using a regular expression pattern. This filter only looks at added lines (lines that start with `+` in the diff). -4. Pull requests must be created one at a time starting from the bottom of the stack. +**Example use cases:** - +- Match changes containing TODOs: `TODO` +- Match changes with specific function calls: `console\.log` +- Match changes with certain patterns: `@deprecated` -5. The PRs will contain a footer with stack information, and as you add more PRs it will keep all up to date. + +

+ Creating a rule that assigns changes containing "fix" to a specific branch +

- +## Managing Rules -6. You can drag changes into commits to amend them (e.g. incorporating review feedback) as well as move and squash commits. +### Editing Rules - - - +To edit an existing rule: -7. If a change in your stack is independent (e.g. an unrelated bugfix) it can be moved to a different virtual branch (or stack). - This works for both uncommitted changes and existing commits that you may want to relocate. +1. Double-click the rule or click the ellipsis menu (...) and select "Edit rule" +2. Modify the branch assignment or filters +3. Click **Save rule** - +### Deleting Rules -8. Review/merge your PRs starting from the bottom up. After a PR/branch from your stack has been merged, it is reflected in the Stack and you should force push to reflect the changes - on the remote as well. +To delete a rule: - - +1. Click the ellipsis menu (...) on the rule +2. Select "Delete rule" +3. Confirm the deletion -9. When all branches of a stack have been merged, the stack is complete. +## Understanding Rule Evaluation -## GitHub configuration for stacked PRs +### Order Matters -_TLDR:_ +Rules are evaluated in the order they appear in the Rules drawer (most recent first). The first matching rule determines where a change is assigned. -1. Enable automatic branch deletion [automatic branch deletion](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) - on GitHub. -2. If possible, consider using the the "Merge" strategy when merging PRs. +### AND Logic Within Rules -#### Automatic branch deletion +When a rule has multiple filters, **all filters must match** for the rule to apply. For example, a rule with both "Path Matches Regex: `.*\.ts$`" and "Content Matches Regex: `TODO`" will only match TypeScript files that contain the text "TODO" in their changes. -When reviewing a PR in a stack, it is important to be able to view only the changes in the branch that is being reviewed. -Of course, in pure Git terms, a stacked branch will contain all the changes from the branches below it. +### OR Logic Across Rules -In order to show only the expected Files changed and Commits for PRs in a stack, each PR is created to target the branch below it in the stack. -This is true for all but the bottom branch in the stack, which targets the default branch of the repository as usual. +If you want to match changes that meet any of several conditions (OR logic), create separate rules for each condition. - +### Interaction with Hunk Dependencies -> Every branch in the stack contains the commits from the branches below it. +Rules respect hunk dependencies (locks). If a change depends on a commit in a specific branch, it cannot be automatically reassigned by rules, even if it matches a rule's filters. -This of course does not mean that a Pull Request should be merged into its parent. -When the bottom branch is merged on GitHub, **if** the PR branch is deleted, -GitHub will automatically update any PRs that used to target it to target the default branch instead. +## Best Practices - +1. **Start simple**: Begin with one or two basic path-matching rules before adding complex filters +2. **Order your rules**: Place more specific rules before general catch-all rules +3. **Test your regex**: Make sure your regular expressions match what you intend - it's easy to be too broad or too narrow +4. **Use catch-all rules carefully**: A rule with no filters will match everything, which can interfere with other rules +5. **Consider your workflow**: Rules work best when you have predictable patterns in how your work is organized +6. **Leverage leftmost/rightmost**: Using position-based targeting lets you reorganize lanes without updating rules -If the newly merged branch from the bottom of the stack is not deleted, the next PR in line will still target it and there is a risk of accidentally merging it into the now out of date branch. -For this reason it is _highly recommended_ to [enable on GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) the automatic deletion of branches after merging. +## Limitations -_NB:_ If you merge the first PR but the branch is not deleted and then merge the second PR, -the app can still recover from this, see [Troubleshooting](#troubleshooting). +- Rules can only assign changes to branches that exist in your workspace (applied branches) +- Rules currently only support the `assign` action for filesystem changes -#### Merge strategy +## Related Features -The app will support any merge strategy you wish to use - "Merge", "Rebase" or "Squash". However, due to the nature of merge, -the GitButler will be able to create a slightly better experience if the "Merge" strategy is used. -The reason for this is with merge commits you will be able to merge all the branches in the stack from GitHub without having to force push in the app. +- [Parallel Branches](/features/branch-management/virtual-branches): Understanding the branch system that rules work with +- [Branch Lanes](/features/branch-management/branch-lanes): How lanes are organized and how rules interact with lane positioning -## Troubleshooting -Firstly, if you run into any issue with the app (stacking or not), you can always get in touch either -on [Discord](https://discord.com/invite/MmFkmaJ42D) or via the in-app feedback icon (we will get back via email). -With that said, here are some workarounds for common issues. +# pushing-and-fetching.mdx -#### Accidentally merged a stack branch into an already merged branch before it -If you merged the bottom Pull Request into main but the branch was _not_ deleted, then the target of the next Pull Request would not be automatically updated. -Under these conditions merging that next Pull Request, means it would be merged into the original, now out of date, bottom PR. +GitButler can authenticate with an upstream Git server in several different ways. -A mitigation for this is to rename the branch, push and re-create the Pull Request. + You can just tell us to use the system Git executable, which you can setup however you want. You can use our built in SSH protocol with your own SSH key (this does not require you to have Git installed), or you can use the default [Git credentials helper](https://git-scm.com/doc/credential-helpers). -#### Accidentally merged a branch into a branch before it (not integrated into main/master yet) +You can set your preference (and test if it works) in your project's "Git authentication" section: -Merging of branches in a stack should be done from the bottom up. With the GitHub interface, it is possible to incorrectly merge a Pull Request which is in the middle of the stack. -In this case it will merged in the parent branch. + -In order to recover from this situation you can simply force push the branches and then re-create the PR that was incorrectly merged. +Once that's done, GitButler will be able to automatically fetch upstream work and push new branches to your upstream server. # signing-commits.mdx @@ -2437,217 +2258,171 @@ Now paste in the public SSH key you copied from GitButler, name it and make sure /> -# rules.mdx +# stacked-branches.mdx -Rules are a powerful automation feature in GitButler that automatically assign file changes to specific branches based on conditions you define. Instead of manually dragging changes between lanes, you can set up rules that automatically route changes where they belong. +Create a stack of dependent branches to be reviewed and merged in order. ## Overview -When you're working on multiple branches simultaneously, you often know in advance which types of changes should go to which branch. For example, documentation updates might always go to a `docs` branch, while UI changes go to a `feature/ui-redesign` branch. - -Rules eliminate the manual work of assigning changes by automatically evaluating your uncommitted changes and routing them to the appropriate branch based on filters you define. - -## How Rules Work - -Rules are evaluated whenever files change in your working directory (the `fileSytemChange` trigger). Each rule consists of: - -1. **Filters**: Conditions that determine which changes the rule applies to -2. **Action**: Assigns matching changes to a specific branch - -Multiple rules can exist, and they are evaluated in order. Within a single rule, multiple filters are combined with AND logic - all conditions must match for the rule to apply. - -## Creating a Rule - -To create a rule: - -1. Open the **Rules** drawer at the bottom of the GitButler interface -2. Click the **+** button to add a new rule -3. Select the target branch where matching changes should be assigned: - - Specify a branch by name - - **Leftmost lane**: The leftmost branch in your workspace - - **Rightmost lane**: The rightmost branch in your workspace -4. (Optional) Add filters to specify which changes should match -5. Click **Save rule** - -If you don't add any filters, the rule will match all changes. - - -

- Creating a rule that assigns changes to the leftmost lane -

- -## Filter Types - -Rules support several types of filters to match changes: - -### Path Matches Regex +GitButler allows you to create an ordered stack of branches where each branch depends on (and is based on) the previous one. +The application also supports creating the appropriate stacked Pull Requests (when used with a GitHub remote). +This is useful when you have multiple changesets that depend on each other but it is desirable to have them reviewed and merged separately (and in sequence). -Matches file paths using a regular expression pattern. +> All of the Pull Request stack orchestration is done locally in the client, which means that your repo content is not shared with a cloud service. -**Example use cases:** + -- Match all TypeScript files: `.*\.ts$` -- Match files in a specific directory: `^src/components/.*` -- Match documentation files: `.*\.(md|mdx)$` +## Use cases -### Content Matches Regex +Using stacked branches (Pull Requests) can be helpful for shipping smaller changes more frequently. -Matches the content of changed lines using a regular expression pattern. This filter only looks at added lines (lines that start with `+` in the diff). +### Breaking up a larger change into smaller ones -**Example use cases:** +Consider a scenario where you are implementing a medium/large feature in your software project. +In the course of implementation you end up performing the following sub-tasks: -- Match changes containing TODOs: `TODO` -- Match changes with specific function calls: `console\.log` -- Match changes with certain patterns: `@deprecated` +1. Refactor a part of the codebase to accommodate the new feature +2. Implement an API endpoint supporting the feature +3. Implement the frontend part of the feature consuming the API - -

- Creating a rule that assigns changes containing "fix" to a specific branch -

+While the feature is considered complete only when all of the subtasks are implemented, reviewed and merged, in many cases it is considered beneficial +to ship each stage of the feature on its own, potentially behind a feature flag. Not only the risk of merge conflicts with colleagues is reduced, +but also eventual bugs are easier to track down / revert / fix as compared to a single large change. -### Claude Code Session ID +### More granular (easier) review process -Matches changes that originated from a specific Claude Code session. This filter is automatically used when GitButler's AI features create branches and rules for you. +On GitHub at least, code reviews are performed on per-branch basis. While it is possible to view individual commits in a Pull Request, it is not possible to +approve and merge a subset of commits from the PR. -**Note**: Rules with Claude Code Session ID filters have lower priority than manually created rules. If a change matches both an AI-generated rule and a manual rule, the manual rule takes precedence. +Utilizing stacked pull requests, means that the sub-tasks of a larger change are in their own PRs. +This way it is possible to approve and merge the initial part of a stack (e.g. a refactor) while still iterating on the remaining sub-tasks. - -

- AI-generated rules based on Claude Code sessions -

+## Comparison to Parallel Branches -## Managing Rules +Stacking and Parallel Branches are similar in that they allow you to separate code changes / commits into different branches. In both cases, +the changes are available in your working directory. -### Editing Rules +The main difference is that Parallel Branches are **independent** from one another, while stacked branches **depend** on the ones that come before it. +Because of this, the two features are not mutually exclusive but rather complementary. For example a bugfix change that is unrelated to a feature +can be put in a separate virtual branch. On the other hand, a change that depends on a previous change can be put in a stacked branch above the one it depends on. -To edit an existing rule: +In fact GitButler implements stacked branches as Parallel Branches that are split into multiple dependent branches. -1. Double-click the rule or click the elepsis menu (...) and select "Edit rule" -2. Modify the branch assignment or filters -3. Click **Save rule** + -### Deleting Rules +## Workflow -To delete a rule: +By default, parallel branches in the app are simply stacks of one. +With version `0.14.0` or newer you can create a new dependent branch within a lane by clicking the `+` button above the branch name. -1. Click the elepsis menu (...) on the rule -2. Select "Delete rule" -3. Confirm the deletion +> The workflow below assumes a GitHub remote. If you are using a different forge, you can still use this functionality but will need to manually create/update the Pull/Merge Requests -**Note**: AI-generated rules and implicit rules cannot be edited. +1. Creating a new dependent branch forms a stack within the lane. -## Understanding Rule Evaluation + -### Order Matters +2. New commits land in the top branch of the stack. -Rules are evaluated in the order they appear in the Rules drawer (most recent first). The first matching rule determines where a change is assigned. + -### AND Logic Within Rules +3. Pushing is done for the stack as a whole. Note: The Pull Requests will be created in a way where each branch points to its parent - see [Automatic branch deletion](#automatic-branch-deletion) -When a rule has multiple filters, **all filters must match** for the rule to apply. For example, a rule with both "Path Matches Regex: `.*\.ts$`" and "Content Matches Regex: `TODO`" will only match TypeScript files that contain the text "TODO" in their changes. + -### OR Logic Across Rules +4. Pull requests must be created one at a time starting from the bottom of the stack. -If you want to match changes that meet any of several conditions (OR logic), create separate rules for each condition. + -### Interaction with Hunk Dependencies +5. The PRs will contain a footer with stack information, and as you add more PRs it will keep all up to date. -Rules respect hunk dependencies (locks). If a change depends on a commit in a specific branch, it cannot be automatically reassigned by rules, even if it matches a rule's filters. + -## Best Practices +6. You can drag changes into commits to amend them (e.g. incorporating review feedback) as well as move and squash commits. -1. **Start simple**: Begin with one or two basic path-matching rules before adding complex filters -2. **Order your rules**: Place more specific rules before general catch-all rules -3. **Test your regex**: Make sure your regular expressions match what you intend - it's easy to be too broad or too narrow -4. **Use catch-all rules carefully**: A rule with no filters will match everything, which can interfere with other rules -5. **Consider your workflow**: Rules work best when you have predictable patterns in how your work is organized -6. **Leverage leftmost/rightmost**: Using position-based targeting lets you reorganize lanes without updating rules + + + -## Limitations +7. If a change in your stack is independent (e.g. an unrelated bugfix) it can be moved to a different virtual branch (or stack). + This works for both uncommitted changes and existing commits that you may want to relocate. -- Rules can only assign changes to branches that exist in your workspace (applied branches) -- Implicit (AI-determined) rules cannot be edited through the UI -- Rules currently only support the `assign` action for filesystem changes + -## Related Features +8. Review/merge your PRs starting from the bottom up. After a PR/branch from your stack has been merged, it is reflected in the Stack and you should force push to reflect the changes + on the remote as well. -- [Parallel Branches](/features/branch-management/virtual-branches): Understanding the branch system that rules work with -- [Branch Lanes](/features/branch-management/branch-lanes): How lanes are organized and how rules interact with lane positioning -- [AI Assistance](/features/branch-management/ai-assistance): How AI can create and manage rules automatically + + +9. When all branches of a stack have been merged, the stack is complete. -# virtual-branches.mdx +## GitHub configuration for stacked PRs +_TLDR:_ -Parllel branches are a powerful feature of GitButler that allow you to work on multiple branches at the same time, committing to them independently and simultaneously. This is a key part of the GitButler experience, allowing you to manage your work in a flexible and efficient way that is not possible with traditional Git tooling. +1. Enable automatic branch deletion [automatic branch deletion](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) + on GitHub. +2. If possible, consider using the the "Merge" strategy when merging PRs. -## Overview +#### Automatic branch deletion -With normal Git branching, you can only work on one branch at a time. There is one `HEAD` reference and one index. +When reviewing a PR in a stack, it is important to be able to view only the changes in the branch that is being reviewed. +Of course, in pure Git terms, a stacked branch will contain all the changes from the branches below it. -With parallel branches, you can have multiple branches applied to your working directory at the same time. Each branch is represented as a vertical lane, and you can drag changes between these lanes to commit them independently. +In order to show only the expected Files changed and Commits for PRs in a stack, each PR is created to target the branch below it in the stack. +This is true for all but the bottom branch in the stack, which targets the default branch of the repository as usual. -Each lane also has its own staging area, so you can stage changes for each branch before deciding to commit them. + - +> Every branch in the stack contains the commits from the branches below it. -## How it works +This of course does not mean that a Pull Request should be merged into its parent. +When the bottom branch is merged on GitHub, **if** the PR branch is deleted, +GitHub will automatically update any PRs that used to target it to target the default branch instead. -Let's say that you make changes to two different files and `git status` would list two modified files. In GitButler, you can "assign" the change in each file to a different "virtual" branch, then when you commit, it will create a commit that only contains the changes in that file for that branch. + -One of the nice things with this approach is that since you're starting from changes in a single working directory, you can be sure that all branches that you create from it will merge cleanly, as you're essentially starting from the merge product and extracting branches of work from it. +If the newly merged branch from the bottom of the stack is not deleted, the next PR in line will still target it and there is a risk of accidentally merging it into the now out of date branch. +For this reason it is _highly recommended_ to [enable on GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) the automatic deletion of branches after merging. + +_NB:_ If you merge the first PR but the branch is not deleted and then merge the second PR, +the app can still recover from this, see [Troubleshooting](#troubleshooting). + +#### Merge strategy +The app will support any merge strategy you wish to use - "Merge", "Rebase" or "Squash". However, due to the nature of merge, +the GitButler will be able to create a slightly better experience if the "Merge" strategy is used. +The reason for this is with merge commits you will be able to merge all the branches in the stack from GitHub without having to force push in the app. -# ai-overview.mdx +## Troubleshooting +Firstly, if you run into any issue with the app (stacking or not), you can always get in touch either +on [Discord](https://discord.com/invite/MmFkmaJ42D) or via the in-app feedback icon (we will get back via email). +With that said, here are some workarounds for common issues. -If you're using AI agent tools like Cursor, Windsurf, or Claude Code, GitButler can enhance your coding experience by managing commits, saving points, and more. These integrations allow you to focus on coding with your agents while GitButler handles the version control aspects. +#### Accidentally merged a stack branch into an already merged branch before it -https://www.youtube.com/watch?v=J6xV_Wyz9zg +If you merged the bottom Pull Request into main but the branch was _not_ deleted, then the target of the next Pull Request would not be automatically updated. +Under these conditions merging that next Pull Request, means it would be merged into the original, now out of date, bottom PR. -There are currently three main ways to use AI tools with GitButler: +A mitigation for this is to rename the branch, push and re-create the Pull Request. -1. **Our Coding Agent**: If you have Claude Code setup, you can use our [Code Agent](/features/coding-agents) as a GUI for running Claude Code directly. -2. **Using Hooks in Claude Code or Cursor**: This method allows you to use GitButler's CLI as hook commands to manage commits and branches in either Claude Code or Cursor. -3. **Using the MCP Server**: This method allows you to set up your AI agent to communicate with GitButler's MCP server, enabling features like automatic commits and save points. +#### Accidentally merged a branch into a branch before it (not integrated into main/master yet) -## Enabling the experimental feature flag +Merging of branches in a stack should be done from the bottom up. With the GitHub interface, it is possible to incorrectly merge a Pull Request which is in the middle of the stack. +In this case it will merged in the parent branch. -Note that as of GitButler version `0.15.2` these features have to be enabled via an experimental feature flag. You can find that under `Global Settings` -> `Experimental` -> `GitButler Actions`. +In order to recover from this situation you can simply force push the branches and then re-create the PR that was incorrectly merged. # upstream-integration.mdx @@ -2705,239 +2480,70 @@ However, let's say that you want to do something more complex. Maybe the other i Here you can reorder commits however you want, you can choose to skip some of them, you can squash some of them down, etc. Just make the commits look however you prefer and then hit the "Integrate changes" button and push your final result back to the server. -# cursor-hooks.mdx - -GitButler integrates seamlessly with Cursor through hooks that automatically manage your commits and branches while you're using AI coding features. This allows you to automatically maintain clean git history and organized parallel branches. - -Here's a short video showing how GitButler works with Cursor hooks: - -https://youtu.be/NOYK7LTFvZM - -Ok, let's get it set up. - -## Install the GitButler CLI - -First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](mcp-server) for more details on how to install the CLI. - -## Installing GitButler as a Hook - -Once the command line tool is installed, you can add the `but cursor` commands as hooks. - -You will need to create or edit your `~/.cursor/hooks.json` file (globally) or `[project]/.cursor/hooks.json` file (single project) to have `afterFileEdit` and `stop` hooks like this: - -```json -{ - "version": 1, - "hooks": { - "afterFileEdit": [ - { - "command": "but cursor after-edit" - } - ], - "stop": [ - { - "command": "but cursor stop" - } - ] - } -} -``` - -## Using GitButler with Cursor - -Once the hooks are setup, Cursor will automatically call GitButler when it edits files and when it's done with a task, which will trigger GitButler to: - -- Create a branch if the chat session is new -- Assign edits to an active branch -- Commit with a message based on the prompt when a task is done - - -# mcp-server.mdx - - -If you use an AI agent (such as Cursor, Windsurf, Claude Code) to help you with your code, you can easily setup GitButler to manage your commits automatically, keep save points, and more. You know, _vibe_ commit... - -## Setting up your Agent to use GitButler - -The first step is to let your agent know about GitButler, which is done via MCP - you need to tell your agent to use the GitButler MCP server. - -### Installing the CLI - -GitButler provides a CLI that can be used to interact with the GitButler platform. Before you can setup AI Agent integration, you will need to install the CLI. - -This can be found by opening the GitButler global settings, and then clicking on the "Install CLI" button in the General settings. - - - -Now that you have the `but` CLI installed, your agent can use the CLI's MCP server to interact with GitButler. - -### Cursor - -To install the GitButler MCP server in Cursor, first go to the Cursor settings, and then click on the "Extensions" tab, then click on "Tools and Integrations" and click on "New MCP Server". - -This will open your `~/.cursor/mcp.json` file. - -Add the following to the `mcpServers` object: - -```json -{ - "mcpServers": { - "gitbutler": { - "command": "but", - "args": ["mcp"] - } - } -} -``` - -You should see the GitButler MCP server in the list of MCP servers and it should have the tool `gitbutler_update_branches` available. - -### VSCode - -To install the GitButler MCP server in VSCode, you need to select "MCP: List Servers" from the actions menu. Then select "Add Server". Select "stdio" as the server type. - -Now you can type your command (`but mcp`) and name it something. After this, it should open up your settings file and show you something like this: - -```json - "mcp": { - "servers": { - Running | Stop | Restart | 1 tools - "gitbutler-mcp": { - "type": "stdio", - "command": "but", - "args": ["mcp"] - } - } - } -``` - -However, if you have Cursor's MCP already setup, VSCode will notice and help you automatically reuse the settings. - - - -### Claude Code - -Adding an MCP server to Claude Code is done by running the `claude mcp add` command. - -``` -❯ claude mcp add gitbutler but mcp -Added stdio MCP server gitbutler with command: but mcp to local config - -❯ claude mcp list -gitbutler: but mcp -``` - -## Rules: How to configure auto committing - -Once you have installed the MCP server in your editor or agent, you can optionally configure it to automatically commit your changes. +# virtual-branches.mdx -We've found that adding something like this to your rules works well: -``` -If you generate code or modify files, run the gitbutler update branches MCP tool. -``` +Parllel branches are a powerful feature of GitButler that allow you to work on multiple branches at the same time, committing to them independently and simultaneously. This is a key part of the GitButler experience, allowing you to manage your work in a flexible and efficient way that is not possible with traditional Git tooling. -## How to add rules +## Overview -Cursor stores its rules in `~/.cursor/rules` file, but you can also manually set them by going to the Cursor Settings pane, clicking 'Rules' and adding them to the User Rules section. +With normal Git branching, you can only work on one branch at a time. There is one `HEAD` reference and one index. -In VSCode's Copilot Agent Mode, you can use ["custom instructions"](https://code.visualstudio.com/docs/copilot/copilot-customization#_custom-instructions) to accomplish this. +With parallel branches, you can have multiple branches applied to your working directory at the same time. Each branch is represented as a vertical lane, and you can drag changes between these lanes to commit them independently. -In Claude Code, they are now called "memories" and you can add them by hitting '#' and storing them in user memory (or local if you just want them in one project). +Each lane also has its own staging area, so you can stage changes for each branch before deciding to commit them. -Or directly in your `~/.claude/CLAUDE.md` rules file: - -``` -❯ cat ~/.claude/CLAUDE.md -## Development Workflow -- When you're done with a task where code was created or files edited, please run the gitbutler mcp update_branches command. -``` - -## Using GitButler with your agent - -If you've set up a rule/instruction/memory, then every time a chat session is completed, the agent will send the changes and prompt to GitButler and it will automatically commit the changes. - - +## How it works -If you're using Claude Code, it may look something like this: +Let's say that you make changes to two different files and `git status` would list two modified files. In GitButler, you can "assign" the change in each file to a different "virtual" branch, then when you commit, it will create a commit that only contains the changes in that file for that branch. - +One of the nice things with this approach is that since you're starting from changes in a single working directory, you can be sure that all branches that you create from it will merge cleanly, as you're essentially starting from the merge product and extracting branches of work from it. -If you don't have the agent setup to automatically call our tool, then you can also just manually type 'update gitbutler branches' in the chat, but that's a little less magical. -## GitButler interface +# supporters.mdx -There are two phases to GitButler's MCP agent interaction. The first is the agent sending the changes and prompt to GitButler, which GitButler will quickly record and then return a success to the agent. The second is GitButler processing that raw recorded change and attempting to process that change into a commit. -### Recording the changes +Thinking about paying for Beta software? Sounds odd, right? -When your agent calls the `gitbutler_update_branches` tool, GitButler will record the changes and prompt and then immediately return to the agent, so the call should be very fast. +No worries, the main stuff in GitButler stays the same whether you pay or not. -So for instance, let's say that I prompted my coding agent to update my `README.md` file to add a list of contributing authors. When the agent is done, it should call the update branches MCP tool, which will record a commit that looks something like this: +But hey, we're all about building a cool gang here. We want to know who really digs our butler. And those early supporters? They're like VIPs to us. - +## Perks for Early Supporters -### Processing the changes +- Access to our Early Bird Discord room, for life +- Invitations to exclusive Berlin parties, when it's warm here +- Care packages of schwag, sent your way +- Pricing locked in, no matter how we decide to charge later +- First look at any new features as we go +- Whatever else we can think of over time -Then, if you have AI tooling setup, GitButler will see that and turn it into a commit message like this: +Your support helps us grow and make GitButler even better. Join us on this adventure! - +## How to Support Us +You need to have a GitButler account to support us. If you don't have one, sign up first. + + + } + href="https://gitbutler.com/profile" + title="GitButler" + description="Support GitButler with a monthly contribution" + /> + -You can see all of these steps in the "Actions" section of the GitButler interface, which you can toggle by hitting the "Actions" button in the top right of the interface. +Thanks, from the GitButler Crew! - + -In the near future, we will also be able to do more interesting things like auto-absorbing changes into existing commits, creating new branches based on the prompt theme, creating stacked branches, and more. # debugging.mdx @@ -3128,91 +2734,6 @@ There are a few ways to get in touch with us for feedback, bug reports, feature -# claude-code-hooks.mdx - -If you are using Claude Code, you can use the new ["hooks"](https://docs.anthropic.com/en/docs/claude-code/hooks) functionality to manage the output of even multiple simultaneous instances, while isolating all the generated code into virtual or stacked branches automatically. In this case, there is no need to set up the MCP server, as the hooks will handle everything for you. - -Here's a short video showing how GitButler works with Claude Code: - -https://youtu.be/AwwPwSc9qhA - -Ok, let's get it set up. - -## Install the GitButler CLI - -First, you need to install the GitButler CLI, which can be done in your General settings. See the [MCP Server documentation](./mcp-server) for more details on how to install the CLI. - -## Installing GitButler as a Hook - -Hooks in Claude Code are defined in one of your settings files. - -``` -~/.claude/settings.json - User settings -.claude/settings.json - Project settings -.claude/settings.local.json - Local project settings (not committed) -``` - -Wherever you want to add GitButler to handle your commits automatically, you can add us as a hook by adding the following to the `hooks` array in whatever settings file you want to use: - -```json -{ - "hooks": { - "PreToolUse": [ - { - "matcher": "Edit|MultiEdit|Write", - "hooks": [ - { - "type": "command", - "command": "but claude pre-tool" - } - ] - } - ], - "PostToolUse": [ - { - "matcher": "Edit|MultiEdit|Write", - "hooks": [ - { - "type": "command", - "command": "but claude post-tool" - } - ] - } - ], - "Stop": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "but claude stop" - } - ] - } - ] - } -} -``` - -Essentially, you want to run the `but claude pre-tool` command before any code generation or editing, and the `but claude post-tool` command after it. The `but claude stop` command will run when you stop the agent, ensuring that all changes are committed and branches are updated accordingly. - -You also might want to add to your "memories" to ask Claude not to try commiting using Git as it will be handled by GitButler. You can do something like this: - -``` -❯ cat ~/.claude/CLAUDE.md -## Development Workflow -- Never use the git commit command after a task is finished. -``` - -## Using GitButler with Claude Code - -With the hooks setup, Claude will tell GitButler when it has generated code or edited files and in which session, which helps GitButler to try to isolate the changes into a single branch per session. - -For example, if you have three sessions of Claude Code running at the same time, each will be communicating with GitButler at each step and GitButler will be assigning each change to the correct branch automatically. - -When the agent is done, GitButler will commit all the changes and write a more sophisticated commit message based on what you had prompted your agent. - - # open-source.mdx GitButler is a [Fair Source software project](https://blog.gitbutler.com/gitbutler-is-now-fair-source/), built on a vast foundation of open source software. We're committed to giving back to the community and supporting the projects that we rely on. @@ -3222,44 +2743,6 @@ As part of our commitment to open source, we are an early member of the [Open So You can read more about our reasoning to join the Open Source Pledge in our announcement blog post and 2024 report: [GitButler Joins the Open Source Pledge](https://blog.gitbutler.com/open-source-pledge-2024). -# supporters.mdx - - -Thinking about paying for Beta software? Sounds odd, right? - -No worries, the main stuff in GitButler stays the same whether you pay or not. - -But hey, we're all about building a cool gang here. We want to know who really digs our butler. And those early supporters? They're like VIPs to us. - -## Perks for Early Supporters - -- Access to our Early Bird Discord room, for life -- Invitations to exclusive Berlin parties, when it's warm here -- Care packages of schwag, sent your way -- Pricing locked in, no matter how we decide to charge later -- First look at any new features as we go -- Whatever else we can think of over time - -Your support helps us grow and make GitButler even better. Join us on this adventure! - -## How to Support Us -You need to have a GitButler account to support us. If you don't have one, sign up first. - - - } - href="https://gitbutler.com/profile" - title="GitButler" - description="Support GitButler with a monthly contribution" - /> - - -Thanks, from the GitButler Crew! - - - - - # but-absorb.mdx The semantic for finding "the appropriate commit" is as follows: @@ -3378,150 +2861,6 @@ Examples -# but-amend.mdx - -Wrapper for `but rub `. - -**Usage:** `but amend ` - -## Arguments - -* `` — File ID to amend (required) -* `` — Commit ID to amend into (required) - - - -# but-apply.mdx - -If you want to apply an unapplied branch to your workspace so you -can work on it, you can run `but apply `. - -This will apply the changes in that branch into your working directory -as a parallel applied branch. - -## Examples - -Apply by branch name: - -```text -but apply my-feature-branch -``` - -**Usage:** `but apply ` - -## Arguments - -* `` — Name of the branch to apply (required) - - - -# but-commit.mdx - -The `but commit` command allows you to create a new commit -on a specified branch (stack) with the current uncommitted changes. - -If there is only one branch applied, it will commit to that branch by default. - -If there are multiple branches applied, you must specify which branch to -commit to, or if in interactive mode, you will be prompted to select one. - -By default, all uncommitted changes and all changes already staged to that -branch will be included in the commit. If you only want to commit the changes -that are already staged to that branch, you can use the `--only` flag. - -It will not commit changes staged to other branches. - -Use `but commit empty --before ` or `but commit empty --after ` -to insert a blank commit. This is useful for creating a placeholder -commit that you can amend changes into later using `but mark`, `but rub` or `but absorb`. - -**Usage:** `but commit [BRANCH] [OPTIONS]` - -## Subcommands - -### `but commit empty` - -Insert a blank commit before or after the specified commit. - -This is useful for creating a placeholder commit that you can -then amend changes into later using `but mark`, `but rub` or `but absorb`. - -You can modify the empty commit message at any time using `but reword`. - -This allows for a more Jujutsu style workflow where you create commits -first and then fill them in as you work. Create an empty commit, mark it -for auto-commit, and then just work on your changes. Write the commit -message whenever you prefer. - -## Examples - -Insert at the top of the first branch (no arguments): - -```text -but commit empty -``` - -Insert before a commit: - -```text -but commit empty ab -``` - -Explicitly insert before a commit: - -```text -but commit empty --before ab -``` - -Insert after a commit (at the top of the stack if target is a branch): - -```text -but commit empty --after ab -``` - -**Usage:** `but commit empty [TARGET] [OPTIONS]` - -**Arguments:** - -* `` — The target commit or branch to insert relative to. - -If a target is provided without --before or --after, defaults to --before behavior. If no arguments are provided at all, inserts at the top of the first branch. - -**Options:** - -* `--before` `` — Insert the blank commit before this commit or branch -* `--after` `` — Insert the blank commit after this commit or branch - -## Options - -* `-m`, `--message` `` — Commit message -* `--message-file` `` — Read commit message from file -* `-c`, `--create` — Whether to create a new branch for this commit. If the branch name given matches an existing branch, that branch will be used instead. If no branch name is given, a new branch with a generated name will be created -* `-o`, `--only` — Only commit staged files, not unstaged files -* `-n`, `--no-hooks` — Bypass pre-commit hooks -* `-i`, `--ai` `` — Generate commit message using AI with optional user summary. Use --ai by itself or --ai="your instructions" (equals sign required for value) -* `-p`, `--changes` `` — Uncommitted file or hunk CLI IDs to include in the commit. Can be specified multiple times or as comma-separated values. If not specified, all uncommitted changes (or changes staged to the target branch) are committed - - - -# but-diff.mdx - -Without any arguments, it shows the diff of all uncommitted changes. -Optionally, a CLI ID argument can be provided, which chan show the diff specific to -- an uncommitted file -- a branch -- an entire stack -- a commit -- a file change within a commit - -**Usage:** `but diff [TARGET]` - -## Arguments - -* `` — The CLI ID of the entity to show the diff for - - - # but-branch.mdx This includes creating, deleting, listing, and showing details about branches. @@ -3635,27 +2974,40 @@ You can also choose to fetch and display review information, show files modified -# but-discard.mdx +# but-amend.mdx + +Wrapper for `but rub `. + +**Usage:** `but amend ` + +## Arguments + +* `` — File ID to amend (required) +* `` — Commit ID to amend into (required) + + + +# but-apply.mdx -This command permanently discards changes to files, restoring them to their -state in the HEAD commit. Use this to undo unwanted modifications. +If you want to apply an unapplied branch to your workspace so you +can work on it, you can run `but apply `. -The ID parameter should be a file ID as shown in `but status`. You can -discard a whole file or specific hunks within a file. +This will apply the changes in that branch into your working directory +as a parallel applied branch. ## Examples -Discard all changes to a file: +Apply by branch name: ```text -but discard a1 +but apply my-feature-branch ``` -**Usage:** `but discard ` +**Usage:** `but apply ` ## Arguments -* `` — The ID of the file or hunk to discard (as shown in but status) (required) +* `` — Name of the branch to apply (required) @@ -3810,6 +3162,151 @@ Disable metrics: +# but-commit.mdx + +The `but commit` command allows you to create a new commit +on a specified branch (stack) with the current uncommitted changes. + +If there is only one branch applied, it will commit to that branch by default. + +If there are multiple branches applied, you must specify which branch to +commit to, or if in interactive mode, you will be prompted to select one. + +By default, all uncommitted changes and all changes already staged to that +branch will be included in the commit. If you only want to commit the changes +that are already staged to that branch, you can use the `--only` flag. + +It will not commit changes staged to other branches. + +Use `but commit empty --before ` or `but commit empty --after ` +to insert a blank commit. This is useful for creating a placeholder +commit that you can amend changes into later using `but mark`, `but rub` or `but absorb`. + +**Usage:** `but commit [BRANCH] [OPTIONS]` + +## Subcommands + +### `but commit empty` + +Insert a blank commit before or after the specified commit. + +This is useful for creating a placeholder commit that you can +then amend changes into later using `but mark`, `but rub` or `but absorb`. + +You can modify the empty commit message at any time using `but reword`. + +This allows for a more Jujutsu style workflow where you create commits +first and then fill them in as you work. Create an empty commit, mark it +for auto-commit, and then just work on your changes. Write the commit +message whenever you prefer. + +## Examples + +Insert at the top of the first branch (no arguments): + +```text +but commit empty +``` + +Insert before a commit: + +```text +but commit empty ab +``` + +Explicitly insert before a commit: + +```text +but commit empty --before ab +``` + +Insert after a commit (at the top of the stack if target is a branch): + +```text +but commit empty --after ab +``` + +**Usage:** `but commit empty [TARGET] [OPTIONS]` + +**Arguments:** + +* `` — The target commit or branch to insert relative to. + +If a target is provided without --before or --after, defaults to --before behavior. If no arguments are provided at all, inserts at the top of the first branch. + +**Options:** + +* `--before` `` — Insert the blank commit before this commit or branch +* `--after` `` — Insert the blank commit after this commit or branch + +## Options + +* `-m`, `--message` `` — Commit message +* `--message-file` `` — Read commit message from file +* `-c`, `--create` — Whether to create a new branch for this commit. If the branch name given matches an existing branch, that branch will be used instead. If no branch name is given, a new branch with a generated name will be created +* `-o`, `--only` — Only commit staged files, not unstaged files +* `-n`, `--no-hooks` — Bypass pre-commit hooks +* `-i`, `--ai` `` — Generate commit message using AI with optional user summary. Use --ai by itself or --ai="your instructions" (equals sign required for value) +* `-p`, `--changes` `` — Uncommitted file or hunk CLI IDs to include in the commit. Can be specified multiple times or as comma-separated values. If not specified, all uncommitted changes (or changes staged to the target branch) are committed + + + +# but-diff.mdx + +Without any arguments, it shows the diff of all uncommitted changes. +Optionally, a CLI ID argument can be provided, which chan show the diff specific to +- an uncommitted file +- a branch +- an entire stack +- a commit +- a file change within a commit + +**Usage:** `but diff [TARGET]` + +## Arguments + +* `` — The CLI ID of the entity to show the diff for + + + +# but-gui.mdx + +Running `but gui` will launch the GitButler graphical user interface +in the current directory's GitButler project. + +This provides a visual way to manage branches, commits, and uncommitted +changes, complementing the command-line interface. + +You can also just run `but .` as a shorthand to open the GUI. + +**Usage:** `but gui` + + + +# but-discard.mdx + +This command permanently discards changes to files, restoring them to their +state in the HEAD commit. Use this to undo unwanted modifications. + +The ID parameter should be a file ID as shown in `but status`. You can +discard a whole file or specific hunks within a file. + +## Examples + +Discard all changes to a file: + +```text +but discard a1 +``` + +**Usage:** `but discard ` + +## Arguments + +* `` — The ID of the file or hunk to discard (as shown in but status) (required) + + + # but-mark.mdx Creates or removes a rule for auto-staging or auto-committing changes @@ -3833,17 +3330,32 @@ amended into the marked commit. -# but-gui.mdx +# but-merge.mdx -Running `but gui` will launch the GitButler graphical user interface -in the current directory's GitButler project. +If the target branch is local (`gb-local`), finds the local branch that the target +references (e.g., `gb-local/master` becomes `master`) and merges the specified +branch into that local branch. After merging, runs the equivalent of `but pull` +to update all branches. -This provides a visual way to manage branches, commits, and uncommitted -changes, complementing the command-line interface. +## Examples -You can also just run `but .` as a shorthand to open the GUI. +Merge a branch by its CLI ID: -**Usage:** `but gui` +```text +but merge bu +``` + +Merge a branch by name: + +```text +but merge my-feature-branch +``` + +**Usage:** `but merge ` + +## Arguments + +* `` — Branch ID or name to merge (required) @@ -4002,92 +3514,63 @@ but pick feature-branch -# but-pr.mdx - -If you are authenticated with a forge using but config forge auth, you can use the but pr commands to create pull requests (or merge requests) on the remote repository for your branches. - -Running but pr without a subcommand defaults to but pr new, which will prompt you to select a branch to create a PR for. - -**Usage:** `but pr ` - -## Subcommands - -### `but pr new` - -Create a new pull request for a branch. If no branch is specified, you will be prompted to select one. If there is only one branch without a PR, you will be asked to confirm - -**Usage:** `but pr new [BRANCH] [OPTIONS]` - -**Arguments:** - -* `` — The branch to create a PR for - -**Options:** - -* `-m`, `--message` `` — PR title and description. The first line is the title, the rest is the description -* `-F`, `--file` `` — Read PR title and description from file. The first line is the title, the rest is the description -* `-f`, `--with-force` — Force push even if it's not fast-forward (defaults to true) (default: `true`) -* `-s`, `--skip-force-push-protection` — Skip force push protection checks -* `-r`, `--run-hooks` — Run pre-push hooks (defaults to true) (default: `true`) -* `-t`, `--default` — Use the default content for the PR title and description, skipping any prompts. If the branch contains only a single commit, the commit message will be used (default: `false`) - -### `but pr template` +# but-pull.mdx -Configure the template to use for PR descriptions. This will list all available templates found in the repository and allow you to select one +This fetches the latest changes from the remote and rebases all applied branches +on top of the updated target branch. -**Usage:** `but pr template [TEMPLATE_PATH]` +You should run this regularly to keep your branches up to date with the latest +changes from the main development line. -**Arguments:** +You can run `but pull --check` first to see if your branches can be cleanly +merged into the target branch before running the update. -* `` — Path to the PR template file within the repository +**Usage:** `but pull [OPTIONS]` +## Options +* `-c`, `--check` — Only check the status without updating (equivalent to the old but base check) -# but-merge.mdx -If the target branch is local (`gb-local`), finds the local branch that the target -references (e.g., `gb-local/master` becomes `master`) and merges the specified -branch into that local branch. After merging, runs the equivalent of `but pull` -to update all branches. -## Examples +# but-pr.mdx -Merge a branch by its CLI ID: +If you are authenticated with a forge using but config forge auth, you can use the but pr commands to create pull requests (or merge requests) on the remote repository for your branches. -```text -but merge bu -``` +Running but pr without a subcommand defaults to but pr new, which will prompt you to select a branch to create a PR for. -Merge a branch by name: +**Usage:** `but pr ` -```text -but merge my-feature-branch -``` +## Subcommands -**Usage:** `but merge ` +### `but pr new` -## Arguments +Create a new pull request for a branch. If no branch is specified, you will be prompted to select one. If there is only one branch without a PR, you will be asked to confirm -* `` — Branch ID or name to merge (required) +**Usage:** `but pr new [BRANCH] [OPTIONS]` +**Arguments:** +* `` — The branch to create a PR for -# but-pull.mdx +**Options:** -This fetches the latest changes from the remote and rebases all applied branches -on top of the updated target branch. +* `-m`, `--message` `` — PR title and description. The first line is the title, the rest is the description +* `-F`, `--file` `` — Read PR title and description from file. The first line is the title, the rest is the description +* `-f`, `--with-force` — Force push even if it's not fast-forward (defaults to true) (default: `true`) +* `-s`, `--skip-force-push-protection` — Skip force push protection checks +* `-r`, `--run-hooks` — Run pre-push hooks (defaults to true) (default: `true`) +* `-t`, `--default` — Use the default content for the PR title and description, skipping any prompts. If the branch contains only a single commit, the commit message will be used (default: `false`) -You should run this regularly to keep your branches up to date with the latest -changes from the main development line. +### `but pr template` -You can run `but pull --check` first to see if your branches can be cleanly -merged into the target branch before running the update. +Configure the template to use for PR descriptions. This will list all available templates found in the repository and allow you to select one -**Usage:** `but pull [OPTIONS]` +**Usage:** `but pr template [TEMPLATE_PATH]` -## Options +**Arguments:** -* `-c`, `--check` — Only check the status without updating (equivalent to the old but base check) +* `` — Path to the PR template file within the repository @@ -4143,6 +3626,65 @@ You can also use `but reword ` to rename the branch. +# but-rub.mdx + +The `rub` command is a simple verb that helps you do a number of editing +operations by doing combinations of two things. + +For example, you can "rub" a file onto a branch to stage that file to +the branch. You can also "rub" a commit onto another commit to squash +them together. You can rub a commit onto a branch to move that commit. +You can rub a file from one commit to another. + +## Operations Matrix + +Each cell shows what happens when you rub SOURCE → TARGET: + +```text +SOURCE ↓ / TARGET → │ zz (unassigned) │ Commit │ Branch │ Stack +─────────────────────┼─────────────────┼────────────┼─────────────┼──────────── +File/Hunk │ Unstage │ Amend │ Stage │ Stage +Commit │ Undo │ Squash │ Move │ - +Branch (all changes) │ Unstage all │ Amend all │ Reassign │ Reassign +Stack (all changes) │ Unstage all │ - │ Reassign │ Reassign +Unassigned (zz) │ - │ Amend all │ Stage all │ Stage all +File-in-Commit │ Uncommit │ Move │ Uncommit to │ - +``` + +Legend: +- `zz` is a special target meaning "unassigned" (no branch) +- `-` means the operation is not supported +- "all changes" / "all" refers to all uncommitted changes from that source + +## Examples + +Squashing two commits into one (combining the commit messages): + +```text +but rub 3868155 abe3f53f +``` + +Amending a commit with the contents of a modified file: + +```text +but rub README.md abe3f53f +``` + +Moving a commit from one branch to another: + +```text +but rub 3868155 feature-branch +``` + +**Usage:** `but rub ` + +## Arguments + +* `` — The source entity to combine (required) +* `` — The target entity to combine with the source (required) + + + # but-resolve.mdx When a commit is in a conflicted state (marked with conflicts during rebase), @@ -4217,63 +3759,111 @@ where you want to ensure a git repository exists before setting up GitButler. -# but-rub.mdx +# but-skill.mdx -The `rub` command is a simple verb that helps you do a number of editing -operations by doing combinations of two things. +Skills give coding agents instructions for working with GitButler through the +`but` CLI. -For example, you can "rub" a file onto a branch to stage that file to -the branch. You can also "rub" a commit onto another commit to squash -them together. You can rub a commit onto a branch to move that commit. -You can rub a file from one commit to another. +Use `but skill install` to install the GitButler skill files into your +repository or globally. -## Operations Matrix +## Examples -Each cell shows what happens when you rub SOURCE → TARGET: +Install the skill in the current repository: ```text -SOURCE ↓ / TARGET → │ zz (unassigned) │ Commit │ Branch │ Stack -─────────────────────┼─────────────────┼────────────┼─────────────┼──────────── -File/Hunk │ Unstage │ Amend │ Stage │ Stage -Commit │ Undo │ Squash │ Move │ - -Branch (all changes) │ Unstage all │ Amend all │ Reassign │ Reassign -Stack (all changes) │ Unstage all │ - │ Reassign │ Reassign -Unassigned (zz) │ - │ Amend all │ Stage all │ Stage all -File-in-Commit │ Uncommit │ Move │ Uncommit to │ - +but skill install ``` -Legend: -- `zz` is a special target meaning "unassigned" (no branch) -- `-` means the operation is not supported -- "all changes" / "all" refers to all uncommitted changes from that source +Install the skill globally: + +```text +but skill install --global +``` + +**Usage:** `but skill ` + +## Subcommands + +### `but skill install` + +Install the GitButler CLI skill files for coding agents. + +By default, installs the skill into the current repository. The command prompts +you to select a skill folder format: Claude Code, OpenCode, Codex, GitHub +Copilot, Cursor, or Windsurf. + +Use `--path` to choose a custom location. Use `--global` to install the skill +in a global location instead of the current repository. ## Examples -Squashing two commits into one (combining the commit messages): +Install in current repository (prompts for format): ```text -but rub 3868155 abe3f53f +but skill install ``` -Amending a commit with the contents of a modified file: +Install globally (prompts for format): ```text -but rub README.md abe3f53f +but skill install --global ``` -Moving a commit from one branch to another: +Install to a custom path: ```text -but rub 3868155 feature-branch +but skill install --path .claude/skills/gitbutler ``` -**Usage:** `but rub ` +Auto-detect installation location (update existing installation): -## Arguments +```text +but skill install --detect +``` -* `` — The source entity to combine (required) -* `` — The target entity to combine with the source (required) +**Usage:** `but skill install [OPTIONS]` + +**Options:** + +* `-g`, `--global` — Install the skill globally instead of in the current repository +* `-p`, `--path` `` — Custom path where to install the skill (relative to repository root or absolute) +* `-d`, `--detect` — Automatically detect where to install by finding existing installation + +### `but skill check` + +Check if installed GitButler skills are up to date with the CLI version. +Scans for installed skill files and compares their version with the current +CLI version. By default, checks both local (repository) and global installations. + +## Examples + +Check all installed skills: + +```text +but skill check +``` + +Check and automatically update outdated skills: + +```text +but skill check --update +``` + +Check only global installations: + +```text +but skill check --global +``` + +**Usage:** `but skill check [OPTIONS]` + +**Options:** + +* `-g`, `--global` — Only check global installations (in home directory) +* `-l`, `--local` — Only check local installations (in current repository) +* `-u`, `--update` — Automatically update any outdated skills found # but-show.mdx @@ -4330,140 +3920,65 @@ Wrapper for `but rub `. ## Arguments -* `` — File or hunk ID to stage (required) -* `` — Branch ID to stage to (required) - - - -# but-squash.mdx - -Can be invoked in three ways: -1. Using commit identifiers: `but squash ` or `but squash ...` - - Squashes all commits except the last into the last commit -2. Using a commit range: `but squash ..` - - Squashes all commits in the range into the last commit in the range -3. Using a branch name: `but squash ` - - Squashes all commits in the branch into the bottom-most commit - -**Usage:** `but squash [COMMITS] [OPTIONS]` - -## Arguments - -* `` — Commit identifiers, a range (commit1..commit2), or a branch name - -## Options - -* `-d`, `--drop-message` — Drop source commit messages and keep only the target commit's message -* `-m`, `--message` `` — Provide a new commit message for the resulting commit -* `-i`, `--ai` `` — Generate commit message using AI with optional user summary or instructions. Use --ai by itself or --ai="your instructions" (equals sign required for value) - - - -# but-skill.mdx - -Skills provide enhanced AI capabilities for working with GitButler through -Claude Code and other AI assistants. - -Use `but skill install` to install the GitButler skill files into your -repository or globally. - -## Examples - -Install the skill in the current repository: - -```text -but skill install -``` - -Install the skill globally: - -```text -but skill install --global -``` - -**Usage:** `but skill ` - -## Subcommands - -### `but skill install` - -Install the GitButler CLI skill files for Coding agents - -By default, installs the skill into the current repository. The command -will prompt you to select a skill folder format (Claude Code, OpenCode, Codex, GitHub Copilot, -Cursor, Windsurf) unless you specify a custom path with --path. - -Use --global to install the skill in a global location instead of the -current repository. - -## Examples - -Install in current repository (prompts for format): - -```text -but skill install -``` - -Install globally (prompts for format): +* `` — File or hunk ID to stage (required) +* `` — Branch ID to stage to (required) -```text -but skill install --global -``` -Install to a custom path: -```text -but skill install --path .claude/skills/gitbutler -``` +# but-squash.mdx -Auto-detect installation location (update existing installation): +Can be invoked in three ways: +1. Using commit identifiers: `but squash ` or `but squash ...` + - Squashes all commits except the last into the last commit +2. Using a commit range: `but squash ..` + - Squashes all commits in the range into the last commit in the range +3. Using a branch name: `but squash ` + - Squashes all commits in the branch into the bottom-most commit -```text -but skill install --detect -``` +**Usage:** `but squash [COMMITS] [OPTIONS]` -**Usage:** `but skill install [OPTIONS]` +## Arguments -**Options:** +* `` — Commit identifiers, a range (commit1..commit2), or a branch name -* `-g`, `--global` — Install the skill globally instead of in the current repository -* `-p`, `--path` `` — Custom path where to install the skill (relative to repository root or absolute) -* `-d`, `--detect` — Automatically detect where to install by finding existing installation +## Options -### `but skill check` +* `-d`, `--drop-message` — Drop source commit messages and keep only the target commit's message +* `-m`, `--message` `` — Provide a new commit message for the resulting commit +* `-i`, `--ai` `` — Generate commit message using AI with optional user summary or instructions. Use --ai by itself or --ai="your instructions" (equals sign required for value) -Check if installed GitButler skills are up to date with the CLI version -Scans for installed skill files and compares their version with the current -CLI version. By default, checks both local (repository) and global installations. -## Examples +# but-status.mdx -Check all installed skills: +This shows unstaged files, files staged to stacks, all applied +branches (stacked or parallel), commits on each of those branches, +upstream commits that are unintegrated, commit status (pushed or local), +and base branch information. -```text -but skill check -``` +## Examples -Check and automatically update outdated skills: +Normal usage: ```text -but skill check --update +but status ``` -Check only global installations: +Shorthand with listing files modified ```text -but skill check --global +but status -f ``` -**Usage:** `but skill check [OPTIONS]` +**Usage:** `but status [OPTIONS]` -**Options:** +## Options -* `-g`, `--global` — Only check global installations (in home directory) -* `-l`, `--local` — Only check local installations (in current repository) -* `-u`, `--update` — Automatically update any outdated skills found +* `-f` — Determines whether the committed files should be shown as well (default: `false`) +* `-v`, `--verbose` — Show verbose output with commit author and timestamp (default: `false`) +* `-r`, `--refresh-prs` — Forces a sync of pull requests from the forge before showing status (default: `false`) +* `-u`, `--upstream` — Show detailed list of upstream commits that haven't been integrated yet (default: `false`) +* `--no-hint` — Disable hints about available commands at the end of output (default: `false`) @@ -4533,23 +4048,6 @@ but unapply bu -# but-undo.mdx - -This is a shorthand for restoring to the last oplog entry before the -current one. It allows you to quickly undo the most recent operation. - -**Usage:** `but undo` - - - -# but-unmark.mdx - -This will unmark anything that has been marked by the `but mark` command. - -**Usage:** `but unmark` - - - # but-uncommit.mdx Wrapper for `but rub zz`. @@ -4562,36 +4060,20 @@ Wrapper for `but rub zz`. -# but-status.mdx - -This shows unstaged files, files staged to stacks, all applied -branches (stacked or parallel), commits on each of those branches, -upstream commits that are unintegrated, commit status (pushed or local), -and base branch information. - -## Examples +# but-undo.mdx -Normal usage: +This is a shorthand for restoring to the last oplog entry before the +current one. It allows you to quickly undo the most recent operation. -```text -but status -``` +**Usage:** `but undo` -Shorthand with listing files modified -```text -but status -f -``` -**Usage:** `but status [OPTIONS]` +# but-unmark.mdx -## Options +This will unmark anything that has been marked by the `but mark` command. -* `-f` — Determines whether the committed files should be shown as well (default: `false`) -* `-v`, `--verbose` — Show verbose output with commit author and timestamp (default: `false`) -* `-r`, `--refresh-prs` — Forces a sync of pull requests from the forge before showing status (default: `false`) -* `-u`, `--upstream` — Show detailed list of upstream commits that haven't been integrated yet (default: `false`) -* `--no-hint` — Disable hints about available commands at the end of output (default: `false`) +**Usage:** `but unmark` @@ -4641,91 +4123,6 @@ Examples: but update install Auto-detect channel and install latest bu -# installation.mdx - -How to install and setup the GitButler CLI. - -## Installing the `but` CLI - -Ok, first thing is first, let's get our `but` CLI installed. Currently there are two ways to do this. - -### Via the Desktop Client - -If you have the desktop client installed, you can go into your global settings and click on the "Install CLI" button in the "general" section. - - - -### Curl install - -You can install the CLI by running the following command in your terminal: - -```bash -curl -fsSL https://gitbutler.com/install.sh | sh -``` - -## Setup - -If you go into any existing Git repository and run `but setup`, it will make some neccesary changes to your setup in order for GitButler to manage your data. - -If you run almost any `but` command in an existing Git repository in an interactive terminal, it will ask you if you want to set it up and then run the command you were trying to run. So basically just run `but` anywhere to get started. - -At any time after this, you can run `but teardown` to undo the GitButler changes and go back to being a boring old Git project. It will not remove GitButler metadata, so feel free to go back and forth if you need to. - - -# ai-stuff.mdx - -There are a couple of different ways that the GitButler CLI can use or interact with AI tools. Some are via `--ai` options to commands to use AI to help with tasks, others are ways that coding agents can more easily use the CLI to accomplish tasks. - -## Dash Dash AI - -There are a few commands that will take a `--ai` option to use a configured AI provider to generate something. - -### `but commit --ai` - -Probably the most commonly used would be `but commit --ai`, which will take a look at the changes in the files you're committing and generate an example commit message for you. If you're not feeling like writing anything more than "did some stuff", this could be a nice option for you. - -This will automatically commit the work specified with the generated message, but you can also easily edit it with `but reword ` if you wish. - -### `but squash --ai` - -If you squash two commits together, by default it will simply concatenate the commit messages together, which is rarely what you probably want. You can easily edit the message afterwards, but if you want to let AI try to combine the messages for you, you can give `but squash --ai` a try. - - - -We're working on integrating AI features into many more of our commands, so keep an eye out. - - - -## Skills - -If you're using an AI coding agent that can read skills, you can have GitButler automatically install a GitButler specific skill for various agents with `but skill install`. - -```git -❯ but skill install - -Select a skill folder format: - -? Which format would you like to use?: -> Claude Code - Claude Code CLI skill format (./.claude/skills/gitbutler) - OpenCode - OpenCode AI skill format (./.opencode/skills/gitbutler) - Codex - Codex skill format (./.codex/skills/gitbutler) - GitHub Copilot - GitHub Copilot local (repo) skill format (./.github/skills/gitbutler) - GitHub Copilot - GitHub Copilot global skill format (./.copilot/skills/gitbutler) -``` - -We keep these templates up to date, so if you update GitButler, you may want to update the skills too. - -## Hooks and MCP - -You can also install explicit hooks or an MCP server if you prefer. You can read more about those options [over here](/features/ai-integration/ai-overview) - - # commands-overview.mdx ## Command Reference @@ -4778,178 +4175,103 @@ You can also install explicit hooks or an MCP server if you prefer. You can read - [undo](./but-undo): Undo the last operation by reverting to the previous snapshot -# conclusion.mdx - -Ok, that's a short guide to GitButler's command line interface. - -Join us in [Discord](https://discord.com/invite/MmFkmaJ42D) if you have any other questions or suggestions for how we can improve the tool. - -Thanks! - - -# configuration.mdx - -We've already covered `but config` a bit in dealing with forges and target branches. - -You can also use it for some basic user configuration, such as setting your name and email address for commits and your default editor. - -```cli [configuration-but-config-1, 286px] -but config user -``` - -## Aliases - -GitButler also has a built in aliasing system in case you want to provide some shorthands. - -```cli [configuration-but-alias-1, 286px] -but alias -``` - -To add a new alias, you can run `but alias add `, which you can also provide a `-g` or `--global` if you want it to be a global alias. This will put this data in your local or global Git config file. - -You will notice that there is a `default` alias, which is what runs when you just run `but` with no arguments. If you overwrite the `default` alias, you can set up something other than `status` to run by default. - - -# conflict-resolution.mdx - -In this world nothing can be said to be certain, except death, taxes and merge conflicts. - -There are several different ways that you can run into merge conflicts when using Git (and thus, GitButler, or any other branching version control system). - -Perhaps there are changes that have been merged upstream that modified the same files as you did in your branch. Or maybe you uncommitted something that commits above it depended on. - -## First Class Conflicts in GitButler - -First, it's important to understand how GitButler deals with conflicts. While Git generally has to check out conflicts in your working directory and make you resolve them before you can commit, GitButler can partially apply a conflicting change and store the commit marked as "conflicted". - -This means that: +# installation.mdx -- Rebases _always_ succeed, just sometimes it results with commits in a conflicted state. -- You can deal with conflicts in any order and at any time. +How to install and setup the GitButler CLI. -So, let's take a look at what this looks like and how we can deal with conflicted commits when they arise. +## Installing the `but` CLI -{/* restore [e53a4a85d83d] */} -{/* run git push -f origin 96ccca9:main */} +Ok, first thing is first, let's get our `but` CLI installed. Currently there are two ways to do this. -```cli [conflict-resolution-but-status-1, 396px] -but status -``` +### Via the Desktop Client -Let's say that this is our status and we've decided to pull in from upstream. The changes that have been merged in by someone else upstream conflict with ours. When we run `but pull`, it will result in conflicts in our branch (but it will succeed). +If you have the desktop client installed, you can go into your global settings and click on the "Install CLI" button in the "general" section. -```cli [conflict-resolution-but-pull-1, 286px] -but pull -``` + -Ok, the `pull` tells us that we have conflicts and it also gives us a cheat sheet for what to do to resolve them, which is essentially "run `but resolve`". +### Curl install -So first let's see what our conflicted branch looks like with `but status`. +You can install the CLI by running the following command in your terminal: -```cli [conflict-resolution-but-status-2, 330px] -but status +```bash +curl -fsSL https://gitbutler.com/install.sh | sh ``` -Notice how we have _two_ commits that are conflicted, but one that is not. You could have any number of commits marked as conflicted in a branch, and you'll need to resolve each of them one by one. - -If we were to dig into the details here, a few things have actually happened. - -First of all, we have applied the upstream changes, so if we were to look at the files that conflict, we will see the upstream version rather than what we had done. - -Second, the commits that are not in a conflicted state are still applied - those changes are still in your working directory. In fact, even the conflicted commit's changes will be applied in the areas where they don't conflict. +## Setup -You could potentially have several conflicted commits in your branch. When you resolve one, everything above it is rebased and may introduce new conflicts or may resolve other conflicts, depending on the resolution. +If you go into any existing Git repository and run `but setup`, it will make some neccesary changes to your setup in order for GitButler to manage your data. -However, for now, let's look at a simple resolution flow. All you really need is one command: `but resolve`. +If you run almost any `but` command in an existing Git repository in an interactive terminal, it will ask you if you want to set it up and then run the command you were trying to run. So basically just run `but` anywhere to get started. -If you run `but resolve`, it will look through all your applied branches for any conflicted commits. If it finds any, it will list them out and ask you which you want to start with and default to the lowest one on the first branch. +At any time after this, you can run `but teardown` to undo the GitButler changes and go back to being a boring old Git project. It will not remove GitButler metadata, so feel free to go back and forth if you need to. -```git -❯ but resolve -Found conflicted commits: -Branch: update-homepage - ● 42165fe branding change: readme - ● 404b604 hero update - new branding +# ai-stuff.mdx -Would you like to start resolving these conflicts? -Enter commit ID to resolve [default: 42165fe]: -``` +Use `--ai` when you want the CLI to generate text for a single command. Use +`but skill install` when you want a coding agent to use GitButler's +version-control workflow. -If you hit enter, it will check out the conflict markers in that commit into your working directory. +## `--ai` options -```git -❯ but resolve -You are currently in conflict resolution mode. - - resolve all conflicts - - finalize with but resolve finish - - OR cancel with but resolve cancel +Supported commands can take `--ai` to generate text from your current changes. -Conflicted files remaining: - ✗ README.md -Checking out conflicted commit 42165fe -``` +### `but commit --ai` -So now you're in a special mode called "Edit Mode" in GitButler, where we've directly checked out a commit to work on. If you run any other commands, we'll warn you that you're currently in this mode. +Use `but commit --ai` to generate a commit message from the changes you are +committing. -For the conflicts, we put in zdiff3 style headers, so you can see your side, their side and also the ancestor. For example, if we look at the conflicted README.md file +This commits the selected work with the generated message. You can edit the +message afterward with `but reword `. -```git -❯ head README.md -<<<<<< ours -# The Why Experience -|||||| ancestor -# Twitter Clone -====== -# X Clone ->>>>>> theirs -``` +### `but squash --ai` -So you can see that we started with "Twitter Clone" and upstream changed it to "X Clone" and locally I changed the same line to "The Why Experience". Now I can resolve these three versions into a single line. +Use `but squash --ai` to generate a combined commit message when squashing +commits. -If I do that and then again run `but status`, you can see that GitButler notices that the conflicts in the README file has been resolved. + -```git -❯ but st -Initiated a background sync... -You are currently in conflict resolution mode. - - resolve all conflicts - - finalize with but resolve finish - - OR cancel with but resolve cancel +More commands will gain `--ai` support over time. -No conflicted files remaining! -Files resolved: - ✓ README.md -``` + -If you had other conflicted files, it would give you a list of what was still unresolved so you could work your way through the list. +## `but skill install` -However, now that we've resolved everything, we can either run `but resolve finish` or just `but resolve` and it will move us to the next step. Technically you can just keep running `but resolve` and it will figure out what the next thing to do is. +If your coding agent can read skills, install the GitButler skill with +`but skill install`. ```git -❯ but resolve -You are currently in conflict resolution mode. - - resolve all conflicts - - finalize with but resolve finish - - OR cancel with but resolve cancel +❯ but skill install -No conflicted files remaining! -Files resolved: - ✓ README.md +Select a skill folder format: -All conflicts have been resolved! -Finalize the resolution now? [Y/n]: y +? Which format would you like to use?: +> Claude Code - Claude Code CLI skill format (./.claude/skills/gitbutler) + OpenCode - OpenCode AI skill format (./.opencode/skills/gitbutler) + Codex - Codex skill format (./.codex/skills/gitbutler) + GitHub Copilot - GitHub Copilot local (repo) skill format (./.github/skills/gitbutler) + GitHub Copilot - GitHub Copilot global skill format (./.copilot/skills/gitbutler) +``` -Initiated a background sync... -✓ Conflict resolution finalized successfully! -The commit has been updated with your resolved changes. +We keep these templates up to date, so if you update GitButler, you may want to +update the skill too. -⚠ Warning: New conflicts were introduced during the rebase: +## Agent workflow docs - ● 4f671a1 hero update - new branding +`but skill install` is only the install step. For the full workflow: -Run but status to see all conflicted commits, or but resolve to resolve them. -``` +- Start with [AI agents overview](/ai-agents/overview). +- Install and configure the skill with + [Getting started with AI agents](/ai-agents/getting-started). +- Use [Useful requests](/ai-agents/useful-requests) for prompt examples. +- Use [Tuning agent behavior](/ai-agents/tuning-agent-behavior) for standing + instructions. # branching-and-commiting.mdx @@ -5182,60 +4504,234 @@ Now if we look at our status we can see a commit on our branch instead of the as but st ``` -Now let's commit all the rest of the changes (assigned and unassigned) to our other branch: +Now let's commit all the rest of the changes (assigned and unassigned) to our other branch: + +```cli [branching-and-commiting-but-commit-5, 88px] +but commit -m 'bookmarks stuff' ch +``` + +```cli [branching-and-commiting-but-status-12, 374px] +but status +``` + +### Committing Specific Files or Hunks + +Instead of staging files first and then committing with `-o`, you can also directly specify which files or hunks to include in a commit using the `-p` or `--changes` option. This lets you commit only specific changes without having to assign them to a branch first. + +For example, if you have multiple unassigned files and only want to commit some of them: + +```bash +but commit -p h0,i0 -m "only these two files" user-bookmarks +``` + +You can specify files in several ways: + +- **By CLI ID**: Use the short identifier shown in `but status` (e.g., `h0`, `i0`) +- **Space-separated**: `--changes h0 i0 k0` +- **Comma-separated**: `-p h0,i0,k0` +- **By path**: `-p app/models/bookmark.rb` + +This also works with hunk IDs. When a file has multiple hunks (shown in `but status -f` or `but diff`), you can commit individual hunks rather than the entire file. This is useful when you have changes in the same file that belong to different logical commits. + + + +If you don't specify `-p`, all uncommitted changes (or changes staged to the target branch) are committed. Use `-p` when you need fine-grained control over what goes into a commit. + + + +### Assigning Ranges + +If you happen to have a large number of changes, you can also use ranges or lists for rubbing assignment. So for example, if we go back to this status: + +{/* restore [6fdd8fb1d547] */} +{/* run but rub l0 zz */} + +```cli [branching-and-commiting-but-status-13, 484px] +but status +``` + +Then you can assign the everything in `app/` to a branch with: + +```cli [branching-and-commiting-but-stage-3, 154px] +but stage h0-j0 user-bookmarks +``` + +```cli [branching-and-commiting-but-status-14, 528px] +but status +``` + + +# conclusion.mdx + +Ok, that's a short guide to GitButler's command line interface. + +Join us in [Discord](https://discord.com/invite/MmFkmaJ42D) if you have any other questions or suggestions for how we can improve the tool. + +Thanks! + + +# configuration.mdx + +We've already covered `but config` a bit in dealing with forges and target branches. + +You can also use it for some basic user configuration, such as setting your name and email address for commits and your default editor. + +```cli [configuration-but-config-1, 286px] +but config user +``` + +## Aliases + +GitButler also has a built in aliasing system in case you want to provide some shorthands. + +```cli [configuration-but-alias-1, 286px] +but alias +``` + +To add a new alias, you can run `but alias add `, which you can also provide a `-g` or `--global` if you want it to be a global alias. This will put this data in your local or global Git config file. + +You will notice that there is a `default` alias, which is what runs when you just run `but` with no arguments. If you overwrite the `default` alias, you can set up something other than `status` to run by default. + + +# conflict-resolution.mdx + +In this world nothing can be said to be certain, except death, taxes and merge conflicts. + +There are several different ways that you can run into merge conflicts when using Git (and thus, GitButler, or any other branching version control system). + +Perhaps there are changes that have been merged upstream that modified the same files as you did in your branch. Or maybe you uncommitted something that commits above it depended on. + +## First Class Conflicts in GitButler + +First, it's important to understand how GitButler deals with conflicts. While Git generally has to check out conflicts in your working directory and make you resolve them before you can commit, GitButler can partially apply a conflicting change and store the commit marked as "conflicted". + +This means that: + +- Rebases _always_ succeed, just sometimes it results with commits in a conflicted state. +- You can deal with conflicts in any order and at any time. + +So, let's take a look at what this looks like and how we can deal with conflicted commits when they arise. + +{/* restore [e53a4a85d83d] */} +{/* run git push -f origin 96ccca9:main */} + +```cli [conflict-resolution-but-status-1, 396px] +but status +``` + +Let's say that this is our status and we've decided to pull in from upstream. The changes that have been merged in by someone else upstream conflict with ours. When we run `but pull`, it will result in conflicts in our branch (but it will succeed). + +```cli [conflict-resolution-but-pull-1, 286px] +but pull +``` + +Ok, the `pull` tells us that we have conflicts and it also gives us a cheat sheet for what to do to resolve them, which is essentially "run `but resolve`". + +So first let's see what our conflicted branch looks like with `but status`. + +```cli [conflict-resolution-but-status-2, 330px] +but status +``` + +Notice how we have _two_ commits that are conflicted, but one that is not. You could have any number of commits marked as conflicted in a branch, and you'll need to resolve each of them one by one. + +If we were to dig into the details here, a few things have actually happened. + +First of all, we have applied the upstream changes, so if we were to look at the files that conflict, we will see the upstream version rather than what we had done. + +Second, the commits that are not in a conflicted state are still applied - those changes are still in your working directory. In fact, even the conflicted commit's changes will be applied in the areas where they don't conflict. + +You could potentially have several conflicted commits in your branch. When you resolve one, everything above it is rebased and may introduce new conflicts or may resolve other conflicts, depending on the resolution. + +However, for now, let's look at a simple resolution flow. All you really need is one command: `but resolve`. + +If you run `but resolve`, it will look through all your applied branches for any conflicted commits. If it finds any, it will list them out and ask you which you want to start with and default to the lowest one on the first branch. + +```git +❯ but resolve +Found conflicted commits: + +Branch: update-homepage + ● 42165fe branding change: readme + ● 404b604 hero update - new branding + +Would you like to start resolving these conflicts? +Enter commit ID to resolve [default: 42165fe]: +``` + +If you hit enter, it will check out the conflict markers in that commit into your working directory. -```cli [branching-and-commiting-but-commit-5, 88px] -but commit -m 'bookmarks stuff' ch -``` +```git +❯ but resolve +You are currently in conflict resolution mode. + - resolve all conflicts + - finalize with but resolve finish + - OR cancel with but resolve cancel -```cli [branching-and-commiting-but-status-12, 374px] -but status +Conflicted files remaining: + ✗ README.md +Checking out conflicted commit 42165fe ``` -### Committing Specific Files or Hunks - -Instead of staging files first and then committing with `-o`, you can also directly specify which files or hunks to include in a commit using the `-p` or `--changes` option. This lets you commit only specific changes without having to assign them to a branch first. +So now you're in a special mode called "Edit Mode" in GitButler, where we've directly checked out a commit to work on. If you run any other commands, we'll warn you that you're currently in this mode. -For example, if you have multiple unassigned files and only want to commit some of them: +For the conflicts, we put in zdiff3 style headers, so you can see your side, their side and also the ancestor. For example, if we look at the conflicted README.md file -```bash -but commit -p h0,i0 -m "only these two files" user-bookmarks +```git +❯ head README.md +<<<<<< ours +# The Why Experience +|||||| ancestor +# Twitter Clone +====== +# X Clone +>>>>>> theirs ``` -You can specify files in several ways: +So you can see that we started with "Twitter Clone" and upstream changed it to "X Clone" and locally I changed the same line to "The Why Experience". Now I can resolve these three versions into a single line. -- **By CLI ID**: Use the short identifier shown in `but status` (e.g., `h0`, `i0`) -- **Space-separated**: `--changes h0 i0 k0` -- **Comma-separated**: `-p h0,i0,k0` -- **By path**: `-p app/models/bookmark.rb` +If I do that and then again run `but status`, you can see that GitButler notices that the conflicts in the README file has been resolved. -This also works with hunk IDs. When a file has multiple hunks (shown in `but status -f` or `but diff`), you can commit individual hunks rather than the entire file. This is useful when you have changes in the same file that belong to different logical commits. +```git +❯ but st +Initiated a background sync... +You are currently in conflict resolution mode. + - resolve all conflicts + - finalize with but resolve finish + - OR cancel with but resolve cancel - +No conflicted files remaining! +Files resolved: + ✓ README.md +``` -If you don't specify `-p`, all uncommitted changes (or changes staged to the target branch) are committed. Use `-p` when you need fine-grained control over what goes into a commit. +If you had other conflicted files, it would give you a list of what was still unresolved so you could work your way through the list. - +However, now that we've resolved everything, we can either run `but resolve finish` or just `but resolve` and it will move us to the next step. Technically you can just keep running `but resolve` and it will figure out what the next thing to do is. -### Assigning Ranges +```git +❯ but resolve +You are currently in conflict resolution mode. + - resolve all conflicts + - finalize with but resolve finish + - OR cancel with but resolve cancel -If you happen to have a large number of changes, you can also use ranges or lists for rubbing assignment. So for example, if we go back to this status: +No conflicted files remaining! +Files resolved: + ✓ README.md -{/* restore [6fdd8fb1d547] */} -{/* run but rub l0 zz */} +All conflicts have been resolved! +Finalize the resolution now? [Y/n]: y -```cli [branching-and-commiting-but-status-13, 484px] -but status -``` +Initiated a background sync... +✓ Conflict resolution finalized successfully! +The commit has been updated with your resolved changes. -Then you can assign the everything in `app/` to a branch with: +⚠ Warning: New conflicts were introduced during the rebase: -```cli [branching-and-commiting-but-stage-3, 154px] -but stage h0-j0 user-bookmarks -``` + ● 4f671a1 hero update - new branding -```cli [branching-and-commiting-but-status-14, 528px] -but status +Run but status to see all conflicted commits, or but resolve to resolve them. ``` @@ -5519,25 +5015,6 @@ but show a42580b96ed7b432 As long as we're talking about branches, let's show how to get rid of them. If you've merged one, it will by default not be shown anymore with `but branch` anyhow, but if you have one with some work on it that you want to abandon, you can also easily delete it with `but branch delete` (or `-d`). -# scripting.mdx - -### JSON Errwhere - -All of the commands are designed to be very user friendly when we have an interactive terminal, but you can also very easily script everything by passing the `--json` or `-j` option to anything. For example, here is using `but show` on a commit. - -```cli [scripting-but-show-1, 308px] -but show 2672465 -``` - -Now with the `--json` option: - -```cli [scripting-but-show-2, 682px] -but show --json 2672465 | jq -``` - -You can do this with anything - committing, status, diffing, etc. Just throw a `-j` in there and you get parseable data (or, data your agent can very easily work with). - - # operations-log.mdx GitButler maintains a detailed log of all operations, making it easy to track what happened and undo changes when needed. @@ -5585,25 +5062,6 @@ but oplog snapshot Now you can copy that SHA and restore to that exact point at any time in the future. -# tutorial-overview.mdx - -Using the GitButler CLI is meant to make a specific common workflow very simple, which is roughly: - -- Create a branch -- Do work on that branch -- Commit to that branch -- Optionally, create another branch if you find unrelated work you need to do -- Work on and commit to that branch -- Submit a branch for review -- Create a stacked branch if needed to continue on dependent work -- Update your base if work has been integrated to remove merged work -- Rinse and repeat - -Additionally, GitButler is very good at editing commits (amending fixup work, squashing, rewording messages, etc), it keeps a simple log of what you've done in case you need to go back in time, it makes collaborating on a branch with others easy, it has great GitHub/Lab integration and more. - -Let's walk through some of the things it can do and what a typical day using the GitButler CLI might look like. - - # rubbing.mdx As we saw in the [Branching and Committing](branching-and-commiting) section, the `but stage` command can be used to assign changes to branch lanes. @@ -5741,59 +5199,199 @@ As you might imagine, you can also simultaneously move and squash by rubbing a c ## Moving Files between Commits -You can also move specific file changes from one commit to another. +You can also move specific file changes from one commit to another. + +{/* restore [6ccc38e33e0e] */} + +To do that, you need identifiers for the files and hunks in an existing commit, which you can get via a `but status -f`, or `but status --files` that tells status to also list commit file IDs. + +```cli [rubbing-but-status-10, 638px] +but status -f +``` + +So now we can move the changes from one commit to another by rubbing pretty easily. Let’s take the `app/controllers/bookmarks_controller.rb` change and move it down to the "second commit" commit on the other branch: + +```cli [rubbing-but-rub-6, 88px] +but rub 08:3 2e +``` + +Now the change is in the "second commit" on the other branch: + +```cli [rubbing-but-status-11, 638px] +but status -f +``` + +Also notice that the SHAs of both commits were changed, as they both needed to have content modified. + +## Splitting Commits + +Ok, so now we can be pretty specifc about moving changes around to all these different states. The last thing we’ll cover here is splitting commits, which requires a new command that creates a new empty commit called `but commit empty`. + +The general strategy here is that to split a commit, you would make a new empty commit above or below it, then rub changes from the one commit into the empty commit until it's how you want it to look, then you're done. + +Let’s say we have a branch with a single commit on it and want to split it into two commits. + +{/* restore [64df45a76e99] */} + +```cli [rubbing-but-status-12, 308px] +but status +``` + +Now we want to split the "add bookmark model and associations" into two separate commits. The way we do this is to insert a blank commit in between `06` and `f5` and then rub changes into it (then probably edit the commit message). + +We can insert a blank commit by running `but commit empty --after 6a` which inserts a blank commit above the specified commit. + +```cli [rubbing-but-commit-1, 88px] +but commit empty --after 6a +``` + +Now we have a blank commit: + +```cli [rubbing-but-status-13, 462px] +but status -f +``` + +Now we can use the previous method of moving file changes from other commits into it, then edit the commit message with `but reword 54` (for more on the `reword` command, see [Editing Commits](editing-commits), coming up next). + + +# scripting.mdx + +### JSON Errwhere + +All of the commands are designed to be very user friendly when we have an interactive terminal, but you can also very easily script everything by passing the `--json` or `-j` option to anything. For example, here is using `but show` on a commit. + +```cli [scripting-but-show-1, 308px] +but show 2672465 +``` + +Now with the `--json` option: + +```cli [scripting-but-show-2, 682px] +but show --json 2672465 | jq +``` + +You can do this with anything - committing, status, diffing, etc. Just throw a `-j` in there and you get parseable data (or, data your agent can very easily work with). + + +# tutorial-overview.mdx + +Using the GitButler CLI is meant to make a specific common workflow very simple, which is roughly: + +- Create a branch +- Do work on that branch +- Commit to that branch +- Optionally, create another branch if you find unrelated work you need to do +- Work on and commit to that branch +- Submit a branch for review +- Create a stacked branch if needed to continue on dependent work +- Update your base if work has been integrated to remove merged work +- Rinse and repeat + +Additionally, GitButler is very good at editing commits (amending fixup work, squashing, rewording messages, etc), it keeps a simple log of what you've done in case you need to go back in time, it makes collaborating on a branch with others easy, it has great GitHub/Lab integration and more. + +Let's walk through some of the things it can do and what a typical day using the GitButler CLI might look like. + + +# updating-the-base.mdx + +The target branch is the foundation that your feature branches build upon. Keeping it updated and managing it properly is crucial for a smooth workflow. + +## Understanding the Target Branch + +The target branch is typically your main production branch that acts as the basis for all your local branches. + +In practice, this is generally not actually a local branch, it's usually the branch on whatever server you're using to collaborate and merge changes into, so generally it's something like `origin/main` or `origin/master`. + +When GitButler is first initialized in a project, you are asked to choose a branch to target, as everything in your working directory that doesn't exactly match the tip of this branch is technically a fork of what is considered production. Whatever that target branch looks like when you choose it is set as your 'base'. + +You can always check your target branch setting with `but config`: + +```cli [updating-the-base-but-config-1, 572px] +but config +``` + +Or get more information with `but config target`: + +```cli [updating-the-base-but-config-2, 308px] +but config target +``` + +When you start working, everything that is different from that base goes into a branch based off of it. + + + +## Understanding Upstream + +When you first set your target branch (ie, `origin/main`), we record the state of the branch at that time. + +However, if someone else merges work into that branch while you're working, the target branch moves forward, but the work you're doing is still based off of where it was. We call this 'upstream' work, and the commit that the target _was_ pointing at and your branches were based off of is your "base". -{/* restore [6ccc38e33e0e] */} + -To do that, you need identifiers for the files and hunks in an existing commit, which you can get via a `but status -f`, or `but status --files` that tells status to also list commit file IDs. +The problem is that now the stuff we're working on is out of date. It may conflict with what is upstream, it may need the work that is upstream, etc. So how do we get our branch up to date? -```cli [rubbing-but-status-10, 638px] -but status -f -``` +## Viewing Upstream -So now we can move the changes from one commit to another by rubbing pretty easily. Let’s take the `app/controllers/bookmarks_controller.rb` change and move it down to the "second commit" commit on the other branch: +When you run `but status`, we will by default show you a summary of upstream work if there is any. You can see a more detailed list of what is upstream by `but status --upstream` (or `-u`). -```cli [rubbing-but-rub-6, 88px] -but rub 08:3 2e -``` +{/* restore [cc9d20b8099c] */} +{/* run git push -f origin 32a2175758f7f649ed7a030a17fd21213a5e400f:refs/heads/main */} -Now the change is in the "second commit" on the other branch: +Let's take a look at what this looks like. Let's say that our project is at this state: -```cli [rubbing-but-status-11, 638px] -but status -f +```cli [updating-the-base-but-status-1, 396px] +but status -u ``` -Also notice that the SHAs of both commits were changed, as they both needed to have content modified. +We can see that there are two commits upstream (ie, merged into `origin/main` since we started our branch). -## Splitting Commits +Technically, there could be more reachable commits, but we only show the first parents, so merges of long branches show up as just the merge commits, to simplify things a bit. -Ok, so now we can be pretty specifc about moving changes around to all these different states. The last thing we’ll cover here is splitting commits, which requires a new command that creates a new empty commit called `but commit empty`. +Now let's say that we would like to pull in the upstream work and rebase our branches on top of the new upstream to update them. We can check what all would happen with `but pull --check`. -The general strategy here is that to split a commit, you would make a new empty commit above or below it, then rub changes from the one commit into the empty commit until it's how you want it to look, then you're done. +```cli [updating-the-base-but-pull-1, 308px] +but pull --check +``` -Let’s say we have a branch with a single commit on it and want to split it into two commits. +This will fetch the very latest work, then check that upstream work against your currently applied branches to see if anything has been integrated (and thus we can remove), anything conflicts with upstream work, or a merge/rebase should work cleanly. -{/* restore [64df45a76e99] */} +In this example, we can see that our `user-bookmarks` branch would be cleanly rebased if we did a pull, and that there are two things that have been merged since we started our branches. -```cli [rubbing-but-status-12, 308px] -but status -``` +## Updating the Base -Now we want to split the "add bookmark model and associations" into two separate commits. The way we do this is to insert a blank commit in between `06` and `f5` and then rub changes into it (then probably edit the commit message). +When you feel like you want to get your active branches up to date, you can run `but pull`. This will fetch the very latest work, then rebase your active branches on top of the new target commit to be your new base. -We can insert a blank commit by running `but commit empty --after 6a` which inserts a blank commit above the specified commit. + -```cli [rubbing-but-commit-1, 88px] -but commit empty --after 6a -``` +Let's run it in our example. -Now we have a blank commit: +```cli [updating-the-base-but-pull-2, 396px] +but pull +``` -```cli [rubbing-but-status-13, 462px] -but status -f +```cli [updating-the-base-but-status-2, 308px] +but status ``` -Now we can use the previous method of moving file changes from other commits into it, then edit the commit message with `but reword 54` (for more on the `reword` command, see [Editing Commits](editing-commits), coming up next). +OK, now we can see that our integrated branch was removed, our `gemfile-fixes` branch was successfully rebased and our `sc-branch-26` work is marked as conflicted. We'll see how to deal with that state in a minute. # getting-started.mdx @@ -5993,106 +5591,67 @@ separate worktrees. For more request examples, see [Useful requests](/ai-agents/useful-requests). -# updating-the-base.mdx - -The target branch is the foundation that your feature branches build upon. Keeping it updated and managing it properly is crucial for a smooth workflow. - -## Understanding the Target Branch - -The target branch is typically your main production branch that acts as the basis for all your local branches. +# review-agent-work.mdx -In practice, this is generally not actually a local branch, it's usually the branch on whatever server you're using to collaborate and merge changes into, so generally it's something like `origin/main` or `origin/master`. -When GitButler is first initialized in a project, you are asked to choose a branch to target, as everything in your working directory that doesn't exactly match the tip of this branch is technically a fork of what is considered production. Whatever that target branch looks like when you choose it is set as your 'base'. +When your coding agent uses GitButler, it can do the version-control work for +you: create branches, commit changes, move work between commits, and reshape +local history. The agent usually does this through the GitButler CLI. -You can always check your target branch setting with `but config`: +You may still want to preview what it created or manually adjust the branch and +commit history before anything is pushed or turned into a PR. GitButler gives +you three ways to inspect and adjust that state: the TUI, the CLI, and the +Desktop Client GUI. Use this page to pick the surface you want. The detailed +CLI and Desktop workflows live in their own docs. -```cli [updating-the-base-but-config-1, 572px] -but config -``` +## GitButler TUI -Or get more information with `but config target`: +Use the TUI when you want a terminal view of the workspace without switching to +the Desktop Client. It is useful for checking branch state, looking at what is +on a branch or still unassigned, and making small manual adjustments to branch +assignment, commit membership, or history shape. -```cli [updating-the-base-but-config-2, 308px] -but config target +```sh +but tui ``` -When you start working, everything that is different from that base goes into a branch based off of it. - - - -## Understanding Upstream - -When you first set your target branch (ie, `origin/main`), we record the state of the branch at that time. - -However, if someone else merges work into that branch while you're working, the target branch moves forward, but the work you're doing is still based off of where it was. We call this 'upstream' work, and the commit that the target _was_ pointing at and your branches were based off of is your "base". - -The problem is that now the stuff we're working on is out of date. It may conflict with what is upstream, it may need the work that is upstream, etc. So how do we get our branch up to date? - -## Viewing Upstream - -When you run `but status`, we will by default show you a summary of upstream work if there is any. You can see a more detailed list of what is upstream by `but status --upstream` (or `-u`). - -{/* restore [cc9d20b8099c] */} -{/* run git push -f origin 32a2175758f7f649ed7a030a17fd21213a5e400f:refs/heads/main */} - -Let's take a look at what this looks like. Let's say that our project is at this state: +## GitButler CLI -```cli [updating-the-base-but-status-1, 396px] -but status -u -``` +Use the CLI when you want exact output, scriptable commands, or the same view of +the repository state that the agent uses. -We can see that there are two commits upstream (ie, merged into `origin/main` since we started our branch). +For command details, start with the [CLI overview](/cli-overview). -Technically, there could be more reachable commits, but we only show the first parents, so merges of long branches show up as just the merge commits, to simplify things a bit. +## GitButler Desktop Client -Now let's say that we would like to pull in the upstream work and rebase our branches on top of the new upstream to update them. We can check what all would happen with `but pull --check`. +Use the Desktop Client when you want a visual overview of branches, commits, +assigned changes, unassigned changes, parallel work, and stacked work. It is +also the visual surface for moving changes between branches and adjusting +commit history. -```cli [updating-the-base-but-pull-1, 308px] -but pull --check +```sh +but gui ``` -This will fetch the very latest work, then check that upstream work against your currently applied branches to see if anything has been integrated (and thus we can remove), anything conflicts with upstream work, or a merge/rebase should work cleanly. - -In this example, we can see that our `user-bookmarks` branch would be cleanly rebased if we did a pull, and that there are two things that have been merged since we started our branches. - -## Updating the Base - -When you feel like you want to get your active branches up to date, you can run `but pull`. This will fetch the very latest work, then rebase your active branches on top of the new target commit to be your new base. - - - -Let's run it in our example. - -```cli [updating-the-base-but-pull-2, 396px] -but pull -``` +For details, see the [Desktop Overview](/overview), +[Branch lanes](/features/branch-management/branch-lanes), and +[Commits](/features/branch-management/commits). -```cli [updating-the-base-but-status-2, 308px] -but status -``` +## Operations history -OK, now we can see that our integrated branch was removed, our `gemfile-fixes` branch was successfully rebased and our `sc-branch-26` work is marked as conflicted. We'll see how to deal with that state in a minute. +GitButler records version-control operations so you can inspect or undo local +history edits. If a branch reorganization does not look right, inspect the +operation history before making more changes. See +[Timeline](/features/timeline), [`but oplog`](/commands/but-oplog), and +[`but undo`](/commands/but-undo). # tuning-agent-behavior.mdx @@ -6385,66 +5944,3 @@ the same files. Stack branches only when one branch depends on another. For the fuller multi-agent workflow, see [Parallel agents](/ai-agents/parallel-agents). - - -# review-agent-work.mdx - - -When your coding agent uses GitButler, it can do the version-control work for -you: create branches, commit changes, move work between commits, and reshape -local history. The agent usually does this through the GitButler CLI. - -You may still want to preview what it created or manually adjust the branch and -commit history before anything is pushed or turned into a PR. GitButler gives -you three ways to inspect and adjust that state: the TUI, the CLI, and the -Desktop Client GUI. Use this page to pick the surface you want. The detailed -CLI and Desktop workflows live in their own docs. - -## GitButler TUI - -Use the TUI when you want a terminal view of the workspace without switching to -the Desktop Client. It is useful for checking branch state, looking at what is -on a branch or still unassigned, and making small manual adjustments to branch -assignment, commit membership, or history shape. - -```sh -but tui -``` - - - -## GitButler CLI - -Use the CLI when you want exact output, scriptable commands, or the same view of -the repository state that the agent uses. - -For command details, start with the [CLI overview](/cli-overview). - -## GitButler Desktop Client - -Use the Desktop Client when you want a visual overview of branches, commits, -assigned changes, unassigned changes, parallel work, and stacked work. It is -also the visual surface for moving changes between branches and adjusting -commit history. - -```sh -but gui -``` - -For details, see the [Desktop Overview](/overview), -[Branch lanes](/features/branch-management/branch-lanes), and -[Commits](/features/branch-management/commits). - -## Operations history - -GitButler records version-control operations so you can inspect or undo local -history edits. If a branch reorganization does not look right, inspect the -operation history before making more changes. See -[Timeline](/features/timeline), [`but oplog`](/commands/but-oplog), and -[`but undo`](/commands/but-undo).