# Table of Contents - [Welcome | GitButler Docs](#welcome-gitbutler-docs) - [Getting Started | GitButler Docs](#getting-started-gitbutler-docs) - [Desktop Overview | GitButler Docs](#desktop-overview-gitbutler-docs) - [Why GitButler | GitButler Docs](#why-gitbutler-gitbutler-docs) - [Butler Flow | GitButler Docs](#butler-flow-gitbutler-docs) - [Inspect and adjust agent work | GitButler Docs](#inspect-and-adjust-agent-work-gitbutler-docs) - [Parallel agents | GitButler Docs](#parallel-agents-gitbutler-docs) - [Workspace Branch | GitButler Docs](#workspace-branch-gitbutler-docs) - [Releases | GitButler Docs](#releases-gitbutler-docs) - [Debugging | GitButler Docs](#debugging-gitbutler-docs) - [Getting started | GitButler Docs](#getting-started-gitbutler-docs) - [GitButler TUI | GitButler Docs](#gitbutler-tui-gitbutler-docs) - [Operations History | GitButler Docs](#operations-history-gitbutler-docs) - [Useful requests | GitButler Docs](#useful-requests-gitbutler-docs) - [Parallel Branches | GitButler Docs](#parallel-branches-gitbutler-docs) - [Overview | GitButler Docs](#overview-gitbutler-docs) - [Rebasing and Conflicts | GitButler Docs](#rebasing-and-conflicts-gitbutler-docs) - [Tuning agent behavior | GitButler Docs](#tuning-agent-behavior-gitbutler-docs) - [CLI Overview | GitButler Docs](#cli-overview-gitbutler-docs) - [Branching and committing | GitButler Docs](#branching-and-committing-gitbutler-docs) - [Branches Page | GitButler Docs](#branches-page-gitbutler-docs) - [Commit Editing | GitButler Docs](#commit-editing-gitbutler-docs) - [Create stacked branches and pull requests | GitButler Docs](#create-stacked-branches-and-pull-requests-gitbutler-docs) - [but oplog | GitButler Docs](#but-oplog-gitbutler-docs) - [but undo | GitButler Docs](#but-undo-gitbutler-docs) - [Installation and Setup | GitButler Docs](#installation-and-setup-gitbutler-docs) - [Supporters | GitButler Docs](#supporters-gitbutler-docs) - [Gerrit Mode | GitButler Docs](#gerrit-mode-gitbutler-docs) - [Contact Us | GitButler Docs](#contact-us-gitbutler-docs) - [GitButler CLI Cheat Sheet | GitButler Docs](#gitbutler-cli-cheat-sheet-gitbutler-docs) - [Custom Content Security Policy (CSP) | GitButler Docs](#custom-content-security-policy-csp-gitbutler-docs) - [Rules | GitButler Docs](#rules-gitbutler-docs) - [Connect GitButler to GitHub | GitButler Docs](#connect-gitbutler-to-github-gitbutler-docs) - [Push and fetch | GitButler Docs](#push-and-fetch-gitbutler-docs) - [Move branches between stacks | GitButler Docs](#move-branches-between-stacks-gitbutler-docs) - [Workflow Overview | GitButler Docs](#workflow-overview-gitbutler-docs) - [Configuration and Aliases | GitButler Docs](#configuration-and-aliases-gitbutler-docs) - [Signing Commits | GitButler Docs](#signing-commits-gitbutler-docs) - [Operations Log | GitButler Docs](#operations-log-gitbutler-docs) - [Recovering Stuff | GitButler Docs](#recovering-stuff-gitbutler-docs) - [Script with JSON output | GitButler Docs](#script-with-json-output-gitbutler-docs) - [Working with AI | GitButler Docs](#working-with-ai-gitbutler-docs) - [Edit commit messages and branch names | GitButler Docs](#edit-commit-messages-and-branch-names-gitbutler-docs) - [AI Assistance | GitButler Docs](#ai-assistance-gitbutler-docs) - [Upstream Integration | GitButler Docs](#upstream-integration-gitbutler-docs) - [Wrap Up | GitButler Docs](#wrap-up-gitbutler-docs) - [Initializing a Repository | GitButler Docs](#initializing-a-repository-gitbutler-docs) - [Conflict Resolution | GitButler Docs](#conflict-resolution-gitbutler-docs) - [Updating your Base | GitButler Docs](#updating-your-base-gitbutler-docs) - [Push branches and create reviews | GitButler Docs](#push-branches-and-create-reviews-gitbutler-docs) - [Edit commit history | GitButler Docs](#edit-commit-history-gitbutler-docs) - [Inspecting changes and branches | GitButler Docs](#inspecting-changes-and-branches-gitbutler-docs) - [but clean | GitButler Docs](#but-clean-gitbutler-docs) - [but apply | GitButler Docs](#but-apply-gitbutler-docs) - [but pull | GitButler Docs](#but-pull-gitbutler-docs) - [but redo | GitButler Docs](#but-redo-gitbutler-docs) - [but diff | GitButler Docs](#but-diff-gitbutler-docs) - [but push | GitButler Docs](#but-push-gitbutler-docs) - [but squash | GitButler Docs](#but-squash-gitbutler-docs) - [but absorb | GitButler Docs](#but-absorb-gitbutler-docs) - [but teardown | GitButler Docs](#but-teardown-gitbutler-docs) - [but discard | GitButler Docs](#but-discard-gitbutler-docs) - [but reword | GitButler Docs](#but-reword-gitbutler-docs) - [but status | GitButler Docs](#but-status-gitbutler-docs) - [but setup | GitButler Docs](#but-setup-gitbutler-docs) - [but unapply | GitButler Docs](#but-unapply-gitbutler-docs) - [but amend | GitButler Docs](#but-amend-gitbutler-docs) - [but worktree | GitButler Docs](#but-worktree-gitbutler-docs) - [but uncommit | GitButler Docs](#but-uncommit-gitbutler-docs) - [but show | GitButler Docs](#but-show-gitbutler-docs) - [but move | GitButler Docs](#but-move-gitbutler-docs) - [but commit | GitButler Docs](#but-commit-gitbutler-docs) - [but land | GitButler Docs](#but-land-gitbutler-docs) - [but branch | GitButler Docs](#but-branch-gitbutler-docs) - [but pr | GitButler Docs](#but-pr-gitbutler-docs) - [but skill | GitButler Docs](#but-skill-gitbutler-docs) - [but help cli-ids | GitButler Docs](#but-help-cli-ids-gitbutler-docs) - [Commands Overview | GitButler Docs](#commands-overview-gitbutler-docs) - [but agent | GitButler Docs](#but-agent-gitbutler-docs) - [but resolve | GitButler Docs](#but-resolve-gitbutler-docs) - [but pick | GitButler Docs](#but-pick-gitbutler-docs) --- # Welcome | GitButler Docs Welcome ======= Welcome to GitButler - a new Source Code Management system designed to manage branches, record work, and enhance your Git workflow. [Overview](https://docs.gitbutler.com/#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](https://docs.gitbutler.com/overview) and [a CLI](https://docs.gitbutler.com/cli-overview) that work together. ### [Desktop Client](https://docs.gitbutler.com/#desktop-client) ![An example of the GitButler client with multiple applied branches and assigned changes.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fvbranch-ex.png&w=3840&q=75) An example of the GitButler client with multiple applied branches and assigned changes. ### [Command Line Interface](https://docs.gitbutler.com/#command-line-interface) ![Our command line interface](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202026-02-02%2520at%252014.52.03%25402x.png&w=3840&q=75) Our 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](https://docs.gitbutler.com/#getting-started) --------------------------------------------------------------- Check out our [Getting Started](https://docs.gitbutler.com/guide) guide to get started with GitButler, or check out our helpful video overview: [Why We're Doing This](https://docs.gitbutler.com/#why-were-doing-this) ------------------------------------------------------------------------ Read about it over [Why GitButler](https://docs.gitbutler.com/why-gitbutler) Section. [What We Do](https://docs.gitbutler.com/#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](https://docs.gitbutler.com/features/branch-management/virtual-branches) * [First Class Conflicts](https://docs.gitbutler.com/features/branch-management/merging) * [Project History](https://docs.gitbutler.com/features/timeline) Last updated on 7/30/2026 [Next\ \ Getting Started](https://docs.gitbutler.com/guide) ### On this page [Overview](https://docs.gitbutler.com/#overview) [Desktop Client](https://docs.gitbutler.com/#desktop-client) [Command Line Interface](https://docs.gitbutler.com/#command-line-interface) [Getting Started](https://docs.gitbutler.com/#getting-started) [Why We're Doing This](https://docs.gitbutler.com/#why-were-doing-this) [What We Do](https://docs.gitbutler.com/#what-we-do) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/index.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22index%22) ![An example of the GitButler client with multiple applied branches and assigned changes.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fvbranch-ex.png&w=3840&q=75) ![Our command line interface](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202026-02-02%2520at%252014.52.03%25402x.png&w=3840&q=75) --- # Getting Started | GitButler Docs Getting Started =============== Complete step-by-step tutorial for getting started with GitButler, from importing repositories to managing multiple branches and commits. Here is a quick overview of how to get started with GitButler. In this guide, we will: * Get setup and start working with a local repository * Do work and commit on several branches simultaneously * Push your work to a remote repository and get it integrated * Reorder and edit your commits * Undo anything [Importing a Local Repository](https://docs.gitbutler.com/guide#importing-a-local-repository) ---------------------------------------------------------------------------------------------- After [downloading](https://gitbutler.com/downloads) and installing GitButler, you will be greeted with the welcome screen. From here you can import or clone a repository. ![Import screen](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fwelcome-screen.9bb7b742.png&w=3840&q=75) First thing you see when you launch GitButler Let's start by importing an existing Git project on your machine. If you click "Add local project" and then choose the directory of the existing Git initialized project, then we will start the import process. [Choosing a Target Branch](https://docs.gitbutler.com/guide#choosing-a-target-branch) -------------------------------------------------------------------------------------- ![Import screen](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fimport.9356ec51.png&w=3840&q=75) First step: choose your target branch The first step is to choose your "target" branch. GitButler focuses on a trunk based development model, so first you need to tell us what branch means "production" to you. Normally this is something like `origin/master` or `origin/main`. If you would like to use our AI features like commit message generation, you can also sign up for a GitButler account and log in. This is optional, but we'll do it here so we can show off these features. You can also connect GitButler to your GitHub account so we can automatically open Pull Requests for you (this is also optional). [Test Git authentication](https://docs.gitbutler.com/guide#test-git-authentication) ------------------------------------------------------------------------------------ GitButler uses your system Git executable and its existing authentication configuration. Open the Git section in your project settings and select **Test credentials** to make sure GitButler can push to the remote. If the test fails, configure authentication for Git in your terminal first, then run the test again. [Ready to Go](https://docs.gitbutler.com/guide#ready-to-go) ------------------------------------------------------------ Ok, now we're all setup and you should see our main working screen. If you had a branch with some work in progress, you should see it imported already. Otherwise, you will see a blank workspace with no branches applied. ![A workspace with no initial branches](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Finitial-space.png&w=3840&q=75) A workspace with no initial branches [Do Some Work](https://docs.gitbutler.com/guide#do-some-work) -------------------------------------------------------------- Now we can start working. GitButler will watch your working directory and immediately show any changes that you make. In the above case, we can see that there are some changes to the `README.md` file. Let's create a new branch and commit our changes to it. You can click the "Create Branch" button in the workspace, or the "Commit to new branch" button below the Unassigned changes. ![Creating a new branch.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-07-02%2520at%252010.44.12%25402x.png&w=3840&q=75) Creating a new branch. You can click on any file to see what the diff is. ![view-file.png](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fview-file.png&w=3840&q=75) view-file.png Now that you have a branch, you can simply hit the "Start a Commit" button on the branch you want to commit to, then either write your commit message, or hit "Generate Message" to let AI look at the diffs and write a message for you. ![Simple commit message dialog](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-07-02%2520at%252010.53.15%25402x.png&w=3840&q=75) Simple commit message dialog Once you've done that, you should see something like this: ![Now we can see our one commit on our branch](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fpost-commit.png&w=3840&q=75) Now we can see our one commit on our branch [Split secondary work into a new branch](https://docs.gitbutler.com/guide#split-secondary-work-into-a-new-branch) ------------------------------------------------------------------------------------------------------------------ Now let's say we decide to add a new feature and don't want it to depend on our README change. Instead of stashing the changes and doing that, or committing unrelated work into the branch I'm on, I can simply create a new parallel branch, drag my work over there and commit there. ![Now we have two branches, both applied](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Ftwo-branches.png&w=3840&q=75) Now we have two branches, both applied Now both branches are applied, but I can commit to them independently and push them to a remote repository at different times. [Integrate Your Work](https://docs.gitbutler.com/guide#integrate-your-work) ---------------------------------------------------------------------------- Since the README updating branch is ready to be merged, I can push that branch up, open a Pull Request on it and wait for it to be integrated, while I continue to work on and commit to my other feature branch. ![One branch is pushed and we can see that it has been integrated upstream.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fintegrated2.png&w=3840&q=75) One branch is pushed and we can see that it has been integrated upstream. Now we have a series of commits on our feature branch, which we've continued to work on while we're waiting for our README update to be integrated. GitButler sees that our target branch has new work and shows us the "Update" button, which we can click to rebase our feature branch on top of the new work and also remove the README branch automatically, since we can see that it has been integrated upstream. ![Updating from upstream will automatically remove integrated branches and rebase other branches on top of the new work.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fupdate-base.png&w=3840&q=75) Updating from upstream will automatically remove integrated branches and rebase other branches on top of the new work. [Reorder and Edit Your Commits](https://docs.gitbutler.com/guide#reorder-and-edit-your-commits) ------------------------------------------------------------------------------------------------ GitButler makes it very easy to edit, reorder, squash and split commits. If you hover over any commit, you will see a drag handle on the top right. You can drag the commit to reorder it, or drag it on top of another commit to squash them together. ![Drag one commit on top of another to squash, above or below to reorder, or to another branch to move it.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fmove-commit.png&w=3840&q=75) Drag one commit on top of another to squash, above or below to reorder, or to another branch to move it. To split a commit, you can insert an "empty" commit in between the two commits you want to split, then drag the changes from the commit you want to split into the empty commit. ![Add a new empty commit above or below an existing one](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fadd-empty-commit.png&w=3840&q=75) Add a new empty commit above or below an existing one Now you can drag the changes from the commit you want to split into the new empty commit. ![Drag files from one commit to another, in this case, amending the previously empty commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Famend-to-empty-commit.png&w=3840&q=75) Drag files from one commit to another, in this case, amending the previously empty commit Finally, you can edit the commit message of the previously empty commit to give it a meaningful message, and now you have split the original commit into two separate commits. ![add-commit-message.png](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fadd-commit-message.png&w=3840&q=75) add-commit-message.png You can also uncommit any commit without dependencies, or even individual files in a commit. ![Uncommit any commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Funcommit.png&w=3840&q=75) Uncommit any commit All of this makes it very easy to build up and maintain a nice, clean history that is easy to understand and work with. [Unapply a stack](https://docs.gitbutler.com/guide#unapply-a-stack) -------------------------------------------------------------------- If you decide you don't want to work on a branch anymore, you can simply unapply it. This will remove all the changes from that branch from your working directory, but keep the branch around in case you want to reapply it later. ![Unapply a branch to remove those changes from your working directory and save the work](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Funapply-stack.png&w=3840&q=75) Unapply a branch to remove those changes from your working directory and save the work [Undo Anything](https://docs.gitbutler.com/guide#undo-anything) ---------------------------------------------------------------- If at any time, you do something you didn't mean to do, you can always undo it. You can undo a commit, a commit edit, a squash, an upstream update, a branch application, anything. To do this, click the "Operations History" button in the sidebar, find the action you want to rewind to and hit the "Revert" button. ![Revert back to a previous point in time with the Operations History](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fophistory.png&w=3840&q=75) Revert back to a previous point in time with the Operations History Last updated on 7/30/2026 [Previous\ \ Welcome](https://docs.gitbutler.com/) [Next\ \ Why GitButler](https://docs.gitbutler.com/why-gitbutler) ### On this page [Importing a Local Repository](https://docs.gitbutler.com/guide#importing-a-local-repository) [Choosing a Target Branch](https://docs.gitbutler.com/guide#choosing-a-target-branch) [Test Git authentication](https://docs.gitbutler.com/guide#test-git-authentication) [Ready to Go](https://docs.gitbutler.com/guide#ready-to-go) [Do Some Work](https://docs.gitbutler.com/guide#do-some-work) [Split secondary work into a new branch](https://docs.gitbutler.com/guide#split-secondary-work-into-a-new-branch) [Integrate Your Work](https://docs.gitbutler.com/guide#integrate-your-work) [Reorder and Edit Your Commits](https://docs.gitbutler.com/guide#reorder-and-edit-your-commits) [Unapply a stack](https://docs.gitbutler.com/guide#unapply-a-stack) [Undo Anything](https://docs.gitbutler.com/guide#undo-anything) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/guide.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22guide%22) --- # Desktop Overview | GitButler Docs Desktop Overview ================ Learn how GitButler enables working on multiple branches simultaneously with parallel branches, target branches, and conflict resolution. GitButler lets you work on several branches at the same time, committing and stashing them independently and simultaneously. Here is a general overview of how this works and how you can use it. One of the main strengths of GitButler is its incredible versatility around branch management. You can decide to create multiple independent branches to work on from a single working directory simultaneously, or you can create dependent, stacked branches and merge them in a particular order. We refer to our independent branches as "virtual" branches and our dependent branches as "stacked" branches. This ability to do multiple dependant or independent branches at the same time is something that's not possible with vanilla Git. ![The main workspace, showing multiple dependent and independent branches](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fvbranches-overview.png&w=3840&q=75) The main workspace, showing multiple dependent and independent branches When using GitButler, we setup a special branch to handle the multiple branches in a way that Git can understand a bit better. This means if you use vanilla git branching commands like `git switch`, GitButler will pause and ask you to return to GitButler's method when you return. The reason is stock Git can only handle one branch at a time, it does not have tooling to use or understand multiple branches, so most commands having to do with the index or HEAD or branching (commit, branch, checkout, etc) may behave unexpectedly. Read [Parallel Branches](https://docs.gitbutler.com/features/branch-management/virtual-branches) for more detail on how GitButler represents several branches in one working directory. [Target Branch](https://docs.gitbutler.com/overview#target-branch) ------------------------------------------------------------------- With parallel branches, you are not working directly on a local `main` or `master` branch. Similar to GitHub, where you specify a default branch to use to merge your Pull Requests into by default, GitButler requires a "Target Branch". This is understood to be whatever your concept of "production" is. Typically what represents deployed, production code that cannot or should not be rolled back. Generally this would be something like `origin/master` or `origin/main`. Once a target branch is specified, GitButler treats it as the baseline for the workspace. New working-directory changes appear under **Unstaged**. Stage the files or hunks you want into a branch lane, then commit the branch's **Staged** changes. You can start editing before deciding which branch should own the work. In workspace mode there is no checked-out local `main` or `master`; your branches hold the work that will eventually be integrated into the target. [Parallel Branches](https://docs.gitbutler.com/overview#parallel-branches) --------------------------------------------------------------------------- You can easily work in a single branch at a time, but GitButler can handle several parallel branches at the same time. If you have 3 different changes in one file, you can drag each of the changes to a different virtual branch lane and commit and push them independently. Each virtual branch is kept in a vertical lane, similar to a kanban board, and every file and difference is similar to a card that you can drag between the lanes until they are committed there. Each time you commit on a virtual branch, GitButler calculates what that branch would have looked like if the changes you dragged onto it were the only things in your working directory and commits a file tree that represents that work. If you push that commit and inspect it on GitHub (or whatever upstream service you use to collaborate), it should look like that was the only change you made, even though you could potentially still have multiple branches applied in your working directory. [Applying and Unapplying Branches](https://docs.gitbutler.com/overview#applying-and-unapplying-branches) --------------------------------------------------------------------------------------------------------- Since there isn't just a single branch you can be on, you don't "switch" branches, which implies replacement. You simply "apply" branches, which takes whatever changes they represent and adds them to your working directory. If you don't want those changes in your working directory anymore, you can "unapply" them, which removes only those changes. ![Virtual Branch Apply / Unapply](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Funapply-stack.png&w=3840&q=75) Click 'unapply' for any branch to stash it and remove its changes from the working directory [Merging Upstream](https://docs.gitbutler.com/overview#merging-upstream) ------------------------------------------------------------------------- Eventually, you will have work merged into the branch you chose as your target branch, which will need to be reconciled with all your parallel branches to keep them up to date with where they will eventually need to merge to. ![Updating from upstream will automatically remove integrated branches and rebase other branches on top of the new work.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fupdate-base.png&w=3840&q=75) Updating from upstream will automatically remove integrated branches and rebase other branches on top of the new work. Upstream work will automatically be shown on the top of your window as "X upstream commits". When you click there, you will see the incoming work and you will be directed on how to update your active branches on top of it. For each parallel branch you have, we will show you if the incoming upstream work has conflicts with each branch. If there are conflicts, you can choose to stash the branch or go ahead and rebase with conflicts, which you can fix later. If a virtual branch is entirely integrated into upstream, it will be removed and deleted when those changes are integrated. So you can keep a virtual branch applied locally until it is integrated and it will go away automatically. [Conflicting Branches](https://docs.gitbutler.com/overview#conflicting-branches) --------------------------------------------------------------------------------- If you do rebase work with conflicts, the commit will be marked as being in a conflicted state and you can check it out and fix it whenever you wish. ![When your commits have conflicts](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fconflict-resolve.png&w=3840&q=75) When your commits have conflicts This is different from how you might have dealt with conflicts in Git before. If there is conflicting work in a commit, GitButler will ignore the parts that conflict and keep rebasing. In other words, rebases _always_ work. Then you can focus resolving each conflicted commit, one at a time. ![Resolving a conflict by individual commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fresolve-conflicts-mode.png&w=3840&q=75) Resolving a conflict by individual commit This will check out the conflicts into your working directory and you can let us know when you're done resolving it and GitButler will rebase everything above it. ![Conflicts resolved!](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fconflicts-resolved.png&w=3840&q=75) Conflicts resolved! [The End](https://docs.gitbutler.com/overview#the-end) ------------------------------------------------------- That is our general overview of how our branching model and workflow works. We've found that it's way easier and faster than constantly switching back and forth between branches, managing branches all the time, and all the other overhead that comes with branching in Git, while still easily creating pull requests and integrating features. Last updated on 7/30/2026 [Previous\ \ Why GitButler](https://docs.gitbutler.com/why-gitbutler) [Next\ \ Butler Flow](https://docs.gitbutler.com/butler-flow) ### On this page [Target Branch](https://docs.gitbutler.com/overview#target-branch) [Parallel Branches](https://docs.gitbutler.com/overview#parallel-branches) [Applying and Unapplying Branches](https://docs.gitbutler.com/overview#applying-and-unapplying-branches) [Merging Upstream](https://docs.gitbutler.com/overview#merging-upstream) [Conflicting Branches](https://docs.gitbutler.com/overview#conflicting-branches) [The End](https://docs.gitbutler.com/overview#the-end) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/overview.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22overview%22) --- # Why GitButler | GitButler Docs Why GitButler ============= The manifesto explaining why GitButler was created to reimagine source code management beyond traditional Git limitations. 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. ![](https://docs.gitbutler.com/img/markus-chill.svg) Last updated on 7/30/2026 [Previous\ \ Getting Started](https://docs.gitbutler.com/guide) [Next\ \ Desktop Overview](https://docs.gitbutler.com/overview) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/why-gitbutler.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22why-gitbutler%22) --- # Butler Flow | GitButler Docs Butler Flow =========== Discover Butler Flow, a lightweight branch-based development workflow that improves upon GitHub Flow with GitButler's parallel branches. Butler Flow is a lightweight, branch-based workflow enabled by GitButler's virtual branch functionality. For most modern software development teams that want to set up a culture of shipping, who push to production every day, who are constantly testing and deploying, one of the most popular and effective development workflows is [GitHub Flow](https://docs.github.com/en/get-started/quickstart/github-flow) . These are wise words, enterprising men quote 'em. Don't act surprised, you guys, [cuz I wrote 'em](https://scottchacon.com/2011/08/31/github-flow) . However, a decade later, and with a new and more powerful branching toolset, we're able to amend that basic workflow to be simpler, faster, more flexible, and less error prone. Let's take a quick minute to explore what the Butler Flow is for software development teams using GitButler and how this can make all of our lives easier. [Overview](https://docs.gitbutler.com/butler-flow#overview) ------------------------------------------------------------ In a nutshell, the basic development cycle is very simple. * All work is based off a "target branch", which is a representation of released production code. * All work immediately exists in a branch. * Work can be shared with teammates for review as early as possible. * All branches that are close to merging can be applied locally for integration testing. * Branches can be reviewed independently and merged after final review. * Integrated branches are automatically removed from developer context. ### [The Target Branch](https://docs.gitbutler.com/butler-flow#the-target-branch) 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, 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](https://docs.gitbutler.com/butler-flow#parallel-branches) Once you choose a target branch, everything that is in your working directory and not ignored by the Git Ignore specification must be owned by a virtual branch. If you don't have one active, GitButler will automatically create one for you. All subsequent changes to your working directory, either by applying other branches or directly modifying files, must be owned by a virtual branch. Branches are meant to be small, independent and rapidly integrated. However, longer lived branches can be continuously re-integrated, keeping them clean and mergeable for long periods of time if needed, while still being shareable and reviewable with your team. Parallel branches can be started and ended entirely independently of each other. Developers can work on longer branches, while starting, reviewing, finishing, merging, and deleting small ones without ever changing branch context. ### [Collaboration](https://docs.gitbutler.com/butler-flow#collaboration) All your team's work, whether created and managed by GitButler or not, exists on the central server as normal Git branches. These will automatically be pulled down and kept up to date by GitButler and can be converted into parallel branches and applied to your working directory in addition to your branches. This allows you to integrate work from the rest of your team continuously and early, while still keeping non-dependent changes separated and independently reviewable and mergable. It allows you to review code without needing to entirely switch contexts, and to do so early and often in an executable environment. Merge conflicts are known almost as soon as they occur and can be communicated about and collaborated on far before an upstream merge. ### [Maintenance](https://docs.gitbutler.com/butler-flow#maintenance) 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. Last updated on 7/30/2026 [Previous\ \ Desktop Overview](https://docs.gitbutler.com/overview) [Next\ \ Parallel Branches](https://docs.gitbutler.com/features/branch-management/virtual-branches) ### On this page [Overview](https://docs.gitbutler.com/butler-flow#overview) [The Target Branch](https://docs.gitbutler.com/butler-flow#the-target-branch) [Parallel Branches](https://docs.gitbutler.com/butler-flow#parallel-branches) [Collaboration](https://docs.gitbutler.com/butler-flow#collaboration) [Maintenance](https://docs.gitbutler.com/butler-flow#maintenance) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/butler-flow.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22butler-flow%22) --- # Inspect and adjust agent work | GitButler Docs Inspect and adjust agent work ============================= Choose a GitButler surface for previewing and adjusting coding-agent branch and commit history. 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](https://docs.gitbutler.com/gitbutler-tui) , the CLI, and the Desktop Client GUI. Use this page to pick the surface you want. The detailed workflows live in their own docs. [GitButler TUI](https://docs.gitbutler.com/ai-agents/review-agent-work#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. but tui For the full workflow and keybindings, see the [TUI guide](https://docs.gitbutler.com/gitbutler-tui) . ![GitButler TUI showing available keyboard commands over workspace status](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fai-agents-tui.abc95c4b.png&w=3840&q=75) GitButler TUI command view. [GitButler CLI](https://docs.gitbutler.com/ai-agents/review-agent-work#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](https://docs.gitbutler.com/cli-overview) . [GitButler Desktop Client](https://docs.gitbutler.com/ai-agents/review-agent-work#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. but gui For details, see the [Desktop Overview](https://docs.gitbutler.com/overview) , [Branch lanes](https://docs.gitbutler.com/features/branch-management/branch-lanes) , and [Commits](https://docs.gitbutler.com/features/branch-management/commits) . [Operations history](https://docs.gitbutler.com/ai-agents/review-agent-work#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](https://docs.gitbutler.com/features/timeline) , [`but oplog`](https://docs.gitbutler.com/commands/but-oplog) , and [`but undo`](https://docs.gitbutler.com/commands/but-undo) . Last updated on 7/30/2026 [Previous\ \ Parallel agents](https://docs.gitbutler.com/ai-agents/parallel-agents) [Next\ \ Tuning agent behavior](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior) ### On this page [GitButler TUI](https://docs.gitbutler.com/ai-agents/review-agent-work#gitbutler-tui) [GitButler CLI](https://docs.gitbutler.com/ai-agents/review-agent-work#gitbutler-cli) [GitButler Desktop Client](https://docs.gitbutler.com/ai-agents/review-agent-work#gitbutler-desktop-client) [Operations history](https://docs.gitbutler.com/ai-agents/review-agent-work#operations-history) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/ai-agents/review-agent-work.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22ai-agents/review-agent-work%22) --- # Parallel agents | GitButler Docs Parallel agents =============== 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: Work on checkout validation. When either session is ready, ask it to commit: 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](https://docs.gitbutler.com/features/branch-management/virtual-branches) . The `Version control` instructions written by `but agent setup` (see [Getting started](https://docs.gitbutler.com/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](https://docs.gitbutler.com/ai-agents/parallel-agents#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](https://docs.gitbutler.com/ai-agents/parallel-agents#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: 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: 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](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#create-stacked-pull-requests) . [Know what is shared](https://docs.gitbutler.com/ai-agents/parallel-agents#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](https://docs.gitbutler.com/ai-agents/useful-requests) . Last updated on 7/30/2026 [Previous\ \ Useful requests](https://docs.gitbutler.com/ai-agents/useful-requests) [Next\ \ Inspect and adjust agent work](https://docs.gitbutler.com/ai-agents/review-agent-work) ### On this page [How this differs from worktrees](https://docs.gitbutler.com/ai-agents/parallel-agents#how-this-differs-from-worktrees) [Handle dependencies explicitly](https://docs.gitbutler.com/ai-agents/parallel-agents#handle-dependencies-explicitly) [Know what is shared](https://docs.gitbutler.com/ai-agents/parallel-agents#know-what-is-shared) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/ai-agents/parallel-agents.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22ai-agents/parallel-agents%22) --- # Workspace Branch | GitButler Docs Workspace Branch ================ What is the \`gitbutler/workspace\` branch and merge commit it points to? Also, why do we need it? 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: 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](https://docs.gitbutler.com/workspace-branch#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](https://docs.gitbutler.com/workspace-branch#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 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. Last updated on 7/30/2026 [Previous\ \ but worktree](https://docs.gitbutler.com/commands/but-worktree) [Next\ \ Debugging](https://docs.gitbutler.com/development/debugging) ### On this page [Status, Diff and Log](https://docs.gitbutler.com/workspace-branch#status-diff-and-log) [Committing, Branching, Checking Out](https://docs.gitbutler.com/workspace-branch#committing-branching-checking-out) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/workspace-branch.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22workspace-branch%22) --- # Releases | GitButler Docs Releases ======== Information about GitButler's release tracks, supported platforms, and download options for stable and nightly builds. 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](https://docs.gitbutler.com/releases#platforms) ----------------------------------------------------------- We bundle and ship GitButler for Mac OS, Windows, and Linux. ### [Windows](https://docs.gitbutler.com/releases#windows) | Arch | Format | In-app updater | | --- | --- | --- | | `x86_64` | `msi` | | ### [Mac OS](https://docs.gitbutler.com/releases#mac-os) | Arch | Format | In-app updater | | --- | --- | --- | | `x86_64` | `dmg` | | | `arm64` | `dmg` | | ### [Linux](https://docs.gitbutler.com/releases#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. Last updated on [Previous\ \ Supporters](https://docs.gitbutler.com/community/supporters) ### On this page [Platforms](https://docs.gitbutler.com/releases#platforms) [Windows](https://docs.gitbutler.com/releases#windows) [Mac OS](https://docs.gitbutler.com/releases#mac-os) [Linux](https://docs.gitbutler.com/releases#linux) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/releases.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22releases%22) --- # Debugging | GitButler Docs Debugging ========= Troubleshooting guide for GitButler technical issues including logs, data files, and platform-specific debugging tips. If you are having technical issues with the GitButler client, here are a few things you can do to help us help you. Or help yourself. If you get stuck or need help with anything, hit us up over on Discord, here's [GitButler Discord Server Link](https://discord.gg/MmFkmaJ42D) . ![](https://docs.gitbutler.com/img/nothing-found.svg) The first things to try is checking out the frontend related logs in the console by opening the developer tools in GitButler via the "View" -> "Developer Tools" menu option. Next, if you launch GitButler from the command line, you can view the backend logs directly in your terminal. [Logs](https://docs.gitbutler.com/development/debugging#logs) -------------------------------------------------------------- Often the most helpful thing is to look at the logs. GitButler is a Tauri app, so the logs are in your OS's [app log directory](https://docs.rs/tauri/1.8.1/tauri/api/path/fn.app_log_dir.html) . This should be: macOSWindowsLinux ~/Library/Logs/com.gitbutler.app/ In this directory, there should be rolling daily logs: Terminal ❯ cd ~/Library/Logs/com.gitbutler.app ❯ tree -L 1 ├── GitButler.log ├── GitButler.log.2023-09-02 ├── GitButler.log.2023-09-03 ├── GitButler.log.2023-09-04 ├── GitButler.log.2023-09-05 ├── GitButler.log.2023-09-06 ├── GitButler.log.2023-09-07 ├── GitButler.log.2023-09-08 ├── GitButler.log.2023-10-10 ├── GitButler.log.2024-01-30 └── tokio-console ❯ tail GitButler.log.2024-01-30 2024-01-30T13:02:56.319843Z INFO get_public_key: gitbutler-app/src/keys/commands.rs:20: new 2024-01-30T13:02:56.320000Z INFO git_get_global_config: gitbutler-app/src/commands.rs:116: new key="gitbutler.utmostDiscretion" 2024-01-30T13:02:56.320117Z INFO git_get_global_config: gitbutler-app/src/commands.rs:116: new key="gitbutler.signCommits" 2024-01-30T13:02:56.320194Z INFO get_public_key: gitbutler-app/src/keys/commands.rs:20: close time.busy=317µs time.idle=47.0µs 2024-01-30T13:02:56.320224Z INFO git_get_global_config: gitbutler-app/src/commands.rs:116: close time.busy=204µs time.idle=25.3µs key="gitbutler.utmostDiscretion" 2024-01-30T13:02:56.320276Z INFO git_get_global_config: gitbutler-app/src/commands.rs:116: close time.busy=133µs time.idle=35.8µs key="gitbutler.signCommits" 2024-01-30T13:02:56.343467Z INFO menu_item_set_enabled: gitbutler-app/src/menu.rs:11: new menu_item_id="project/settings" enabled=false 2024-01-30T13:02:56.343524Z INFO menu_item_set_enabled: gitbutler-app/src/menu.rs:11: close time.busy=35.7µs time.idle=28.8µs menu_item_id="project/settings" enabled=false [Data Files](https://docs.gitbutler.com/development/debugging#data-files) -------------------------------------------------------------------------- GitButler also keeps its own data about each of your projects. The virtual branch metadata, your user config stuff, a log of changes in each file, etc. If you want to inspect what GitButler is doing or debug or reset everything, you can go to our data directory. macOSWindowsLinux ~/Library/Application Support/com.gitbutler.app/ In this folder there are a bunch of interesting things. Terminal ❯ cd ~/Library/Application\ Support/com.gitbutler.app ❯ tree . ├── keys │ ├── ed25519 │ └── ed25519.pub ├── projects.json └── settings.json 4 directories, 4 files The `projects.json` file will have a list of your projects metadata: Terminal ❯ cat projects.json [\ {\ "id": "71218b1b-ee2e-4e0f-8393-54f467cd665b",\ "title": "gitbutler-blog",\ "description": null,\ "path": "/Users/scottchacon/projects/gitbutler-blog",\ "preferred_key": "generated",\ "ok_with_force_push": true,\ "api": null,\ "gitbutler_data_last_fetch": null,\ "gitbutler_code_push_state": null,\ "project_data_last_fetch": {\ "fetched": {\ "timestamp": {\ "secs_since_epoch": 1706619724,\ "nanos_since_epoch": 202467000\ }\ }\ }\ }\ ] The `settings.json` are some top level preferences you've set. Terminal ❯ cat settings.json { "appAnalyticsConfirmed": true, "appNonAnonMetricsEnabled": true } Finally, the `keys` directory holds the SSH key that we generate for you in case you don't want to go through creating your own. It's only used if you want to use it to sign commits or use it for authentication. ### [Per-project repository data](https://docs.gitbutler.com/development/debugging#per-project-repository-data) Most repository-specific GitButler state lives next to the repository itself, inside the `.git` directory. By default, GitButler stores that data in `.git/gitbutler` for release builds, nightly builds and developer builds. You can override that location with a Git config change, here for the stable build: Terminal ❯ git config --local gitbutler.storagePath gitbutler-alt You can also set it globally if you want all repositories opened by GitButler on that machine to use the same base configuration: Setting it to a shared directory is useful if the project locations themselves are on a filesystem that doesn't support Sqlite very well, like a network drive. Terminal ❯ git config --global gitbutler.storagePath /path/to/gitbutler-projects Setting it to a relative path would force a channel, like Nightly, to reuse the data of stable builds. Terminal ❯ git config --global gitbutler.nightly.storagePath gitbutler The Git config key depends on the app channel: * Release builds use `gitbutler.storagePath` * Nightly builds use `gitbutler.nightly.storagePath` * Developer builds use `gitbutler.dev.storagePath` There are a couple of constraints on the configured path: * Relative paths are resolved relative to the repository's `.git` directory * If the resolved path stays inside `.git`, it must be under a top-level directory whose name starts with `gitbutler`, case-insensitive * You cannot point it at `.git` itself * If the resolved path ends up outside `.git`, GitButler appends a project-path specific identifier so multiple repositories can share the same base directory safely For example, these are valid: Terminal ❯ git config --local gitbutler.storagePath gitbutler-alt ❯ git config --local gitbutler.storagePath ../../gitbutler-projects If you use a path outside `.git`, GitButler treats it as a base directory. For example, `../../gitbutler-projects` becomes something like `../../gitbutler-projects/` after resolution. [Linux](https://docs.gitbutler.com/development/debugging#linux) ---------------------------------------------------------------- ### [`glibc` Errors](https://docs.gitbutler.com/development/debugging#glibc-errors) The Linux installation is currently being built in a GitHub Action with Ubuntu 24.04. This means support is limited to those installations using the same or newer version of `glibc`. Unfortunately we cannot build using earlier versions of Ubuntu due to another incompatibility with `libwebkit2gtk-4.1` and Tauri at the moment. If you're using an older distribution, you may be interested in trying our Flatpak package available on Flathub. ### [`Failed to create EGL image from DMABuf`](https://docs.gitbutler.com/development/debugging#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`. Last updated on [Previous\ \ Workspace Branch](https://docs.gitbutler.com/workspace-branch) [Next\ \ Contact Us](https://docs.gitbutler.com/community/contact-us) ### On this page [Logs](https://docs.gitbutler.com/development/debugging#logs) [Data Files](https://docs.gitbutler.com/development/debugging#data-files) [Per-project repository data](https://docs.gitbutler.com/development/debugging#per-project-repository-data) [Linux](https://docs.gitbutler.com/development/debugging#linux) [`glibc` Errors](https://docs.gitbutler.com/development/debugging#glibc-errors) [`Failed to create EGL image from DMABuf`](https://docs.gitbutler.com/development/debugging#failed-to-create-egl-image-from-dmabuf) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/development/debugging.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22development/debugging%22) --- # Getting started | GitButler Docs Getting started =============== Install \`but\`, run \`but agent setup\`, and give coding agents a GitButler version-control policy. 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](https://docs.gitbutler.com/ai-agents/getting-started#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: curl -fsSL https://gitbutler.com/install.sh | sh See [Installation and setup](https://docs.gitbutler.com/cli-guides/installation) for the full CLI install options. [Run the agent setup wizard](https://docs.gitbutler.com/ai-agents/getting-started#run-the-agent-setup-wizard) -------------------------------------------------------------------------------------------------------------- From the repository where the agent will work, run: but agent setup The wizard asks which agents you use, where the setup applies, and which workflow preferences you want. It can: * install the GitButler skill for Codex, Claude Code, Cursor, GitHub Copilot, Windsurf / Devin, OpenCode, or Agent Skills; * save workflow instructions globally, in this repository, or both; * run `but setup` for this repository when GitButler needs workspace mode. Before it writes anything, the wizard shows the skill install paths, instruction files, any repository setup step, and the exact generated text. `but agent` with no subcommand starts the same wizard. For command details, see [`but agent`](https://docs.gitbutler.com/commands/but-agent) . The wizard installs the skill for you. To check installed skills and update any outdated copies later without rerunning the wizard, use: but skill check --update See [`but skill`](https://docs.gitbutler.com/commands/but-skill) for other install and update options. [Set up the repository](https://docs.gitbutler.com/ai-agents/getting-started#set-up-the-repository) ---------------------------------------------------------------------------------------------------- GitButler currently needs the repository in workspace mode for its multi-branch model: multiple GitButler branches in one working directory. The setup wizard runs this for you when needed. You can also run it yourself: but setup For the full list of setup changes, see [`but setup`](https://docs.gitbutler.com/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](https://docs.gitbutler.com/ai-agents/getting-started#add-optional-agent-instructions) ------------------------------------------------------------------------------------------------------------------------ The wizard can write common workflow preferences for you: folding small fixes into the right commits, splitting mixed work, stacking dependent branches, updating from the target branch, opening draft PRs, landing approved work directly onto the target instead of opening pull requests (single-repository setups only), using a publish phrase, naming branches, following commit-message conventions, and creating checkpoint commits. Use [Tuning agent behavior](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior) when you want to read the policies before choosing them, adjust them after the wizard runs, or copy individual snippets by hand. These instructions steer agent behavior; they are not access controls. Use your usual repository permissions and branch protection for hard limits. For prompt examples that ask for specific branch and commit outcomes, see [Useful requests](https://docs.gitbutler.com/ai-agents/useful-requests) . Last updated on 7/30/2026 [Previous\ \ Overview](https://docs.gitbutler.com/ai-agents/overview) [Next\ \ Useful requests](https://docs.gitbutler.com/ai-agents/useful-requests) ### On this page [Install the `but` CLI](https://docs.gitbutler.com/ai-agents/getting-started#install-the-but-cli) [Run the agent setup wizard](https://docs.gitbutler.com/ai-agents/getting-started#run-the-agent-setup-wizard) [Set up the repository](https://docs.gitbutler.com/ai-agents/getting-started#set-up-the-repository) [Add optional agent instructions](https://docs.gitbutler.com/ai-agents/getting-started#add-optional-agent-instructions) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/ai-agents/getting-started.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22ai-agents/getting-started%22) --- # GitButler TUI | GitButler Docs GitButler TUI ============= Inspect and edit your GitButler workspace from interactive terminal UIs. Use `but tui` when you want a live, keyboard-first GitButler workspace in your terminal. It opens an interactive view of your workspace state: uncommitted changes, active branches, commits, files, and the common base. but tui Run it from a GitButler-managed repository. If the repository has not been set up yet, run [`but setup`](https://docs.gitbutler.com/commands/but-setup) first. ![GitButler TUI showing available keyboard commands over workspace status](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fai-agents-tui.abc95c4b.png&w=3840&q=75) GitButler TUI command view. [Pick the right terminal workflow](https://docs.gitbutler.com/gitbutler-tui#pick-the-right-terminal-workflow) -------------------------------------------------------------------------------------------------------------- * Use `but tui` for the full workspace view: branches, commits, assigned changes, uncommitted changes, diffs, and local history operations. * Use [`but diff --tui`](https://docs.gitbutler.com/commands/but-diff) for focused diff review without the full workspace editing surface. * Mark files or hunks inside `but tui`, then press `c` when you want to commit only those changes. * Use [command mode](https://docs.gitbutler.com/gitbutler-tui#use-command-mode) inside `but tui` when you need a `but` command without leaving the TUI. * Use plain CLI commands when you need repeatable output for scripts, agents, or logs. [What you can do](https://docs.gitbutler.com/gitbutler-tui#what-you-can-do) ---------------------------------------------------------------------------- In the full workspace TUI, you can: * Inspect uncommitted changes, branch lanes, commits, and file-level changes. * Open a details pane for the selected branch, commit, file, or hunk. * Create commits from all or selected uncommitted changes, and insert empty commits. * Create branches. * Move commits or branches. * Squash commits, amend changes into commits, or move committed changes back to the uncommitted area. * Mark multiple commits and act on them together. * Reword commits or branch names. * Open selected files in another program. * Discard local work after a confirmation prompt. * Undo and redo GitButler operations. For the complete shortcut list, press `?` inside the TUI. The help popup is generated from the current keybindings, so it is the source of truth. [Move around](https://docs.gitbutler.com/gitbutler-tui#move-around) -------------------------------------------------------------------- Most navigation uses Vim-style keys, with arrow keys where they make sense. * `j` / `k` move down and up. * `Shift+j` / `Shift+k` jump to the next or previous section. * `g` jumps to uncommitted changes. * `Shift+g` jumps to the common merge base. * `t` opens the branch picker. * `Esc` backs out of the current mode. * `q` quits. The hotbar at the bottom shows the most useful keys for the current mode. [Inspect changes](https://docs.gitbutler.com/gitbutler-tui#inspect-changes) ---------------------------------------------------------------------------- Select a branch, commit, file, or hunk, then press `d` to open details. The details pane shows commit metadata and diffs for the selected row. * `d` toggles the split details pane. * `Shift+d` toggles full-screen details. * `f` shows files in the selected commit. * `Shift+f` shows files across all commits. * `l` focuses the details pane. * `h` returns focus to the status list. * `+` and `-` resize the split details pane. * In details mode, `j` / `k` move between hunks. * In details mode, `Shift+j` / `Shift+k` scroll. * In details mode, `r` starts squash mode from the current uncommitted hunk. * In details mode, `y` copies the current hunk. [Change local history](https://docs.gitbutler.com/gitbutler-tui#change-local-history) -------------------------------------------------------------------------------------- * Press `c` to create a commit from the selected uncommitted changes. Press `i` in commit mode to write the message inline, `e` to leave it empty, or `b` to commit to a new branch. * Press `n` to insert an empty commit. * Press `b` to create a branch. * Press `m` to move the selected commit or branch, then choose the destination and press `Enter`. * Press `r` to enter squash mode with the selected source. Choose a target and press `Enter`. The target is labeled with the operation GitButler will run: `amend`, `squash`, or `uncommit`. * In squash mode, press `u` to keep the target commit message when combining commits. * Press `Space` to mark multiple commits, then press `r` to squash them into another commit. * Press `Enter` on a commit or branch to reword it inline. Press `Shift+m` to reword a commit in your configured editor. * Press `x` to discard the selected local work. Destructive actions ask for confirmation. * Press `u` to undo the last operation and `Shift+u` to redo it. GitButler records these operations in the operations log, so you can also inspect and recover with [`but oplog`](https://docs.gitbutler.com/commands/but-oplog) , [`but undo`](https://docs.gitbutler.com/commands/but-undo) , and [`but redo`](https://docs.gitbutler.com/commands/but-redo) . [Commit selected changes](https://docs.gitbutler.com/gitbutler-tui#commit-selected-changes) -------------------------------------------------------------------------------------------- You do not need to stage changes before committing them. Mark the files or hunks that belong together, then create the commit directly: 1. Select an uncommitted file and press `Space` to mark it. 2. To select individual hunks, open the file details with `d`, focus the details pane with `l`, and press `Space` on each hunk you want. 3. Press `c`, choose the target branch or commit position, and press `Enter`. Commit mode opens your configured editor for the message by default. Press `i` before confirming to write the message inline, `e` to leave it empty, or `b` to create the commit on a new branch. [Open files in another program](https://docs.gitbutler.com/gitbutler-tui#open-files-in-another-program) -------------------------------------------------------------------------------------------------------- Select an uncommitted or committed file and press `o` to open it in the default available program. Press `Shift+o` to choose a program instead. You can mark multiple files or hunks before opening them. When multiple items are marked, GitButler opens the containing files rather than individual hunks. [Restore your last selection](https://docs.gitbutler.com/gitbutler-tui#restore-your-last-selection) ---------------------------------------------------------------------------------------------------- Start the TUI with `--remember-selection` to remember supported selections such as an uncommitted item, branch, commit, or file when you quit, then restore that selection the next time you use the same option: but tui --remember-selection If the saved branch, commit, or file no longer exists, the TUI starts with its normal default selection. [Use command mode](https://docs.gitbutler.com/gitbutler-tui#use-command-mode) ------------------------------------------------------------------------------ Use command mode when you want the TUI to stay open but need one command. * `:` runs a `but` command. For example, type `branch list` rather than `but branch list`. * `!` runs an external command. It does not run through your shell, so shell syntax like pipes, redirects, built-ins, and `&&` needs `sh -c '...'`. * `Ctrl+r` reloads the workspace state. After the command finishes, press `Enter` to return to the TUI. Successful commands reload the workspace state. Failed commands return with an error. [Use the diff TUI](https://docs.gitbutler.com/gitbutler-tui#use-the-diff-tui) ------------------------------------------------------------------------------ [`but diff --tui`](https://docs.gitbutler.com/commands/but-diff) opens a smaller TUI focused only on diffs. It has a file list on the left and a diff pane on the right. but diff --tui but diff g0 --tui but diff my-branch --tui * `j` / `k` move through files in the file list. * `h` / `l` / `Tab` switch panes. * In the diff pane, `j` / `k` scroll one line. * `Space` or `PageDown` scrolls down a page. * `PageUp` scrolls up a page. * `q` quits. You can make `but diff` use the TUI by default: but config ui set tui true Use `--no-tui` for a one-off plain diff: but diff --no-tui Last updated on 7/30/2026 [Previous\ \ CLI Overview](https://docs.gitbutler.com/cli-overview) [Next\ \ Installation and Setup](https://docs.gitbutler.com/cli-guides/installation) ### On this page [Pick the right terminal workflow](https://docs.gitbutler.com/gitbutler-tui#pick-the-right-terminal-workflow) [What you can do](https://docs.gitbutler.com/gitbutler-tui#what-you-can-do) [Move around](https://docs.gitbutler.com/gitbutler-tui#move-around) [Inspect changes](https://docs.gitbutler.com/gitbutler-tui#inspect-changes) [Change local history](https://docs.gitbutler.com/gitbutler-tui#change-local-history) [Commit selected changes](https://docs.gitbutler.com/gitbutler-tui#commit-selected-changes) [Open files in another program](https://docs.gitbutler.com/gitbutler-tui#open-files-in-another-program) [Restore your last selection](https://docs.gitbutler.com/gitbutler-tui#restore-your-last-selection) [Use command mode](https://docs.gitbutler.com/gitbutler-tui#use-command-mode) [Use the diff TUI](https://docs.gitbutler.com/gitbutler-tui#use-the-diff-tui) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/gitbutler-tui.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22gitbutler-tui%22) --- # Operations History | GitButler Docs Features Operations History ================== Use GitButler's operations history to undo actions and restore previous project states with automatic snapshots. Undo nearly any of your actions or go back in time to an earlier state. [How it works](https://docs.gitbutler.com/features/timeline#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. ![The operations history tab](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Foplog.png&w=3840&q=75) The operations history tab [Restoring State](https://docs.gitbutler.com/features/timeline#restoring-state) -------------------------------------------------------------------------------- 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. ![oplog-restore.png](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Foplog-restore.png&w=3840&q=75) oplog-restore.png [Recovering Content](https://docs.gitbutler.com/features/timeline#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. ![preview-oplog.png](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fpreview-oplog.png&w=3840&q=75) preview-oplog.png Last updated on [Previous\ \ AI Assistance](https://docs.gitbutler.com/features/branch-management/ai-assistance) [Next\ \ Connect GitButler to GitHub](https://docs.gitbutler.com/features/forge-integration/github-integration) ### On this page [How it works](https://docs.gitbutler.com/features/timeline#how-it-works) [Restoring State](https://docs.gitbutler.com/features/timeline#restoring-state) [Recovering Content](https://docs.gitbutler.com/features/timeline#recovering-content) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/timeline.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/timeline%22) --- # Useful requests | GitButler Docs Useful requests =============== 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](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior) . [Commit changes](https://docs.gitbutler.com/ai-agents/useful-requests#commit-changes) -------------------------------------------------------------------------------------- The agent commits the session's changes to its dedicated GitButler branch, not unrelated user or agent work. You can tell your agent: Commit your changes. Relevant command: [`but commit`](https://docs.gitbutler.com/commands/but-commit) . [Clean up history](https://docs.gitbutler.com/ai-agents/useful-requests#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. 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`](https://docs.gitbutler.com/commands/but-move) , [`but squash`](https://docs.gitbutler.com/commands/but-squash) , [`but reword`](https://docs.gitbutler.com/commands/but-reword) , [`but amend`](https://docs.gitbutler.com/commands/but-amend) , and [`but uncommit`](https://docs.gitbutler.com/commands/but-uncommit) . [Split a large commit into smaller commits](https://docs.gitbutler.com/ai-agents/useful-requests#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. Split this into smaller commits by concern. Keep tests with the behavior they verify. [Put uncommitted fixes into existing commits](https://docs.gitbutler.com/ai-agents/useful-requests#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. Amend your follow-up fixes into the appropriate local commits. Relevant commands: [`but absorb`](https://docs.gitbutler.com/commands/but-absorb) and [`but amend`](https://docs.gitbutler.com/commands/but-amend) . [Take changes out of a commit](https://docs.gitbutler.com/ai-agents/useful-requests#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. Take the debug logging out of the commit and leave it uncommitted. Move the docs changes out of the feature commit and into a separate docs commit. Relevant commands: [`but uncommit`](https://docs.gitbutler.com/commands/but-uncommit) and [`but commit`](https://docs.gitbutler.com/commands/but-commit) . [Create stacked pull requests](https://docs.gitbutler.com/ai-agents/useful-requests#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. 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](https://docs.gitbutler.com/features/branch-management/stacked-branches) , [`but move`](https://docs.gitbutler.com/commands/but-move) , and [`but pr`](https://docs.gitbutler.com/commands/but-pr) . [Work in parallel](https://docs.gitbutler.com/ai-agents/useful-requests#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](https://docs.gitbutler.com/ai-agents/parallel-agents) . Last updated on 7/30/2026 [Previous\ \ Getting started](https://docs.gitbutler.com/ai-agents/getting-started) [Next\ \ Parallel agents](https://docs.gitbutler.com/ai-agents/parallel-agents) ### On this page [Commit changes](https://docs.gitbutler.com/ai-agents/useful-requests#commit-changes) [Clean up history](https://docs.gitbutler.com/ai-agents/useful-requests#clean-up-history) [Split a large commit into smaller commits](https://docs.gitbutler.com/ai-agents/useful-requests#split-a-large-commit-into-smaller-commits) [Put uncommitted fixes into existing commits](https://docs.gitbutler.com/ai-agents/useful-requests#put-uncommitted-fixes-into-existing-commits) [Take changes out of a commit](https://docs.gitbutler.com/ai-agents/useful-requests#take-changes-out-of-a-commit) [Create stacked pull requests](https://docs.gitbutler.com/ai-agents/useful-requests#create-stacked-pull-requests) [Work in parallel](https://docs.gitbutler.com/ai-agents/useful-requests#work-in-parallel) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/ai-agents/useful-requests.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22ai-agents/useful-requests%22) --- # Parallel Branches | GitButler Docs FeaturesBranch Management Parallel Branches ================= Understanding GitButler's parallel branches that allow simultaneous work on multiple branches in a single working directory. 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. [Overview](https://docs.gitbutler.com/features/branch-management/virtual-branches#overview) -------------------------------------------------------------------------------------------- With normal Git branching, you can only work on one branch at a time. There is one `HEAD` reference and one index. 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. Each lane also has its own staging area, so you can stage changes for each branch before deciding to commit them. ![A project with three simultaneous branches, plus staged changes in each one and some unstaged changes.](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fvbranch-ex.png&w=3840&q=75) A project with three simultaneous branches, plus staged changes in each one and some unstaged changes. [How it works](https://docs.gitbutler.com/features/branch-management/virtual-branches#how-it-works) ---------------------------------------------------------------------------------------------------- Let's say that you make changes to two different files and `git status` would list two modified files. In GitButler, you can stage the change in each file to a different branch, then commit each branch independently. 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. Last updated on [Previous\ \ Butler Flow](https://docs.gitbutler.com/butler-flow) [Next\ \ Create stacked branches and pull requests](https://docs.gitbutler.com/features/branch-management/stacked-branches) ### On this page [Overview](https://docs.gitbutler.com/features/branch-management/virtual-branches#overview) [How it works](https://docs.gitbutler.com/features/branch-management/virtual-branches#how-it-works) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/virtual-branches.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/virtual-branches%22) --- # Overview | GitButler Docs Overview ======== 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](https://docs.gitbutler.com/cli-overview) , and you can inspect the same state in the [Desktop Client](https://docs.gitbutler.com/overview) . For when to use GitButler instead of separate worktrees, see [Parallel agents](https://docs.gitbutler.com/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. We ran coding agents through the same version-control tasks with Git, Jujutsu, and GitButler and published the results at [vcbench.dev](https://vcbench.dev/) . With GitButler, agents used about 80% fewer commands and finished around 60% faster than with plain Git, at similar reliability. It is our own benchmark, so the tasks, deterministic grader, and full results are public for you to check. [Quick start](https://docs.gitbutler.com/ai-agents/overview#quick-start) ------------------------------------------------------------------------- Run this from the repository where your agent will work: but agent setup The wizard can install the GitButler skill, write GitButler version-control instructions for your agent, and prepare the repository with `but setup` when GitButler needs workspace mode. It shows the files and exact instructions before writing anything. For the full setup path, see [Getting started](https://docs.gitbutler.com/ai-agents/getting-started) . To choose or adjust the policies by hand, see [Tuning agent behavior](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior) . [What agents can do with GitButler](https://docs.gitbutler.com/ai-agents/overview#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 commit selected files or hunks by passing their IDs positionally to `but commit`. Other uncommitted changes stay untouched, so 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`](https://docs.gitbutler.com/commands/but-oplog) to restore an earlier local GitButler state if the branch layout needs to be rolled back. [History edits as direct commands](https://docs.gitbutler.com/ai-agents/overview#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. The command depends on the task: use [`but amend`](https://docs.gitbutler.com/commands/but-amend) for uncommitted fixes that belong in an existing commit, [`but squash`](https://docs.gitbutler.com/commands/but-squash) to combine commits or move committed changes into another commit, and [`but uncommit`](https://docs.gitbutler.com/commands/but-uncommit) to move committed changes back to the uncommitted area. For reviewed work, agents can push branches and open PRs or MRs with [`but pr`](https://docs.gitbutler.com/commands/but-pr) . When you explicitly authorize a direct update to the target branch, [`but land`](https://docs.gitbutler.com/commands/but-land) can land a branch without a pull request. Last updated on 7/30/2026 [Previous\ \ Recovering Stuff](https://docs.gitbutler.com/troubleshooting/recovering-stuff) [Next\ \ Getting started](https://docs.gitbutler.com/ai-agents/getting-started) ### On this page [Quick start](https://docs.gitbutler.com/ai-agents/overview#quick-start) [What agents can do with GitButler](https://docs.gitbutler.com/ai-agents/overview#what-agents-can-do-with-gitbutler) [History edits as direct commands](https://docs.gitbutler.com/ai-agents/overview#history-edits-as-direct-commands) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/ai-agents/overview.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22ai-agents/overview%22) --- # Rebasing and Conflicts | GitButler Docs FeaturesBranch Management Rebasing and Conflicts ====================== Learn GitButler's approach to rebasing and conflict resolution that allows commits to continue rebasing even with conflicts. 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: ![Updating from upstream will let you know if there will be conflicts](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fupdate-will-conflict.png&w=3840&q=75) Updating from upstream will let you know if there will be 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 your commits have conflicts](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fconflict-resolve.png&w=3840&q=75) When your commits have conflicts 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. ![Resolving a conflict by individual commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fresolve-conflicts-mode.png&w=3840&q=75) Resolving a conflict by individual 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. ![conflicts-resolved.png](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fconflicts-resolved.png&w=3840&q=75) conflicts-resolved.png Last updated on [Previous\ \ Push and fetch](https://docs.gitbutler.com/features/branch-management/pushing-and-fetching) [Next\ \ Upstream Integration](https://docs.gitbutler.com/features/branch-management/upstream-integration) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/merging.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/merging%22) --- # Tuning agent behavior | GitButler Docs Tuning agent behavior ===================== Add optional instruction snippets that steer how coding agents amend, checkpoint, stack, publish, and recover work with GitButler. `but agent setup` can write many of these policies for you. Start with [Getting started](https://docs.gitbutler.com/ai-agents/getting-started) when you want the wizard path; use this page when you want to understand, copy, or adjust individual policies. Add these optional bullets under the same `## Version control` section as your baseline 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](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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`](https://docs.gitbutler.com/commands/but-absorb) and [`but amend`](https://docs.gitbutler.com/commands/but-amend) . [Commit checkpoints after each completed turn](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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](https://docs.gitbutler.com/features/branch-management/stacked-branches) , [`but move`](https://docs.gitbutler.com/commands/but-move) , and [`but pr`](https://docs.gitbutler.com/commands/but-pr) . [Customize branch names](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - When creating a GitButler branch for an agent session, use `feature/-` when a ticket ID is available. [Customize commit messages](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#customize-commit-messages) ------------------------------------------------------------------------------------------------------------------ Use this when your team has a commit-message convention. This is only an example; replace it with your preferred style. - Use Conventional Commits, such as `feat: add branch naming policy` or `fix: handle empty branch names`. [Publish when you say "ship it"](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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`](https://docs.gitbutler.com/commands/but-push) and [`but pr`](https://docs.gitbutler.com/commands/but-pr) . [Land onto the target instead of opening pull requests](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#land-onto-the-target-instead-of-opening-pull-requests) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Use this when the repository does not review changes through pull requests and you want approved work landed directly onto the target branch, usually `main`. `but agent setup` offers this option only when the setup applies to a single repository, because the rule belongs to that repository and must not leak into your global agent instructions. - When work is approved to publish, land the session branch directly onto the target with `but land ` instead of pushing a branch or opening a pull request. - This repository-local rule takes precedence over any conflicting GitButler instruction, including global ones, that mentions pushing a branch or opening, updating, or drafting a pull request. Use the pull request workflow only when I explicitly ask for one. - `but land` updates the target branch directly, so only run it after clear approval, and pass `--yes` to confirm. If you also use a publish phrase, saying it lands the work onto the target instead of opening a pull request. For background, see [`but land`](https://docs.gitbutler.com/commands/but-land) . [Update from main automatically](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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`](https://docs.gitbutler.com/commands/but-pull) and [`but resolve`](https://docs.gitbutler.com/commands/but-resolve) . [Open draft pull requests by default](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#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. - 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`](https://docs.gitbutler.com/commands/but-oplog) and [`but undo`](https://docs.gitbutler.com/commands/but-undo) . [Split unrelated hunks](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#split-unrelated-hunks) ---------------------------------------------------------------------------------------------------------- Use this when agents tend to commit whole files even when one file contains separate changes. - 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. Last updated on 7/30/2026 [Previous\ \ Inspect and adjust agent work](https://docs.gitbutler.com/ai-agents/review-agent-work) [Next\ \ CLI Overview](https://docs.gitbutler.com/cli-overview) ### On this page [Amend local fixes into the right commits](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#amend-local-fixes-into-the-right-commits) [Commit checkpoints after each completed turn](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#commit-checkpoints-after-each-completed-turn) [Create stacked pull requests](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#create-stacked-pull-requests) [Customize branch names](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#customize-branch-names) [Customize commit messages](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#customize-commit-messages) [Publish when you say "ship it"](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#publish-when-you-say-ship-it) [Land onto the target instead of opening pull requests](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#land-onto-the-target-instead-of-opening-pull-requests) [Update from main automatically](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#update-from-main-automatically) [Open draft pull requests by default](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#open-draft-pull-requests-by-default) [Create a recovery point before large history edits](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#create-a-recovery-point-before-large-history-edits) [Split unrelated hunks](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior#split-unrelated-hunks) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/ai-agents/tuning-agent-behavior.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22ai-agents/tuning-agent-behavior%22) --- # CLI Overview | GitButler Docs CLI Overview ============ All about the command line version of the GitButler tool GitButler includes a command line interface for managing branches and commits from a terminal, script, or coding agent. This includes tooling for: * [managing stacked and parallel branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting) * [inspecting and diffing](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting) * [an operations log and restoration of older states](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log) * [editing commits](https://docs.gitbutler.com/commands/commands-overview#editing-commits) * [upstream management](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base) * [conflict resolution](https://docs.gitbutler.com/cli-guides/cli-tutorial/conflict-resolution) * [working with forges](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges) * [aliases and configuration](https://docs.gitbutler.com/cli-guides/cli-tutorial/configuration) * [an interactive terminal UI](https://docs.gitbutler.com/gitbutler-tui) All with a simple command line tool. [Quick Reference](https://docs.gitbutler.com/cli-overview#quick-reference) --------------------------------------------------------------------------- For the most commonly used commands, open the [GitButler CLI cheat sheet](https://docs.gitbutler.com/cli/cheat) . It is also available as a downloadable PDF. [Getting Started](https://docs.gitbutler.com/cli-overview#getting-started) --------------------------------------------------------------------------- Start with the [installation guide](https://docs.gitbutler.com/cli-guides/installation) , or browse the [command reference](https://docs.gitbutler.com/commands/commands-overview) . Last updated on 7/30/2026 [Previous\ \ Tuning agent behavior](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior) [Next\ \ GitButler TUI](https://docs.gitbutler.com/gitbutler-tui) ### On this page [Quick Reference](https://docs.gitbutler.com/cli-overview#quick-reference) [Getting Started](https://docs.gitbutler.com/cli-overview#getting-started) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-overview.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-overview%22) --- # Branching and committing | GitButler Docs GuidesCLI Tutorial Branching and committing ======================== Create branches, commit selected changes, and stack dependent work with the GitButler CLI. Now that your project is set up, you can create a branch and commit your first changes. [Create and commit on a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#create-and-commit-on-a-branch) ------------------------------------------------------------------------------------------------------------------------------------------ Start by inspecting the workspace: but status `but status` shows the uncommitted area, applied branches and stacks, and the commits that haven't landed in your target branch. If you have uncommitted changes and no branch yet, create the branch and commit in one command: but commit -b user-bookmarks -m "Add user bookmarks" The `-b` option selects the branch. If `user-bookmarks` doesn't exist, GitButler creates it. Because the command doesn't include any change IDs, it commits all uncommitted changes. If you omit `-m`, GitButler opens your configured editor for the commit message. In scripts, always pass `-m` or `--no-message` so the command doesn't wait for input. [Commit selected files or hunks](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#commit-selected-files-or-hunks) -------------------------------------------------------------------------------------------------------------------------------------------- Use `but diff` to get IDs for the changes you want to commit: but diff The first token on each file line is its ID. A hunk ID has the form `:`, such as `q3:5`. Pass the IDs as space-separated positional arguments: but commit -b user-bookmarks -m "Add bookmark model" q3 w7 That commits only changes `q3` and `w7`. The other changes stay uncommitted. To commit one hunk without committing the rest of its file: but commit -b user-bookmarks -m "Validate bookmark URLs" q3:5 Copy IDs from your current `but diff` output. Don't comma-separate IDs or use line ranges. [Work on parallel branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#work-on-parallel-branches) ---------------------------------------------------------------------------------------------------------------------------------- Parallel branches hold independent work in the same workspace. Suppose `user-bookmarks` is applied and you start an unrelated `liked-tweets` change. Inspect the new changes, then commit them to another branch: but diff but commit -b liked-tweets -m "Add liked tweets" n2 p8 GitButler creates `liked-tweets` alongside `user-bookmarks`. Run `but status` to see both branches: but status When more than one independent stack is applied, always use `-b`, `--above`, or `--below` to say where a commit belongs. GitButler refuses an untargeted commit when the destination is ambiguous. [Stack dependent branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#stack-dependent-branches) -------------------------------------------------------------------------------------------------------------------------------- If the `liked-tweets` work turns out to depend on `user-bookmarks`, move that branch above `user-bookmarks` to turn the two parallel branches into a stack: but move liked-tweets --above user-bookmarks Once you've authenticated with `but config forge auth`, publish the stack from its top branch: but pr new liked-tweets -t GitButler pushes the stack and creates the missing reviews from the bottom upward. See [Create stacked branches and pull requests](https://docs.gitbutler.com/features/branch-management/stacked-branches) for the full stacked-review workflow. Last updated on [Previous\ \ Initializing a Repository](https://docs.gitbutler.com/cli-guides/cli-tutorial/initializing-a-repository) [Next\ \ Inspecting changes and branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting) ### On this page [Create and commit on a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#create-and-commit-on-a-branch) [Commit selected files or hunks](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#commit-selected-files-or-hunks) [Work on parallel branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#work-on-parallel-branches) [Stack dependent branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting#stack-dependent-branches) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/branching-and-commiting.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/branching-and-commiting%22) --- # Branches Page | GitButler Docs FeaturesBranch Management Branches Page ============= Manage parallel branches, remote branches, and workspace targets in GitButler's branch management interface. 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: ![The branch tab](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fbranch-tab.png&w=3840&q=75) The branch tab [Branch List](https://docs.gitbutler.com/features/branch-management/branch-lanes#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](https://docs.gitbutler.com/features/branch-management/branch-lanes#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. ![workspace-target.png](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fworkspace-target.png&w=3840&q=75) workspace-target.png Last updated on [Previous\ \ Commit Editing](https://docs.gitbutler.com/features/branch-management/commits) [Next\ \ Rules](https://docs.gitbutler.com/features/branch-management/rules) ### On this page [Branch List](https://docs.gitbutler.com/features/branch-management/branch-lanes#branch-list) [Current Workspace Target](https://docs.gitbutler.com/features/branch-management/branch-lanes#current-workspace-target) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/branch-lanes.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/branch-lanes%22) --- # Commit Editing | GitButler Docs FeaturesBranch Management Commit Editing ============== Master commit editing in GitButler with drag-and-drop operations for creating, modifying, squashing, and splitting commits. GitButler gives you a lot of tooling for creating, modifying, squashing, splitting and undoing commits. GitButler has lots of ways to craft the exact commits that you want to end up with. With other Git clients, you tend to have to run somewhat complicated `git rebase -i` type commands to change commit messages, split a commit up or absorb new changes into an existing commit. With GitButler, most of these are simply drag-and-drop operations. Here are some of the cool things you can do very easily with GitButler. [Creating Commits](https://docs.gitbutler.com/features/branch-management/commits#creating-commits) --------------------------------------------------------------------------------------------------- Once you have changes on a virtual branch and want to commit them, you can hit the "Start a Commit" button in any lane, which gives you an editor to write a summary and optional description for your commit message. ![Crafting a commit message with our advanced floating mode editor](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fcommit-edit.png&w=3840&q=75) Crafting a commit message with our advanced floating mode editor If you want AI to use your diff to generate a commit message, you can hit the "Generate message" button. [AI Commit Message Settings](https://docs.gitbutler.com/features/branch-management/commits#ai-commit-message-settings) ----------------------------------------------------------------------------------------------------------------------- If you want to use AI for generating your commit messages or branch names from time to time, there are quite a few options in your user preferences. You can choose from [OpenAI](https://platform.openai.com/) , [Anthropic](https://www.anthropic.com/) , [Ollama](https://www.ollama.com/) or [LM Studio](https://lmstudio.ai/) as your engine. For both OpenAI and Anthropic, you can either use your own API key to directly send your request to their servers, or you can proxy via our server (which you need to be logged in for). ![AI Commit Settings](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcommits-02.c7a6b56f.png&w=3840&q=75) If you use your own key for OpenAI or Anthropic, you can choose which model you would like us to use. ![AI Commit Settings](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcommits-03.c3ee4f62.png&w=3840&q=75) If you don't want to send your diff to another server, you can also use Ollama or LM Studio, which are a local LLM servers. With Ollama, you can run nearly any open source large language model ([Llama 3](https://www.ollama.com/library/llama3) , [Phi 3](https://www.ollama.com/library/phi3) , [Mistral](https://www.ollama.com/library/mistral) , [Gemma](https://www.ollama.com/library/gemma) , etc) entirely locally. Note that if you choose to configure a self-hosted Ollama server, you will likely need to add 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)](https://docs.gitbutler.com/troubleshooting/custom-csp) section of the documentation. With all of these models, you can also customize the prompt if you want something more specific. In the "Custom AI prompts" section, you can add new prompts and select which one you want to use per project. This is useful for following certain formats or generating messages in other languages, etc. ![AI Commit Settings](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcommits-04.a54b7ce6.png&w=3840&q=75) Custom prompts can contain three variables which we will replace with the appropriate values. Those include: * `%{emoji_style}` - Instructs the LLM whether or not to make use of [GitMoji](https://gitmoji.dev/) in the title prefix, based on your settings. * `%{brief_style}` - Instructs the LLM to not exceed 1 sentence when generating the commit message. * `%{diff}` - The contents of the diff. * `%{branch_name}` - The name of the current branch. Available in "Commit Message" custom prompt only. [Absorbing New Work](https://docs.gitbutler.com/features/branch-management/commits#absorbing-new-work) ------------------------------------------------------------------------------------------------------- If you have a commit and get some feedback on it or find an issue and wish to amend it, you can very easily absorb changes into existing commits. Simply drag the file into the commit you want to absorb that change into and drop it there. This will both rewrite that commit to include the new changes and also rebase every commit upstream from it automatically. ![Assigning work on a file to a lane, then into an existing commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fabsorb-work.gif&w=3840&q=75) Assigning work on a file to a lane, then into an existing commit [Undoing Commits](https://docs.gitbutler.com/features/branch-management/commits#undoing-commits) ------------------------------------------------------------------------------------------------- You can easily undo any commit in your stack by expanding the commit and hitting the 'Undo' button. This will rebase all the commits above it and leave whatever work was in that commit as new uncommitted changes. "Undo"ing a commit does not throw it away, it simply makes that work not in a commit anymore. It will not discard the changes. ![Undoing a commit in GitButler](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fundoing-commits.gif&w=3840&q=75) Undoing a commit in GitButler [Undoing One File in a Commit](https://docs.gitbutler.com/features/branch-management/commits#undoing-one-file-in-a-commit) --------------------------------------------------------------------------------------------------------------------------- If you want to undo a single file in a commit, you can expand the commit and click on the file you want to undo. Then hit "Uncommit". This will remove that file from the commit and leave it as uncommitted changes. ![Uncommitting a file, then adding it back into the commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fundoing-file-then-redoing.gif&w=3840&q=75) Uncommitting a file, then adding it back into the commit [Squashing Commits](https://docs.gitbutler.com/features/branch-management/commits#squashing-commits) ----------------------------------------------------------------------------------------------------- Squashing two commits into a single combined commit is also very simple. Just drag one commit on top of another one. ![Squash commits together by dragging and dropping](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fsquashing.gif&w=3840&q=75) Squash commits together by dragging and dropping [Splitting Commits](https://docs.gitbutler.com/features/branch-management/commits#splitting-commits) ----------------------------------------------------------------------------------------------------- Splitting commits is slightly more complex. GitButler allows you to create an "empty" commit anywhere and then drag changes into it. Here is an example of creating an empty commit between two other commits, dragging changes from both of them into it and then absorbing new work into it as well. ![Splitting commits by adding an empty commit and dragging changes into it](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fsplitting.gif&w=3840&q=75) Splitting commits by adding an empty commit and dragging changes into it You can also notice that I easily edit the commit message by just hitting the "edit message" button. [Moving Commits](https://docs.gitbutler.com/features/branch-management/commits#moving-commits) ----------------------------------------------------------------------------------------------- You can also arbitrarily change the order of your commits by dragging and dropping them, which rebases everything to change the order. ![Reordering commits in a branch](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Freorder.gif&w=3840&q=75) Reordering commits in a branch [Edit Mode](https://docs.gitbutler.com/features/branch-management/commits#edit-mode) ------------------------------------------------------------------------------------- The other way that you can modify a commit is to go into "Edit Mode". When you click on a commit, there is a button that says "Edit commit". If you click this, GitButler will check out that commit by itself into your working directory (automatically stashing everything else temporarily). The screen will go into "Edit mode", indicating that you're in a special state where you're focusing on this one commit. ![Going into edit mode to directly edit the state of a commit](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fedit-mode.gif&w=3840&q=75) Going into edit mode to directly edit the state of a commit Then you can change whatever you want and when you click "Save and exit", it will amend the commit you were editing and rebase anything on top of it. 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. Last updated on [Previous\ \ Create stacked branches and pull requests](https://docs.gitbutler.com/features/branch-management/stacked-branches) [Next\ \ Branches Page](https://docs.gitbutler.com/features/branch-management/branch-lanes) ### On this page [Creating Commits](https://docs.gitbutler.com/features/branch-management/commits#creating-commits) [AI Commit Message Settings](https://docs.gitbutler.com/features/branch-management/commits#ai-commit-message-settings) [Absorbing New Work](https://docs.gitbutler.com/features/branch-management/commits#absorbing-new-work) [Undoing Commits](https://docs.gitbutler.com/features/branch-management/commits#undoing-commits) [Undoing One File in a Commit](https://docs.gitbutler.com/features/branch-management/commits#undoing-one-file-in-a-commit) [Squashing Commits](https://docs.gitbutler.com/features/branch-management/commits#squashing-commits) [Splitting Commits](https://docs.gitbutler.com/features/branch-management/commits#splitting-commits) [Moving Commits](https://docs.gitbutler.com/features/branch-management/commits#moving-commits) [Edit Mode](https://docs.gitbutler.com/features/branch-management/commits#edit-mode) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/commits.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/commits%22) --- # Create stacked branches and pull requests | GitButler Docs FeaturesBranch Management Create stacked branches and pull requests ========================================= Split dependent work into branches, publish focused reviews, and keep the stack in sync. Use a stack when one change depends on another but each change still deserves its own review. GitButler keeps every branch in the same workspace and publishes each branch as a focused pull request. ![Two dependent GitButler branches published as separate pull requests](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2F0_concepts.5ae94c5d.jpg&w=3840&q=75) The branch closest to your target branch is the **bottom** of the stack. Work that depends on it goes above it. [Create a local stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#create-a-local-stack) -------------------------------------------------------------------------------------------------------------------- In GitButler Desktop: 1. Create the bottom branch and commit the first reviewable change. 2. On that branch, click the **Create new branch** stack icon. 3. Name the dependent branch and commit the next change to it. 4. Repeat for each dependent change. New commits go to the top branch unless you select a different branch first. You can also [move existing branches between stacks](https://docs.gitbutler.com/features/branch-management/moving-branches) or drag commits to the branch where they belong. To stack two existing branches with the CLI, put the dependent branch above its dependency: but move checkout-ui --above checkout-api [Publish the pull request stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#publish-the-pull-request-stack) ---------------------------------------------------------------------------------------------------------------------------------------- Connect your forge account before publishing. For GitHub, see [Connect GitButler to GitHub](https://docs.gitbutler.com/features/forge-integration/github-integration) . In Desktop, create pull requests from the bottom branch upward. If you try to create one above a lower branch that has no pull request yet, GitButler warns you that the lower pull request provides its review base. With the CLI, name the top branch to publish missing pull requests for the whole stack. This example uses `-t` to accept the default titles and descriptions without prompting: but pr new checkout-ui -t GitButler pushes the branches and sets the pull request bases: * The bottom pull request targets the repository's target branch, usually `main`. * Every pull request above it targets the nearest branch below it that also has a pull request. That keeps each pull request's **Files changed** view limited to the change being reviewed. [Choose how the stack is published](https://docs.gitbutler.com/features/branch-management/stacked-branches#choose-how-the-stack-is-published) ---------------------------------------------------------------------------------------------------------------------------------------------- GitButler publishes stacks as native GitHub stacked pull requests when the repository supports them. Otherwise, it uses ordinary pull requests or merge requests with GitButler-managed stack information in their descriptions. The default GitHub mode, **Auto**, uses native stacks when available and falls back otherwise. To require or disable native stacks, see [Use native GitHub stacked pull requests](https://docs.gitbutler.com/features/forge-integration/github-integration#use-native-github-stacked-pull-requests) . [Update a published stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#update-a-published-stack) ---------------------------------------------------------------------------------------------------------------------------- Amend commits, move branches, or add another branch as the review changes. When you push again, GitButler updates the review bases to match the local branch order. It also synchronizes the native GitHub stack or the stack information in the review descriptions. [Merge the stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#merge-the-stack) ---------------------------------------------------------------------------------------------------------- For a native GitHub stack, use GitHub's stack controls. GitHub can merge a higher pull request together with the pull requests below it. For description-based stacks, merge from the bottom upward. Enable [automatic branch deletion 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) so GitHub can retarget the next pull request after its base branch lands. After merging, update the workspace from the target branch. In the CLI, run: but pull Last updated on [Previous\ \ Parallel Branches](https://docs.gitbutler.com/features/branch-management/virtual-branches) [Next\ \ Commit Editing](https://docs.gitbutler.com/features/branch-management/commits) ### On this page [Create a local stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#create-a-local-stack) [Publish the pull request stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#publish-the-pull-request-stack) [Choose how the stack is published](https://docs.gitbutler.com/features/branch-management/stacked-branches#choose-how-the-stack-is-published) [Update a published stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#update-a-published-stack) [Merge the stack](https://docs.gitbutler.com/features/branch-management/stacked-branches#merge-the-stack) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/stacked-branches.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/stacked-branches%22) --- # but oplog | GitButler Docs Commands \>\_ but oplog ========= Commands for viewing and managing operation history. Displays a list of past operations performed in the repository, including their timestamps and descriptions. This allows you to restore to any previous point in the history of the project. All state is preserved in operations, including uncommitted changes. You can use `but oplog restore ` to restore to a specific state. By default, shows the last 20 oplog entries (same as `but oplog list`). **Usage:** `but oplog ` [Subcommands](https://docs.gitbutler.com/commands/but-oplog#subcommands) ------------------------------------------------------------------------- ### [`but oplog list`](https://docs.gitbutler.com/commands/but-oplog#but-oplog-list) List operation history. Displays a list of past operations performed in the repository, including their timestamps and descriptions. This allows you to restore to any previous point in the history of the project. All state is preserved in operations, including uncommitted changes. You can use `but oplog restore ` to restore to a specific state. **Usage:** `but oplog list [OPTIONS]` **Options:** * `--since` `` — Start from this oplog SHA instead of the head * `-s`, `--snapshot` — Show only on-demand snapshot entries ### [`but oplog snapshot`](https://docs.gitbutler.com/commands/but-oplog#but-oplog-snapshot) Create an on-demand snapshot with optional message. This allows you to create a named snapshot of the current state, which can be helpful to always be able to return to a known good state. You can provide an optional message to describe the snapshot. **Usage:** `but oplog snapshot [OPTIONS]` **Options:** * `-m`, `--message` `` — Message to include with the snapshot ### [`but oplog restore`](https://docs.gitbutler.com/commands/but-oplog#but-oplog-restore) Restore to a specific oplog snapshot. This command allows you to revert the repository to a previous state captured in an oplog snapshot. You need to provide the SHA of the oplog entry you want to restore to, which you can find by running `but oplog` or `but oplog list`. **Usage:** `but oplog restore ` **Arguments:** * `` — Oplog SHA to restore to (required) Last updated on [Previous\ \ but move](https://docs.gitbutler.com/commands/but-move) [Next\ \ but undo](https://docs.gitbutler.com/commands/but-undo) ### On this page [Subcommands](https://docs.gitbutler.com/commands/but-oplog#subcommands) [`but oplog list`](https://docs.gitbutler.com/commands/but-oplog#but-oplog-list) [`but oplog snapshot`](https://docs.gitbutler.com/commands/but-oplog#but-oplog-snapshot) [`but oplog restore`](https://docs.gitbutler.com/commands/but-oplog#but-oplog-restore) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-oplog.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-oplog%22) --- # but undo | GitButler Docs Commands \>\_ but undo ======== Undo the last operation. **Usage:** `but undo` Last updated on [Previous\ \ but oplog](https://docs.gitbutler.com/commands/but-oplog) [Next\ \ but redo](https://docs.gitbutler.com/commands/but-redo) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-undo.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-undo%22) --- # Installation and Setup | GitButler Docs Guides Installation and Setup ====================== Installation and setup guide for the GitButler CLI tool. How to install and setup the GitButler CLI. [Installing the `but` CLI](https://docs.gitbutler.com/cli-guides/installation#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](https://docs.gitbutler.com/cli-guides/installation#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. ![How to install the GitButler CLI](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Finstall-but.png&w=3840&q=75) How to install the GitButler CLI ### [Curl install](https://docs.gitbutler.com/cli-guides/installation#curl-install) You can install the CLI by running the following command in your terminal: curl -fsSL https://gitbutler.com/install.sh | sh [Setup](https://docs.gitbutler.com/cli-guides/installation#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. Last updated on [Previous\ \ GitButler TUI](https://docs.gitbutler.com/gitbutler-tui) [Next\ \ Workflow Overview](https://docs.gitbutler.com/cli-guides/cli-tutorial/tutorial-overview) ### On this page [Installing the `but` CLI](https://docs.gitbutler.com/cli-guides/installation#installing-the-but-cli) [Via the Desktop Client](https://docs.gitbutler.com/cli-guides/installation#via-the-desktop-client) [Curl install](https://docs.gitbutler.com/cli-guides/installation#curl-install) [Setup](https://docs.gitbutler.com/cli-guides/installation#setup) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/installation.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/installation%22) --- # Supporters | GitButler Docs Community Supporters ========== Join GitButler's early supporter program for exclusive perks, Discord access, and locked-in pricing. 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](https://docs.gitbutler.com/community/supporters#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](https://docs.gitbutler.com/community/supporters#how-to-support-us) --------------------------------------------------------------------------------------- You need to have a GitButler account to support us. If you don't have one, sign up first. [### GitButler\ \ Support GitButler with a monthly contribution](https://gitbutler.com/profile) Thanks, from the GitButler Crew! ![](https://docs.gitbutler.com/img/pixel-bowtie.svg) Last updated on [Previous\ \ Open Source](https://docs.gitbutler.com/community/open-source) [Next\ \ Releases](https://docs.gitbutler.com/releases) ### On this page [Perks for Early Supporters](https://docs.gitbutler.com/community/supporters#perks-for-early-supporters) [How to Support Us](https://docs.gitbutler.com/community/supporters#how-to-support-us) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/community/supporters.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22community/supporters%22) --- # Gerrit Mode | GitButler Docs Features Gerrit Mode =========== Use Gerrit mode in GitButler to have a simple and powerful client for the Gerrit code review system 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](https://docs.gitbutler.com/features/gerrit-mode#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) : ![The Android project's Gerrit code review](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-10-17%2520at%252016.03.44%25402x.png&w=3840&q=75) The Android project's Gerrit code review [How is Gerrit different than Pull/Merge Requests?](https://docs.gitbutler.com/features/gerrit-mode#how-is-gerrit-different-than-pullmerge-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](https://docs.gitbutler.com/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](https://docs.gitbutler.com/features/gerrit-mode#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](https://docs.gitbutler.com/features/gerrit-mode#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. ![Gerrit Change numbers and URLs are shown and linked to](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-10-17%2520at%252016.21.06%25402x.png&w=3840&q=75) Gerrit Change numbers and URLs are shown and linked to 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) ![Set a topic, hashtag or wip status on push](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-10-17%2520at%252016.50.07%25402x.png&w=3840&q=75) Set a topic, hashtag or wip status on push Last updated on [Previous\ \ GitLab Integration](https://docs.gitbutler.com/features/forge-integration/gitlab-integration) [Next\ \ Custom Content Security Policy (CSP)](https://docs.gitbutler.com/troubleshooting/custom-csp) ### On this page [What is Gerrit](https://docs.gitbutler.com/features/gerrit-mode#what-is-gerrit) [How is Gerrit different than Pull/Merge Requests?](https://docs.gitbutler.com/features/gerrit-mode#how-is-gerrit-different-than-pullmerge-requests) [How to turn on Gerrit Mode](https://docs.gitbutler.com/features/gerrit-mode#how-to-turn-on-gerrit-mode) [What is Gerrit Mode](https://docs.gitbutler.com/features/gerrit-mode#what-is-gerrit-mode) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/gerrit-mode.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/gerrit-mode%22) --- # Contact Us | GitButler Docs Community Contact Us ========== Get in touch with the GitButler team through email or Discord for feedback, bug reports, and feature requests. There are a few ways to get in touch with us for feedback, bug reports, feature requests, etc. [### Email\ \ The simplest way to get in touch with us is to email us](mailto:hello@gitbutler.com) [### Discord\ \ We are also available to chat on our Discord server](https://discord.com/invite/MmFkmaJ42D) Last updated on [Previous\ \ Debugging](https://docs.gitbutler.com/development/debugging) [Next\ \ Open Source](https://docs.gitbutler.com/community/open-source) --- # GitButler CLI Cheat Sheet | GitButler Docs GitButler CLI Cheat Sheet ========================= Download PDF Essential commands for working with GitButler BasicAdvanced Use the GitButler CLI to inspect changes, manage parallel or stacked branches, edit commits, and publish your work. Setup and Teardown ------------------ Switching to and from GitButler branch management but setup Switch to GitButler in the current repository but teardown Go back to vanilla git branch management Branch Management ----------------- Create and manage parallel and stacked branches but branch List all branches available but branch new \[name\] Create a new parallel branch but branch new \[name\] --anchor \[branch\] Create a new stacked branch from an existing branch but apply \[branch\] Apply (enable) a branch to your working directory but unapply \[branch|id\] Unapply (disable) a branch from your working directory Remote Operations ----------------- Push changes and interact with forges but push \[branch\] Push one branch to its remote but pull Update the target and rebase all applied branches but pr new \[branch\] -t Push a branch or stack and create its reviews but config forge View and modify forge authentications Conflict Management ------------------- Resolve conflicts in commits but resolve \[commit\] Enter resolution mode for a conflicted commit Inspection ---------- View your workspace state and changes but status Show uncommitted changes, applied branches, and commits but status -fv Show committed files, IDs, authors, and timestamps but diff Show uncommitted changes and their file and hunk IDs but show \[id\] Show details for a commit or branch Committing Changes ------------------ Create commits on your branches but commit -b \[branch\] -m "\[message\]" Commit all uncommitted changes; create the branch if needed but commit -b \[branch\] -m "\[message\]" \[change-id\]... Commit selected files or hunks from but diff Operations Log -------------- View and restore workspace history but undo Undo the last operation but oplog Show operation history of workspace but oplog restore \[oplog-sha\] Restore workspace to a specific snapshot Helper Commands --------------- Open GitButler and configure terminal integrations but gui Open the GUI to the current project but alias Create and manage aliases for commonly used commands but config View and modify GitButler configuration settings GitButler CLI Cheat Sheet | GitButler Docs --- # Custom Content Security Policy (CSP) | GitButler Docs Troubleshooting Custom Content Security Policy (CSP) ==================================== Configure custom Content Security Policy settings to allow GitButler connections to self-hosted GitHub, GitLab, or Ollama instances. By default GitButler uses a strict Content Security Policy (CSP) to protect against various attacks, such as cross-site scripting (XSS) and data injection attacks. This policy restricts the sources from which content can be loaded, as well as the hosts the application can connect to, ensuring that only trusted sources are allowed. However, there are some cases where you may need to customize the CSP to allow certain features or integrations. Some examples include: * Self-hosted GitHub Enterprise instances * Self-hosted GitLab instances * Self-hosted Ollama instances In those cases you are likely to observe an error message that looks something like this: Refused to connect to https://./api/v4/projects/9/merge_requests because it does not appear in the connect-src directive of the Content Security Policy. You can resolve this issue by adding your host to the CSP. [Adding a Custom CSP](https://docs.gitbutler.com/troubleshooting/custom-csp#adding-a-custom-csp) ------------------------------------------------------------------------------------------------- You can add a custom CSP by editing the GitButler configuration file, found at the following location: macOSWindowsLinux ~/Library/Application\ Support/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) In order to add your custom CSP entry, you want to add an `extraCsp` entry to the JSON file. The `extraCsp` entry is an object that contains a `hosts` array, which is where you can add your custom hosts. For example: "extraCsp": { "hosts": ["https://subdomain.example.com", "http://another-subdomain.example.com"] } Note that if `extraCsp` is the only entry in the JSON file, you may want to enclose it in a top-level object, like this: { "extraCsp": { "hosts": ["https://subdomain.example.com", "http://another-subdomain.example.com"] } } The changes will take effect the next time you start GitButler. Last updated on [Previous\ \ Gerrit Mode](https://docs.gitbutler.com/features/gerrit-mode) [Next\ \ Fix fetch and push issues](https://docs.gitbutler.com/troubleshooting/fetch-push) ### On this page [Adding a Custom CSP](https://docs.gitbutler.com/troubleshooting/custom-csp#adding-a-custom-csp) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/troubleshooting/custom-csp.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22troubleshooting/custom-csp%22) --- # Rules | GitButler Docs FeaturesBranch Management Rules ===== Automate change assignment with rules that match file patterns and automatically route changes to the right branch. 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](https://docs.gitbutler.com/features/branch-management/rules#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](https://docs.gitbutler.com/features/branch-management/rules#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](https://docs.gitbutler.com/features/branch-management/rules#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. Your browser does not support the video tag. Creating a rule that assigns changes to the leftmost lane [Filter Types](https://docs.gitbutler.com/features/branch-management/rules#filter-types) ----------------------------------------------------------------------------------------- Rules support filters that match file paths or changed line content. ### [Path Matches Regex](https://docs.gitbutler.com/features/branch-management/rules#path-matches-regex) Matches file paths using a regular expression pattern. **Example use cases:** * Match all TypeScript files: `.*\.ts$` * Match files in a specific directory: `^src/components/.*` * Match documentation files: `.*\.(md|mdx)$` ### [Content Matches Regex](https://docs.gitbutler.com/features/branch-management/rules#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). **Example use cases:** * Match changes containing TODOs: `TODO` * Match changes with specific function calls: `console\.log` * Match changes with certain patterns: `@deprecated` Your browser does not support the video tag. Creating a rule that assigns changes containing "fix" to a specific branch [Managing Rules](https://docs.gitbutler.com/features/branch-management/rules#managing-rules) --------------------------------------------------------------------------------------------- ### [Editing Rules](https://docs.gitbutler.com/features/branch-management/rules#editing-rules) To edit an existing 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** ### [Deleting Rules](https://docs.gitbutler.com/features/branch-management/rules#deleting-rules) To delete a rule: 1. Click the ellipsis menu (...) on the rule 2. Select "Delete rule" 3. Confirm the deletion [Understanding Rule Evaluation](https://docs.gitbutler.com/features/branch-management/rules#understanding-rule-evaluation) --------------------------------------------------------------------------------------------------------------------------- ### [Order Matters](https://docs.gitbutler.com/features/branch-management/rules#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. ### [AND Logic Within Rules](https://docs.gitbutler.com/features/branch-management/rules#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. ### [OR Logic Across Rules](https://docs.gitbutler.com/features/branch-management/rules#or-logic-across-rules) If you want to match changes that meet any of several conditions (OR logic), create separate rules for each condition. ### [Interaction with Hunk Dependencies](https://docs.gitbutler.com/features/branch-management/rules#interaction-with-hunk-dependencies) 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](https://docs.gitbutler.com/features/branch-management/rules#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 [Limitations](https://docs.gitbutler.com/features/branch-management/rules#limitations) --------------------------------------------------------------------------------------- * Rules can only assign changes to branches that exist in your workspace (applied branches) * Rules currently only support the `assign` action for filesystem changes [Related Features](https://docs.gitbutler.com/features/branch-management/rules#related-features) ------------------------------------------------------------------------------------------------- * [Parallel Branches](https://docs.gitbutler.com/features/branch-management/virtual-branches) : Understanding the branch system that rules work with * [Branch Lanes](https://docs.gitbutler.com/features/branch-management/branch-lanes) : How lanes are organized and how rules interact with lane positioning Last updated on [Previous\ \ Branches Page](https://docs.gitbutler.com/features/branch-management/branch-lanes) [Next\ \ Move branches between stacks](https://docs.gitbutler.com/features/branch-management/moving-branches) ### On this page [Overview](https://docs.gitbutler.com/features/branch-management/rules#overview) [How Rules Work](https://docs.gitbutler.com/features/branch-management/rules#how-rules-work) [Creating a Rule](https://docs.gitbutler.com/features/branch-management/rules#creating-a-rule) [Filter Types](https://docs.gitbutler.com/features/branch-management/rules#filter-types) [Path Matches Regex](https://docs.gitbutler.com/features/branch-management/rules#path-matches-regex) [Content Matches Regex](https://docs.gitbutler.com/features/branch-management/rules#content-matches-regex) [Managing Rules](https://docs.gitbutler.com/features/branch-management/rules#managing-rules) [Editing Rules](https://docs.gitbutler.com/features/branch-management/rules#editing-rules) [Deleting Rules](https://docs.gitbutler.com/features/branch-management/rules#deleting-rules) [Understanding Rule Evaluation](https://docs.gitbutler.com/features/branch-management/rules#understanding-rule-evaluation) [Order Matters](https://docs.gitbutler.com/features/branch-management/rules#order-matters) [AND Logic Within Rules](https://docs.gitbutler.com/features/branch-management/rules#and-logic-within-rules) [OR Logic Across Rules](https://docs.gitbutler.com/features/branch-management/rules#or-logic-across-rules) [Interaction with Hunk Dependencies](https://docs.gitbutler.com/features/branch-management/rules#interaction-with-hunk-dependencies) [Best Practices](https://docs.gitbutler.com/features/branch-management/rules#best-practices) [Limitations](https://docs.gitbutler.com/features/branch-management/rules#limitations) [Related Features](https://docs.gitbutler.com/features/branch-management/rules#related-features) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/rules.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/rules%22) --- # Connect GitButler to GitHub | GitButler Docs FeaturesForge Integrations Connect GitButler to GitHub =========================== Connect GitHub accounts to create pull requests and keep branch stacks in sync from GitButler. Connect GitButler to a GitHub account to create and manage pull requests without leaving the app. You can connect multiple GitHub accounts and choose which one each project uses. [Connect a GitHub account](https://docs.gitbutler.com/features/forge-integration/github-integration#connect-a-github-account) ------------------------------------------------------------------------------------------------------------------------------ Open GitButler settings from the profile button in the sidebar. Go to **Integrations**, then click **Add account** for GitHub. ![GitHub authentication via the Integrations settings tab](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-1.png&w=3840&q=75) GitHub authentication via the Integrations settings tab You can add an account three ways: * **Device Flow** generates a code and opens GitHub in your browser for authorization. This is the recommended option for most users. * **Personal Access Token** connects an account with a token you create on GitHub. * **GitHub Enterprise** connects to an Enterprise instance with its API URL and a personal access token. We'll select the **Device Flow** option for this example. ![Generated code for GitHub authentication](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-2.png&w=3840&q=75) Generated code for GitHub authentication A code will be generated for you. Copy it to your clipboard. ![URL to authorize GitHub integration](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-3.png&w=3840&q=75) URL to authorize GitHub integration Click **Open GitHub activation page** to continue in your browser. ![Enter the device code on GitHub](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fgithub-auth.png&w=3840&q=75) Enter the device code on GitHub Paste the code into GitHub and approve the authorization request. ![Button to check authorization status](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-4.png&w=3840&q=75) Button to check authorization status Return to GitButler and click **Check the status**. Your GitHub username appears in the Integrations tab after the account connects. ![GitHub account connected successfully](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-5.png&w=3840&q=75) GitHub account connected successfully To disconnect an account, click **Forget** next to its name. ![Add a GitHub account via Personal Access Token](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-6.png&w=3840&q=75) Add a GitHub account via Personal Access Token To connect with a personal access token, select **Personal Access Token** when adding the account. GitButler needs read access to **Metadata** and read and write access to **Pull Requests**. These requirements may change as GitButler adds GitHub features. ![Add a GitHub Enterprise account via Personal Access Token](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2F2025-10-30-github-setup-7.png&w=3840&q=75) Add a GitHub Enterprise account via Personal Access Token For GitHub Enterprise, select **GitHub Enterprise** and enter the instance's API base URL and a personal access token with the same permissions. 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. [Create and manage pull requests](https://docs.gitbutler.com/features/forge-integration/github-integration#create-and-manage-pull-requests) -------------------------------------------------------------------------------------------------------------------------------------------- After connecting GitHub, create a pull request from its GitButler branch. ![Create a pull request from a GitButler branch](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2Fcreate-pr.png&w=3840&q=75) Create a pull request from a GitButler branch GitButler checks whether each branch has an associated pull request. You can view those pull requests from the **Pull Requests** section of the Branches page. [Use native GitHub stacked pull requests](https://docs.gitbutler.com/features/forge-integration/github-integration#use-native-github-stacked-pull-requests) ------------------------------------------------------------------------------------------------------------------------------------------------------------ GitButler uses native GitHub stacked pull requests when: * The repository is enrolled in GitHub's stacked pull requests private preview. * The pull requests use branches in the same repository, not a fork. * The project has not disabled native stacks. The default mode is **Auto**. GitButler detects whether the repository supports native stacks and registers stacks containing at least two open pull requests. GitHub renders the stack, so GitButler does not add stack information to the pull request descriptions. If the repository is not enrolled, Auto falls back to ordinary pull requests with GitButler-managed stack information in their descriptions. Fork-backed pull requests always use this fallback. Change the mode under **Project settings → Project → Native GitHub stacked pull requests**: * **Auto** uses native stacks when available and falls back otherwise. * **Native** requires native stack support and reports an error when the repository is not enrolled. * **Disabled** always uses description-based stack information. The **Stack information in review descriptions** setting controls whether fallback information appears at the top, bottom, or not at all. It does not affect native stacks. The same project-local setting is available in the CLI: but config forge github-stacks auto but config forge github-stacks enable but config forge github-stacks disable The CLI values map to Desktop as follows: * `auto` selects **Auto**. * `enable` selects **Native**. * `disable` selects **Disabled**. Changes take effect on the next push or pull request creation. GitButler then updates the pull request bases and either the native stack membership or the fallback descriptions. See [Create stacked branches and pull requests](https://docs.gitbutler.com/features/branch-management/stacked-branches) for the publishing workflow. Last updated on [Previous\ \ Operations History](https://docs.gitbutler.com/features/timeline) [Next\ \ GitLab Integration](https://docs.gitbutler.com/features/forge-integration/gitlab-integration) ### On this page [Connect a GitHub account](https://docs.gitbutler.com/features/forge-integration/github-integration#connect-a-github-account) [Create and manage pull requests](https://docs.gitbutler.com/features/forge-integration/github-integration#create-and-manage-pull-requests) [Use native GitHub stacked pull requests](https://docs.gitbutler.com/features/forge-integration/github-integration#use-native-github-stacked-pull-requests) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/forge-integration/github-integration.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/forge-integration/github-integration%22) --- # Push and fetch | GitButler Docs FeaturesBranch Management Push and fetch ============== Use your system Git authentication to push and fetch, or land branches directly onto the target branch without pull requests. GitButler uses your system Git executable to authenticate with your remote. This means it uses the same SSH configuration, SSH agent, or [credential helper](https://git-scm.com/doc/credential-helpers) as Git in your terminal. Open your project settings, go to the Git section, and select **Test credentials** to verify that GitButler can push to the remote. The test pushes an existing commit to a temporary remote branch and removes the branch after the check. If the test fails, configure authentication for your system Git first, then run the test again. GitButler no longer has separate settings for selecting an SSH key or credential helper. Once authentication works, GitButler can automatically fetch upstream work and push new branches to your remote. [Land branches without pull requests](https://docs.gitbutler.com/features/branch-management/pushing-and-fetching#land-branches-without-pull-requests) ------------------------------------------------------------------------------------------------------------------------------------------------------ If your project does not review changes through pull requests, you can switch a project to the "push to main" workflow. During repository onboarding, check "Push to main / Skip pull requests mode". For an existing project, open the project settings, go to the Git section, and turn on "Land branches directly". With this on, the "Create PR" button on the bottom branch of a stack becomes a "Land" button. Landing integrates the branch straight into the target branch — fast-forwarding when possible, otherwise with a merge commit — and pushes the result. It works without a forge integration. Landing bypasses code review, CI checks, and branch protection, and a branch protected against direct pushes will reject it. The CLI equivalent is [`but land`](https://docs.gitbutler.com/commands/but-land) . Last updated on [Previous\ \ Move branches between stacks](https://docs.gitbutler.com/features/branch-management/moving-branches) [Next\ \ Rebasing and Conflicts](https://docs.gitbutler.com/features/branch-management/merging) ### On this page [Land branches without pull requests](https://docs.gitbutler.com/features/branch-management/pushing-and-fetching#land-branches-without-pull-requests) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/pushing-and-fetching.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/pushing-and-fetching%22) --- # Move branches between stacks | GitButler Docs FeaturesBranch Management Move branches between stacks ============================ Change branch dependencies by moving branches between stacks or tearing them off into new stacks. You can drag a branch from one stack to another to change what it depends on. You can also tear a branch off into an independent stack. [Move a branch to another stack](https://docs.gitbutler.com/features/branch-management/moving-branches#move-a-branch-to-another-stack) --------------------------------------------------------------------------------------------------------------------------------------- Drag the branch to the position where it belongs in the target stack: 1. **Drag the branch header** - Click and hold on the branch header (the section displaying the branch name) 2. **Drop on target location** - Drag it to the position where you want to insert it in another stack When you hover over a valid drop target during the drag operation, you'll see visual indicators showing where the branch will be placed. Your browser does not support the video tag. ### [Drop zones](https://docs.gitbutler.com/features/branch-management/moving-branches#drop-zones) There are two types of drop zones when moving branches: * **Between branches** - Drop the branch between two existing branches in a stack to insert it at that position * **Top of stack** - Drop at the top of a stack to make the moved branch the first branch The drop zones appear as horizontal lines with visual feedback when you hover over them during a drag operation. [Tear a branch off into a new stack](https://docs.gitbutler.com/features/branch-management/moving-branches#tear-a-branch-off-into-a-new-stack) ----------------------------------------------------------------------------------------------------------------------------------------------- You can also separate a branch from its current stack and create a new independent stack for it. This is called "tearing off" a branch. ### [Tear off a branch](https://docs.gitbutler.com/features/branch-management/moving-branches#tear-off-a-branch) 1. **Drag the branch header** - Click and hold on the branch header you want to separate 2. **Drop outside the stacks area** - Drag it to the designated dropzone outside of the existing stacks This creates a new standalone stack containing only that branch. Your browser does not support the video tag. [Requirements](https://docs.gitbutler.com/features/branch-management/moving-branches#requirements) --------------------------------------------------------------------------------------------------- Not all branches can be moved. A branch must meet these conditions to be movable: * **No conflicts** - The branch must not have any merge conflicts * **Has commits** - The branch must contain at least one commit * **Different target stack** - You can only move branches to different stacks (not within the same stack) ### [What happens during a move](https://docs.gitbutler.com/features/branch-management/moving-branches#what-happens-during-a-move) When you move a branch: 1. **Branch is extracted** - The branch and its commits are extracted from the source stack 2. **Rebasing occurs** - The branch is rebased onto the new base in the target stack 3. **References updated** - Git references are updated to reflect the new structure 4. **Stack cleanup** - If the moved branch was the last one in its stack, that stack is deleted ### [Pull request updates](https://docs.gitbutler.com/features/branch-management/moving-branches#pull-request-updates) If the branch has an associated pull request or merge request: * **Pull request bases** - Each pull request targets the nearest branch below it that also has a pull request * **GitHub stack membership** - GitButler updates the native stack on GitHub to match the new branch order * **Description-based stacks** - Repositories without native stack support get updated stack information in their pull request descriptions The synchronization runs on the next push or pull request creation. [Related features](https://docs.gitbutler.com/features/branch-management/moving-branches#related-features) ----------------------------------------------------------------------------------------------------------- * [Create stacked branches and pull requests](https://docs.gitbutler.com/features/branch-management/stacked-branches) * [Use the Branches page](https://docs.gitbutler.com/features/branch-management/branch-lanes) * [Work with parallel branches](https://docs.gitbutler.com/features/branch-management/virtual-branches) Last updated on [Previous\ \ Rules](https://docs.gitbutler.com/features/branch-management/rules) [Next\ \ Push and fetch](https://docs.gitbutler.com/features/branch-management/pushing-and-fetching) ### On this page [Move a branch to another stack](https://docs.gitbutler.com/features/branch-management/moving-branches#move-a-branch-to-another-stack) [Drop zones](https://docs.gitbutler.com/features/branch-management/moving-branches#drop-zones) [Tear a branch off into a new stack](https://docs.gitbutler.com/features/branch-management/moving-branches#tear-a-branch-off-into-a-new-stack) [Tear off a branch](https://docs.gitbutler.com/features/branch-management/moving-branches#tear-off-a-branch) [Requirements](https://docs.gitbutler.com/features/branch-management/moving-branches#requirements) [What happens during a move](https://docs.gitbutler.com/features/branch-management/moving-branches#what-happens-during-a-move) [Pull request updates](https://docs.gitbutler.com/features/branch-management/moving-branches#pull-request-updates) [Related features](https://docs.gitbutler.com/features/branch-management/moving-branches#related-features) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/moving-branches.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/moving-branches%22) --- # Workflow Overview | GitButler Docs GuidesCLI Tutorial Workflow Overview ================= What is a semi-normal CLI based workflow with GitButler 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. Last updated on [Previous\ \ Installation and Setup](https://docs.gitbutler.com/cli-guides/installation) [Next\ \ Initializing a Repository](https://docs.gitbutler.com/cli-guides/cli-tutorial/initializing-a-repository) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/tutorial-overview.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/tutorial-overview%22) --- # Configuration and Aliases | GitButler Docs GuidesCLI Tutorial Configuration and Aliases ========================= How to customize your GitButler CLI experience 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. $ but config user **User Configuration**: Name: Scott Chacon (global) Email: schacon@gmail.com (global) Editor: nvim (global) To set values: but config user set name "Your Name" but config user set --global email your@email.com [Aliases](https://docs.gitbutler.com/cli-guides/cli-tutorial/configuration#aliases) ------------------------------------------------------------------------------------ GitButler also has a built in aliasing system in case you want to provide some shorthands. $ but alias **User aliases**: stf → status -f (local) stfu → status -f -u (local) **Default aliases** (overridable): default → status st → status stf → status --files (overridden) 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. Last updated on [Previous\ \ Push branches and create reviews](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges) [Next\ \ Working with AI](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff) ### On this page [Aliases](https://docs.gitbutler.com/cli-guides/cli-tutorial/configuration#aliases) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/configuration.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/configuration%22) --- # Signing Commits | GitButler Docs FeaturesBranch Management Signing Commits =============== Configure commit signing in GitButler using GPG or SSH keys for verified commits on GitHub and GitLab. GitHub and GitLab provide a mechanism to verify signed commits using an uploaded public SSH or GPG key. GitButler can be configured automatically sign all your commits. Git provides a mechanism to sign your commits with a GPG key or SSH key. This enables other developers to make sure that you were actually the person who committed it, rather than someone else just setting their email to yours and committing it as if they were you. To make this work, a signature is added to the commit header and then that signature is checked against public key stored somewhere, generally for most people the most useful way to verify these signatures is through GitHub or GitLab. This is what a verified commit looks like on both systems: ![Viewing Remote Branches](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsigning-01.cc59dad9.png&w=3840&q=75) A verified commit on GitLab. ![Viewing Remote Branches](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsigning-02.62c1b310.png&w=3840&q=75) Verified and non-verified commits on GitHub. This means that the server has a public key that you used to sign the commits that is associated to your account and has verified that this user actually signed this commit. In order for this to work, you need to: 1. Tell GitButler to sign your commits 2. Upload your key as a "signing key" to GitHub or GitLab (or elsewhere) [Telling GitButler to Sign](https://docs.gitbutler.com/features/branch-management/signing-commits#telling-gitbutler-to-sign) ----------------------------------------------------------------------------------------------------------------------------- For GitButler to sign commits, you need to setup Git to sign commits, as we do roughly the same thing that Git itself tries to do, and we read and respect most of the same Git config settings. The main difference is that instead of only the `commit.gpgSign` as the flag that tells Git to automatically sign commits, we look for `gitbutler.signCommits` first. Thus, if Git would sign, GitButler will attempt to sign your commits with the normal Git settings as well. But if something goes wrong, `gitbutler.signCommits` will be set to `false` in the repository-local settings to prevent commits from failing generally. Set `gitbutler.signCommits` to `true` in your user-level `~/.gitconfig`, to prevent GitButler from automatically disabling commit signing for that repository. We look to see if we have a signing key in `user.signingkey`. If we have a key, we look for 'ssh' in `gpg.format`, otherwise we use GPG. We will respect `gpg.ssh.program` for ssh if there is a different binary path, and `gpg.program` for GPG. We also identify literal SSH keys in the `user.signingkey` field. The only major thing we don't support yet is `gpg.ssh.defaultKeyCommand` for other ways to get a key other than the `user.signingkey` field. We also don't support the X.509 smime stuff. Here is an example, if you have a public key here `.ssh/id_ed25519.pub` then you can setup signing with something like this: Terminal $ git config --global user.signingkey "/Users/schacon/.ssh/id_ed25519.pub" $ git config --global gpg.format ssh $ git config --global gitbutler.signCommits true You can also set this up in your project settings, perhaps a little more easily: ![Viewing Remote Branches](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsigning-03.3775e1ac.png&w=3840&q=75) The nice thing here is that you can also test the settings easily by hitting the "Test Signing" button. There are lots of other ways to set up GPG or SSH commit signing: * 1Password is a very easy way to [SSH sign commits](https://blog.1password.com/git-commit-signing/) . * GitHub has a [good guide](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key) on how to setup GPG or SSH keysigning. * Here is a nice simple gist for [GPG signing on Windows](https://gist.github.com/BoGnY/f9b1be6393234537c3e247f33e74094a) . Using GitButler's Generated SSH Key Earlier versions of GitButler would only sign with its generated SSH key. Although we've removed that functionality, you can easily set it back up by pointing the signingKey at the generated SSH Key. The key is located in the following locations: macOSWindowsLinux /Users/[username]/Library/Application Support/com.gitbutler.app/keys/ed25519.pub [Upload Your Signing Key](https://docs.gitbutler.com/features/branch-management/signing-commits#upload-your-signing-key) ------------------------------------------------------------------------------------------------------------------------- For GitHub or GitLab to verify your signatures, you need to say that the SSH or GPG public key we are using is a valid signing key for your user. ### [Adding to GitHub](https://docs.gitbutler.com/features/branch-management/signing-commits#adding-to-github) You can click on the "Add key to GitHub" link in the settings page right about the signing toggle, or you can go here ([https://github.com/settings/ssh/new](https://github.com/settings/ssh/new) ) to paste that public key in. ![Adding a key to GitHub](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsigning-04.0071b3e8.png&w=3840&q=75) Be sure to change the type to 'Signing Key' Now your signed commits should show up as "Verified". ### [Adding to GitLab](https://docs.gitbutler.com/features/branch-management/signing-commits#adding-to-gitlab) For GitLab you need to go to "SSH Keys" in your profile: [https://gitlab.com/-/profile/keys](https://gitlab.com/-/profile/keys) and click the "Add new key" button. ![Adding a key to GitHub](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsigning-05.3a358c60.png&w=3840&q=75) Add new key here. Now paste in the public SSH key you copied from GitButler, name it and make sure the "Usage Type" is either "Signing" or "Authentication and Signing". ![Adding a key to GitHub](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsigning-06.33cde0c4.png&w=3840&q=75) Now all your GitButler generated commits will be verified on that platform! Last updated on [Previous\ \ Upstream Integration](https://docs.gitbutler.com/features/branch-management/upstream-integration) [Next\ \ AI Assistance](https://docs.gitbutler.com/features/branch-management/ai-assistance) ### On this page [Telling GitButler to Sign](https://docs.gitbutler.com/features/branch-management/signing-commits#telling-gitbutler-to-sign) [Upload Your Signing Key](https://docs.gitbutler.com/features/branch-management/signing-commits#upload-your-signing-key) [Adding to GitHub](https://docs.gitbutler.com/features/branch-management/signing-commits#adding-to-github) [Adding to GitLab](https://docs.gitbutler.com/features/branch-management/signing-commits#adding-to-gitlab) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/signing-commits.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/signing-commits%22) --- # Operations Log | GitButler Docs GuidesCLI Tutorial Operations Log ============== Understanding and using GitButler's operations log to track and undo changes. GitButler maintains a detailed log of all operations, making it easy to track what happened and undo changes when needed. [Viewing the Operations Log](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#viewing-the-operations-log) --------------------------------------------------------------------------------------------------------------------------- See all recent GitButler operations: $ but oplog **Operations History** ────────────────────────────────────────────────── e16021d339a2 2020-10-09 09:06:03 \[OTHER\] UpdateDependentBranchName b0f492536a38 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot 6ac172bcd27e 2020-10-09 09:06:03 \[INSERT\] InsertBlankCommit 92a40ac9b19f 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot 74862403ab1c 2020-10-09 09:06:03 \[OTHER\] FileChanges f22383e0493c 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot c009517b354c 2020-10-09 09:06:03 \[MOVE\] MoveCommit f33a43433210 2020-10-09 09:06:03 \[MOVE\] MoveCommit 785eaf5b8ec5 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot cca556351442 2020-10-09 09:06:03 \[UNDO\] UndoCommit 020eaf3a565c 2020-10-09 09:06:03 \[UNDO\] UndoCommit 14568d7f9e9d 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot a90094763410 2020-10-09 09:06:03 \[SQUASH\] SquashCommit 2b4f05e9c18e 2020-10-09 09:06:03 \[SQUASH\] SquashCommit 38202db7e609 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot a1a7361b9d81 2020-10-09 09:06:03 \[AMEND\] AmendCommit 357dd95433c0 2020-10-09 09:06:03 \[AMEND\] AmendCommit 784d1964e6c4 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot 995bed5ffd5d 2020-10-09 09:06:03 \[RESTORE\] Restored from snapshot 2e89b508f5fd 2020-10-09 09:06:03 \[MOVE\_HUNK\] MoveHunk [Undoing the last operation](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#undoing-the-last-operation) --------------------------------------------------------------------------------------------------------------------------- Undo the last operation: $ but undo **Undoing operation...** Reverting to: Restored from snapshot (2020-10-09 09:06:03) **✓** Undo completed successfully! Restored to snapshot: b0f492536a38 [Restoring to a previous point](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#restoring-to-a-previous-point) --------------------------------------------------------------------------------------------------------------------------------- You can restore to any point in the operations history by running the `but oplog restore` command with the SHA from `but oplog`. $ but oplog restore 6fdd8fb1d547 **✓** Restore completed successfully! Workspace has been restored to the selected snapshot. 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](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#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. $ but oplog snapshot **Snapshot created successfully!** Snapshot ID: 25820fb040f2 💡 Use 'but oplog restore 25820fb' to restore to this snapshot later. Now you can copy that SHA and restore to that exact point at any time in the future. Last updated on [Previous\ \ Edit commit messages and branch names](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits) [Next\ \ Updating your Base](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base) ### On this page [Viewing the Operations Log](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#viewing-the-operations-log) [Undoing the last operation](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#undoing-the-last-operation) [Restoring to a previous point](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#restoring-to-a-previous-point) [Creating Snapshots](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log#creating-snapshots) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/operations-log.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/operations-log%22) --- # Recovering Stuff | GitButler Docs Troubleshooting Recovering Stuff ================ Recover lost work and data from GitButler using Git references, operations log, and internal data structures. 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](https://docs.gitbutler.com/troubleshooting/recovering-stuff#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). 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: ![Parallel Branches Example](https://docs.gitbutler.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Frecovering-01.2ba693f3.webp&w=3840&q=75) I can view the git branches like this: 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: 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`: 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](https://docs.gitbutler.com/troubleshooting/recovering-stuff#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](https://docs.gitbutler.com/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. 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: 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: 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: 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: virtual\_branches \[branch-id\] commits \[commit-id1\] commit tree \[commit-id2\] tree \[branch-id\] commits tree This allows you to get contents of any file in any of your virtual branch states as well. Last updated on [Previous\ \ Fixing conflicts outside of GitButler](https://docs.gitbutler.com/troubleshooting/fixing-conflicts-outside-gitbutler) [Next\ \ Overview](https://docs.gitbutler.com/ai-agents/overview) ### On this page [GitButler References](https://docs.gitbutler.com/troubleshooting/recovering-stuff#gitbutler-references) [GitButler Operations Log](https://docs.gitbutler.com/troubleshooting/recovering-stuff#gitbutler-operations-log) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/troubleshooting/recovering-stuff.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22troubleshooting/recovering-stuff%22) --- # Script with JSON output | GitButler Docs GuidesCLI Tutorial Script with JSON output ======================= Use structured GitButler CLI output in scripts and agent workflows. Commands that expose structured output accept the `--json` option. For example, inspect the workspace with `jq`: but status --json | jq Or inspect one commit: but show nn --json | jq Mutation commands such as `but commit`, `but amend`, and `but move` also support `--json`: but commit -b user-bookmarks -m "Add user bookmarks" q3 w7 --json Not every command has JSON output, and there is no `-j` shorthand. Check `but --help` before relying on `--json` in a script. Avoid commands that can prompt for input. Pass a commit message, name explicit branch targets, and use command-specific non-interactive options when available. Last updated on [Previous\ \ Working with AI](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff) [Next\ \ Wrap Up](https://docs.gitbutler.com/cli-guides/cli-tutorial/conclusion) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/scripting.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/scripting%22) --- # Working with AI | GitButler Docs GuidesCLI Tutorial Working with AI =============== Use AI-backed CLI options and set up GitButler for coding agents. Use `--ai` when you want the CLI to generate text for a single command. Use `but agent setup` when you want a coding agent to use GitButler's version-control workflow. [`--ai` options](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#--ai-options) ------------------------------------------------------------------------------------------- Supported commands can take `--ai` to generate text from your current changes. ### [`but commit --ai`](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#but-commit---ai) Use `but commit --ai` to generate a commit message from the changes you are committing. This commits the selected work with the generated message. You can edit the message afterward with `but reword `. ### [`but squash --ai`](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#but-squash---ai) Use `but squash --ai` to generate a combined commit message when squashing commits. More commands will gain `--ai` support over time. [`but agent setup`](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#but-agent-setup) ------------------------------------------------------------------------------------------------- Run the setup wizard from the repository where your coding agent will work: but agent setup The wizard can install the GitButler skill, save workflow preferences in supported agent instruction files, and run `but setup` for the repository when GitButler needs workspace mode. Use `but skill install` when you only want to install or update the skill files without writing workflow instructions. To update an existing install without going through the prompts, run: but skill install --detect We keep these templates up to date, so update the skill after updating GitButler. [Agent workflow docs](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#agent-workflow-docs) ------------------------------------------------------------------------------------------------------- For the full workflow: * Start with [AI agents overview](https://docs.gitbutler.com/ai-agents/overview) . * Install and configure the skill with [Getting started with AI agents](https://docs.gitbutler.com/ai-agents/getting-started) . * Use [Useful requests](https://docs.gitbutler.com/ai-agents/useful-requests) for prompt examples. * Use [Tuning agent behavior](https://docs.gitbutler.com/ai-agents/tuning-agent-behavior) for standing instructions. Last updated on [Previous\ \ Configuration and Aliases](https://docs.gitbutler.com/cli-guides/cli-tutorial/configuration) [Next\ \ Script with JSON output](https://docs.gitbutler.com/cli-guides/cli-tutorial/scripting) ### On this page [`--ai` options](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#--ai-options) [`but commit --ai`](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#but-commit---ai) [`but squash --ai`](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#but-squash---ai) [`but agent setup`](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#but-agent-setup) [Agent workflow docs](https://docs.gitbutler.com/cli-guides/cli-tutorial/ai-stuff#agent-workflow-docs) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/ai-stuff.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/ai-stuff%22) --- # Edit commit messages and branch names | GitButler Docs GuidesCLI Tutorial Edit commit messages and branch names ===================================== Reword commits and rename branches with the GitButler CLI. Use `but reword` to change a commit message or branch name. When you reword a commit, GitButler rewrites it and rebases dependent work above it. [Change a commit message](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits#change-a-commit-message) ---------------------------------------------------------------------------------------------------------------------- Find the commit ID: but status Then pass the new message: but reword nn -m "Add user bookmarks" Omit `-m` when you want to edit the existing message in your configured editor: but reword nn Use `--fix-formatting` to wrap the existing message to 72 characters without opening an editor: but reword nn --fix-formatting [Rename a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits#rename-a-branch) ------------------------------------------------------------------------------------------------------ Pass the branch name or CLI ID as the target: but reword user-bookmarks -m feature/user-bookmarks Run `but status` to see the new branch name. Last updated on [Previous\ \ Edit commit history](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing) [Next\ \ Operations Log](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log) ### On this page [Change a commit message](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits#change-a-commit-message) [Rename a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits#rename-a-branch) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/editing-commits.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/editing-commits%22) --- # AI Assistance | GitButler Docs FeaturesBranch Management AI Assistance ============= Let AI handle the busywork — generate branch names, commit messages, and pull request descriptions automatically in GitButler. [Getting Started](https://docs.gitbutler.com/features/branch-management/ai-assistance#getting-started) ------------------------------------------------------------------------------------------------------- ### [Global AI Setup (One-time)](https://docs.gitbutler.com/features/branch-management/ai-assistance#global-ai-setup-one-time) 1. Navigate to **Global settings** → **AI Options** 2. Choose your AI provider: * **GitButler API** (default): Uses OpenAI through GitButler's servers - no API key needed * **Your own key**: Bring your own OpenAI, Claude, Ollama, or LM Studio credentials 3. If using your own key, enter your API credentials ### [Per-Project Setup](https://docs.gitbutler.com/features/branch-management/ai-assistance#per-project-setup) 1. Open **Project settings** → **AI options** 2. Enable **"Enable branch and commit message generation"** 3. Optionally enable **"Enable experimental AI features"** for advanced functionality [Features](https://docs.gitbutler.com/features/branch-management/ai-assistance#features) ----------------------------------------------------------------------------------------- ### [Branch Name Generation](https://docs.gitbutler.com/features/branch-management/ai-assistance#branch-name-generation) Automatically creates descriptive, kebab-case branch names based on your code changes. **Usage:** * Right-click on a branch header and select **Generate branch name** * GitButler analyzes commit messages in the branch and suggests an appropriate name * Generated names use kebab-case format and avoid conflicts with existing branches ### [Commit Message Generation](https://docs.gitbutler.com/features/branch-management/ai-assistance#commit-message-generation) Creates professional commit messages following best practices. **Features:** * Semantic prefixes (`feat:`, `fix:`, `refactor:`) * 50-character title limit, 72-character body wrap * Explains what changed and why * Real-time streaming as AI generates the message * Based on actual code diffs, not just file names **Usage:** 1. Make changes to your files (staging is automatic in GitButler) 2. Click the **Generate message** button in the commit message editor 3. AI streams the generated message in real-time 4. Review and edit before committing **Example format:** feat: add user authentication system Implements JWT-based authentication with login and registration endpoints. Includes password hashing and session management to secure user accounts. ### [Pull Request Descriptions](https://docs.gitbutler.com/features/branch-management/ai-assistance#pull-request-descriptions) Generates comprehensive PR descriptions when creating pull requests. **Usage:** 1. Create a pull request from your branch 2. In the PR creation dialog, click **Generate PR description** 3. AI analyzes all commits in your branch and generates a description 4. Review and edit the generated content before creating the PR **Generated content includes:** * High-level summary based on commit messages * Structured description following PR templates (if configured) * Context derived from the changes in your branch [Advanced Features](https://docs.gitbutler.com/features/branch-management/ai-assistance#advanced-features) ----------------------------------------------------------------------------------------------------------- ### [Custom Prompts](https://docs.gitbutler.com/features/branch-management/ai-assistance#custom-prompts) * **Global Prompts**: Create custom prompts in **Global settings** → **AI Options** * **Project-Specific Prompts**: Assign specific prompts per project in **Project settings** → **AI options** * **Commit & Branch Prompts**: Separate customization for commit messages and branch names [Configuration](https://docs.gitbutler.com/features/branch-management/ai-assistance#configuration) --------------------------------------------------------------------------------------------------- ### [Global Settings (Global settings → AI Options)](https://docs.gitbutler.com/features/branch-management/ai-assistance#global-settings-global-settings--ai-options) * **AI Provider**: Choose between OpenAI, Anthropic, Ollama, or LM Studio * **Key Options**: Use GitButler API or bring your own credentials for each provider * **Model Selection**: Choose specific models per provider (GPT-4o, Claude Sonnet, etc.) * **Amount of provided context**: Set how many characters of git diff to send to AI ### [Project Settings (Project settings → AI options)](https://docs.gitbutler.com/features/branch-management/ai-assistance#project-settings-project-settings--ai-options) * **Enable branch and commit message generation**: Master toggle for AI features in this project * **Enable experimental AI features**: Access to advanced AI functionality (requires GitButler API) * **Custom prompts**: Assign specific prompts from global settings to this project for commits and branches [Troubleshooting](https://docs.gitbutler.com/features/branch-management/ai-assistance#troubleshooting) ------------------------------------------------------------------------------------------------------- **AI features not working?** 1. **Check Global Settings**: Navigate to **Global settings** → **AI Options** and verify: * AI provider is configured (OpenAI, Anthropic, etc.) * Key option is selected (GitButler API or your own key) * If using your own key, ensure it's entered correctly * Model is selected for your chosen provider 2. **Check Project Settings**: Open **Project settings** → **AI options** and ensure: * **"Enable branch and commit message generation"** is turned ON * This setting must be enabled for each project individually 3. **Verify API Access**: Ensure sufficient API quota and valid credentials **AI buttons not appearing?** * The project-level toggle in **Project settings** → **AI options** controls button visibility * Without this enabled, Generate buttons won't appear in the UI **Need better suggestions?** * Customize prompt templates in **Global settings** → **AI Options** * Make meaningful code changes with clear patterns * Use descriptive variable names and comments in your code * Review [troubleshooting guide](https://docs.gitbutler.com/troubleshooting/custom-csp) for advanced configurations Last updated on [Previous\ \ Signing Commits](https://docs.gitbutler.com/features/branch-management/signing-commits) [Next\ \ Operations History](https://docs.gitbutler.com/features/timeline) ### On this page [Getting Started](https://docs.gitbutler.com/features/branch-management/ai-assistance#getting-started) [Global AI Setup (One-time)](https://docs.gitbutler.com/features/branch-management/ai-assistance#global-ai-setup-one-time) [Per-Project Setup](https://docs.gitbutler.com/features/branch-management/ai-assistance#per-project-setup) [Features](https://docs.gitbutler.com/features/branch-management/ai-assistance#features) [Branch Name Generation](https://docs.gitbutler.com/features/branch-management/ai-assistance#branch-name-generation) [Commit Message Generation](https://docs.gitbutler.com/features/branch-management/ai-assistance#commit-message-generation) [Pull Request Descriptions](https://docs.gitbutler.com/features/branch-management/ai-assistance#pull-request-descriptions) [Advanced Features](https://docs.gitbutler.com/features/branch-management/ai-assistance#advanced-features) [Custom Prompts](https://docs.gitbutler.com/features/branch-management/ai-assistance#custom-prompts) [Configuration](https://docs.gitbutler.com/features/branch-management/ai-assistance#configuration) [Global Settings (Global settings → AI Options)](https://docs.gitbutler.com/features/branch-management/ai-assistance#global-settings-global-settings--ai-options) [Project Settings (Project settings → AI options)](https://docs.gitbutler.com/features/branch-management/ai-assistance#project-settings-project-settings--ai-options) [Troubleshooting](https://docs.gitbutler.com/features/branch-management/ai-assistance#troubleshooting) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/ai-assistance.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/ai-assistance%22) --- # Upstream Integration | GitButler Docs FeaturesBranch Management Upstream Integration ==================== Handle upstream commits and merge them into your parallel branches when collaborators push to the same remote branch. 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: ![Oh no, someone else has pushed!](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-09-12%2520at%252014.49.08%25402x.png&w=3840&q=75) Oh no, someone else has pushed! 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. ![GitButler's view when someone else has pushed](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-09-12%2520at%252014.42.06%25402x.png&w=3840&q=75) GitButler's view when someone else has pushed When you decide that you do want to integrate the changes, you have two options - rebase or interactively integrate. [Rebase the changes](https://docs.gitbutler.com/features/branch-management/upstream-integration#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: ![Simple rebase of my changes on top of the upstream changes](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-09-12%2520at%252015.08.05%25402x.png&w=3840&q=75) Simple rebase of my changes on top of the upstream changes Now you can push your commit back upstream without a force push. Easy peasy. [Interactively integrate the changes](https://docs.gitbutler.com/features/branch-management/upstream-integration#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: ![Upstream integration helper](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-09-12%2520at%252014.42.42%25402x.png&w=3840&q=75) Upstream integration helper 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. Last updated on [Previous\ \ Rebasing and Conflicts](https://docs.gitbutler.com/features/branch-management/merging) [Next\ \ Signing Commits](https://docs.gitbutler.com/features/branch-management/signing-commits) ### On this page [Rebase the changes](https://docs.gitbutler.com/features/branch-management/upstream-integration#rebase-the-changes) [Interactively integrate the changes](https://docs.gitbutler.com/features/branch-management/upstream-integration#interactively-integrate-the-changes) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/features/branch-management/upstream-integration.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22features/branch-management/upstream-integration%22) --- # Wrap Up | GitButler Docs GuidesCLI Tutorial Wrap Up ======= That's GitButler's command line interface. 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! Last updated on [Previous\ \ Script with JSON output](https://docs.gitbutler.com/cli-guides/cli-tutorial/scripting) [Next\ \ Commands Overview](https://docs.gitbutler.com/commands/commands-overview) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/conclusion.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/conclusion%22) --- # Initializing a Repository | GitButler Docs GuidesCLI Tutorial Initializing a Repository ========================= How to initialize a GitButler workspace in your repository. 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: $ but setup Setting up GitButler project... → Adding repository to GitButler project registry ✓ Repository added to project registry → Configuring default target branch ✓ Using existing push remote: origin ✓ Set default target to: origin/main **GitButler project setup complete!** Target branch: origin/main Remote: origin We are switching you to GitButler's special \`gitbutler/workspace\` branch To return to normal Git mode, either: - Directly checkout a branch (\`git checkout master\`) - Run \`but teardown\` More info: https://docs.gitbutler.com/workspace-branch 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. Last updated on [Previous\ \ Workflow Overview](https://docs.gitbutler.com/cli-guides/cli-tutorial/tutorial-overview) [Next\ \ Branching and committing](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/initializing-a-repository.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/initializing-a-repository%22) --- # Conflict Resolution | GitButler Docs GuidesCLI Tutorial Conflict Resolution =================== How to deal with conflicts in upstream work 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](https://docs.gitbutler.com/cli-guides/cli-tutorial/conflict-resolution#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. $ but status ╭┄zz \[**unstaged changes**\] ┊ _no changes_ ┊ ┊╭┄ \[\] ┊● 6ef6de2 hero update - new branding ┊● 7bad120 refactor User model ┊│ ┊├┄up \[**update-homepage**\] #**70**: update the homepage ┊● f91211a branding change: readme ├╯ ┊ ┊● 96ccca9 (upstream) ⏫ 1 new commits ├╯ 32a2175 (common base) \[**origin/main**\] 2025-11-03 Merge pull request #65 from schacon/feature-bookma Hint: run \`but help\` for all commands 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). $ but pull **Found** 1 upstream commits on origin/main 96ccca9 Merge pull request #69 from schacon/sc-switch-wording-to-x **Summary** ──────── **To undo this operation:** Run \`but undo\` 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`. $ but status ╭┄zz \[**unstaged changes**\] ┊ _no changes_ ┊ ┊╭┄up \[**update-homepage**\] #**70**: update the homepage ┊◐ a32f332 hero update - new branding ┊● 0e95268 _(no commit message)_ ┊● f91211a branding change: readme ├╯ ┊ ┴ 96ccca9 (common base) \[**origin/main**\] 2026-01-26 Merge pull request #69 from schacon/sc-switch-word Hint: run \`but help\` for all commands 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. ❯ 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. ❯ 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 ❯ 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. ❯ 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. ❯ 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. Last updated on [Previous\ \ Updating your Base](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base) [Next\ \ Push branches and create reviews](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges) ### On this page [First Class Conflicts in GitButler](https://docs.gitbutler.com/cli-guides/cli-tutorial/conflict-resolution#first-class-conflicts-in-gitbutler) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/conflict-resolution.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/conflict-resolution%22) --- # Updating your Base | GitButler Docs GuidesCLI Tutorial Updating your Base ================== Learn how to manage and update your target branch and base commit in GitButler. 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](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#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`: $ but config **GitButler Configuration** **User**: Name: Scott Chacon (global) Email: schacon@gmail.com (global) Editor: nvim (global) **Target Branch**: origin/main **Forge**: • GitHub schacon **UI**: TUI mode: disabled Available subcommands: but config user - User settings (name, email, editor) but config forge - Forge settings (GitHub, etc) but config target - Target branch settings but config metrics - Metrics settings but config ui - UI preferences (TUI mode) Or get more information with `but config target`: $ but config target Used to determine common base to calculate commits unique to each branch (not yet integrated) **Target Branch**: origin/main Remote: git@github.com:schacon/why.git SHA: 204e309a8298ec047e7d79497a9efcec808ddc95 To change target branch: but config target When you start working, everything that is different from that base goes into a branch based off of it. ![Setting a base from a target branch, then doing some work](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-11-03%2520at%252016.01.08%25402x.png&w=3840&q=75) Setting a base from a target branch, then doing some work [Understanding Upstream](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#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". ![Some work has been merged in upstream, now our branch is out of date](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-11-03%2520at%252016.03.00%25402x.png&w=3840&q=75) Some work has been merged in upstream, now our branch is out of date 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](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#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`). Let's take a look at what this looks like. Let's say that our project is at this state: $ but status -u ╭┄zz \[**unstaged changes**\] ┊ _no changes_ ┊ ┊╭┄us \[**user-bookmarks**\] \[✓ upstream merges cleanly\] ┊● 464aae4 add user changes ┊● ca81308 create bookmarks ├╯ ┊ ┊╭┄(upstream) ⏫ 2 new commits ┊● 32a2175 Merge pull request #65 from schacon/feature-bookmarks feat: Add bookmar ┊● c6d8414 Merge pull request #57 from schacon/schacon-patch-1 Update README.md ┊┊ ├╯ 204e309 (common base) \[**origin/main**\] 2025-07-06 Merge pull request #10 from schacon/sc-description Hint: run \`but help\` for all commands We can see that there are two commits upstream (ie, merged into `origin/main` since we started our branch). 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. 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`. $ but pull --check Base branch: origin/main Upstream: 2 new commits on origin/main 32a2175 Merge pull request #65 from schacon/feature-bookmarks feat: Add bookmar c6d8414 Merge pull request #57 from schacon/schacon-patch-1 Update README.md **Branch Status** \[ok\] user-bookmarks Run \`but pull\` to update your branches 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](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#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. ![Rebasing our work onto the new upstream work, updating our base](https://docs.gitbutler.com/_next/image?url=https%3A%2F%2Fd2m1ukvwmu7gz4.cloudfront.net%2FCleanShot%25202025-11-03%2520at%252016.05.16%25402x.png&w=3840&q=75) Rebasing our work onto the new upstream work, updating our base Let's run it in our example. $ but pull **Found** 2 upstream commits on origin/main 32a2175 Merge pull request #65 from schacon/feature-bookmarks c6d8414 Merge pull request #57 from schacon/schacon-patch-1 Updating 1 active branches... **Rebase** of user-bookmarks successful **Summary** ──────── user-bookmarks - rebased **To undo this operation:** Run \`but undo\` $ but status ╭┄zz \[**unstaged changes**\] ┊ _no changes_ ┊ ┊╭┄us \[**user-bookmarks**\] ┊● b4eeb4c add user changes ┊● 9414216 create bookmarks ├╯ ┊ ┴ 32a2175 (common base) \[**origin/main**\] 2025-11-03 Merge pull request #65 from schacon/feature-bookma Hint: run \`but help\` for all commands 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. Last updated on [Previous\ \ Operations Log](https://docs.gitbutler.com/cli-guides/cli-tutorial/operations-log) [Next\ \ Conflict Resolution](https://docs.gitbutler.com/cli-guides/cli-tutorial/conflict-resolution) ### On this page [Understanding the Target Branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#understanding-the-target-branch) [Understanding Upstream](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#understanding-upstream) [Viewing Upstream](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#viewing-upstream) [Updating the Base](https://docs.gitbutler.com/cli-guides/cli-tutorial/updating-the-base#updating-the-base) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/updating-the-base.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/updating-the-base%22) --- # Push branches and create reviews | GitButler Docs GuidesCLI Tutorial Push branches and create reviews ================================ Publish branches, create pull or merge requests, and land work with the GitButler CLI. Use `but push` to publish a branch, `but pr` to create a review, or `but land` when your project accepts direct updates to the target branch. [Push a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#push-a-branch) ----------------------------------------------------------------------------------------- Name the branch you want to push: but push update-homepage Preview the push without changing the remote: but push update-homepage --dry-run In an interactive terminal, bare `but push` opens a branch picker. In a non-interactive session, it pushes every branch with unpushed commits, so naming the branch is safer in scripts. [Create a pull or merge request](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#create-a-pull-or-merge-request) --------------------------------------------------------------------------------------------------------------------------- Authenticate with the repository's forge first: but config forge auth GitButler supports accounts for GitHub, GitLab, and Bitbucket. The authentication flow offers the methods supported by the selected provider, including self-hosted GitHub and GitLab instances. Create a review for a branch: but pr new update-homepage GitButler pushes the branch before creating its pull request or merge request. Use `but mr` as an alias when you prefer GitLab terminology. Pass `-t` to use the default title and description without prompts: but pr new update-homepage -t For a stacked branch, name the top branch. GitButler pushes the whole stack and creates missing reviews from the bottom upward: but pr new feature-polish -t [Manage forge accounts](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#manage-forge-accounts) --------------------------------------------------------------------------------------------------------- Show configured accounts and their authentication status: but config forge List accounts or remove one that you no longer use: but config forge list-users but config forge forget alice [Land without a review](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#land-without-a-review) --------------------------------------------------------------------------------------------------------- If your project accepts direct updates to the target branch, land a branch with: but land update-homepage This bypasses code review and any checks enforced only by your review workflow. GitButler asks for confirmation because the target update isn't easily reversible. The target fast-forwards when possible; otherwise GitButler creates a merge commit. After landing, GitButler reconciles the remaining applied branches onto the updated target. If the remote rejects direct pushes because of branch protection, create a review with `but pr new` instead. See [`but land`](https://docs.gitbutler.com/commands/but-land) for stack and non-interactive options. Last updated on [Previous\ \ Conflict Resolution](https://docs.gitbutler.com/cli-guides/cli-tutorial/conflict-resolution) [Next\ \ Configuration and Aliases](https://docs.gitbutler.com/cli-guides/cli-tutorial/configuration) ### On this page [Push a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#push-a-branch) [Create a pull or merge request](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#create-a-pull-or-merge-request) [Manage forge accounts](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#manage-forge-accounts) [Land without a review](https://docs.gitbutler.com/cli-guides/cli-tutorial/forges#land-without-a-review) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/forges.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/forges%22) --- # Edit commit history | GitButler Docs GuidesCLI Tutorial Edit commit history =================== Amend, squash, uncommit, move, and split commits with the GitButler CLI. GitButler gives each history-editing task a focused command. Start with `but status -fv` when you need commit IDs and the file IDs inside each commit: but status -fv Use the IDs shown in your own output. Commit IDs with a change ID remain stable across history edits; a SHA-based ID can change when GitButler rewrites history. [Amend uncommitted changes](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#amend-uncommitted-changes) ------------------------------------------------------------------------------------------------------------------ Use `but amend` when new work belongs in an existing commit. First inspect the uncommitted changes and history: but diff but status Then pass the uncommitted file or hunk IDs as positional sources and select the commit with `-t`: but amend -t nn q3 w7:5 This adds file `q3` and hunk `w7:5` to commit `nn`. If you target a branch instead, GitButler amends its newest commit: but amend -t user-bookmarks q3 [Squash commits](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#squash-commits) -------------------------------------------------------------------------------------------- To combine a newer commit with an older target commit, pass the source commit first and the target with `-t`: but squash ss -t nn -m "Add bookmark validation" The source commit disappears and its changes become part of the target. Pass `-m` when squashing commits so GitButler doesn't open an editor. To collapse every commit on one branch into a single commit: but squash user-bookmarks -m "Add user bookmarks" [Uncommit work](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#uncommit-work) ------------------------------------------------------------------------------------------ Use `but uncommit` to move a whole commit back to the uncommitted area: but uncommit nn To uncommit one file from a commit, get its committed-file ID from `but status -f`, then combine the commit and file IDs: but uncommit nn:a The rest of commit `nn` stays committed. [Move commits](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#move-commits) ---------------------------------------------------------------------------------------- If a commit landed on the wrong branch, move it to another branch's tip: but move nn -b liked-tweets If `liked-tweets` doesn't exist, GitButler creates it as an independent branch. You can also reorder commits on a branch. `--below` makes the source older than the target, while `--above` makes it newer: but move ss --below nn but move ss --above nn Move a branch above another branch to turn two independent branches into a stack: but move liked-tweets --above user-bookmarks [Move a file between commits](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#move-a-file-between-commits) ---------------------------------------------------------------------------------------------------------------------- Run `but status -f` to get committed-file IDs: but status -f Move file `a` out of commit `nn` and into commit `mm`: but squash nn:a -t mm When the source is a committed file, GitButler keeps the target commit's message. [Split a commit](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#split-a-commit) -------------------------------------------------------------------------------------------- For a top commit, the cleanest split is to uncommit it and create replacement commits from selected changes. 1. Uncommit the source and inspect the resulting file and hunk IDs: but uncommit nn but diff 2. Create the replacement commits from oldest to newest: but commit -b user-bookmarks -m "Add bookmark model" q3 w7 but commit -b user-bookmarks -m "Validate bookmark URLs" p8:5 Changes you don't name remain uncommitted. If the source commit has other commits above it, those commits may need to be moved back to the branch tip after you create the replacements. [Add an empty placeholder commit](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#add-an-empty-placeholder-commit) ------------------------------------------------------------------------------------------------------------------------------ An empty commit can reserve a place in history for work you plan to amend later: but commit --empty --below nn -m "Add bookmark error handling" When the implementation is ready, inspect its change IDs and amend them into the placeholder: but diff but amend -t ee q3 w7 In `but status`, `--above` places the placeholder on the line above the target (newer), while `--below` places it on the line below (older). Next, learn how to [change commit messages and branch names](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits) . Last updated on [Previous\ \ Inspecting changes and branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting) [Next\ \ Edit commit messages and branch names](https://docs.gitbutler.com/cli-guides/cli-tutorial/editing-commits) ### On this page [Amend uncommitted changes](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#amend-uncommitted-changes) [Squash commits](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#squash-commits) [Uncommit work](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#uncommit-work) [Move commits](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#move-commits) [Move a file between commits](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#move-a-file-between-commits) [Split a commit](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#split-a-commit) [Add an empty placeholder commit](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing#add-an-empty-placeholder-commit) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/rubbing.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/rubbing%22) --- # Inspecting changes and branches | GitButler Docs GuidesCLI Tutorial Inspecting changes and branches =============================== Inspect uncommitted changes, commits, and branches with GitButler. GitButler adds concise views for common workspace tasks, while normal read-only Git commands such as `git show`, `git log`, and `git blame` continue to work. [Inspect the workspace](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#inspect-the-workspace) ------------------------------------------------------------------------------------------------------------- Start with: but status This shows the uncommitted area, applied branches and stacks, commit order, and upstream state. Add `-f` to include the files in each commit: but status -f The first token on each entity line is the CLI ID you can pass to other `but` commands. [Diff changes](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#diff-changes) ------------------------------------------------------------------------------------------- Run `but diff` without a target to inspect all uncommitted changes: but diff Pass one CLI ID to narrow the diff: but diff q3 but diff user-bookmarks but diff nn but diff nn:a These examples inspect an uncommitted file, a branch, a commit, and one file within a commit. `but diff` accepts at most one target, so run it again to inspect another entity. You can still use `git diff` when you need Git's raw patch format: git diff HEAD [List branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#list-branches) --------------------------------------------------------------------------------------------- Run `but branch` to show the active branch and the 20 most recently updated branches: but branch The list includes useful context such as how far each branch is ahead of the target and whether it merges cleanly into upstream. Filter branches by a partial name: but branch list book Useful filters include: * `--all` to include all branches * `--local` or `--remote` to limit the source * `--review` to fetch review information * `--no-ahead` and `--no-check` to skip slower calculations [Inspect a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#inspect-a-branch) --------------------------------------------------------------------------------------------------- Show the commits on a branch that haven't landed in the target: but branch show feature-awesome-thing Add details when you need them: but branch show feature-awesome-thing --files --review --check Use `--ai` to generate a summary of the branch changes: but branch show feature-awesome-thing --ai [Inspect a commit](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#inspect-a-commit) --------------------------------------------------------------------------------------------------- Pass a commit's CLI ID or SHA to `but show`: but show nn For a branch, `but show --verbose` includes full commit messages and changed files. [Delete a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#delete-a-branch) ------------------------------------------------------------------------------------------------- Deleting a branch removes it and its commits from the workspace. Check the branch before deleting work you may still need: but branch show old-experiment but branch delete old-experiment GitButler asks for confirmation when the branch contains unpushed commits. Last updated on [Previous\ \ Branching and committing](https://docs.gitbutler.com/cli-guides/cli-tutorial/branching-and-commiting) [Next\ \ Edit commit history](https://docs.gitbutler.com/cli-guides/cli-tutorial/rubbing) ### On this page [Inspect the workspace](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#inspect-the-workspace) [Diff changes](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#diff-changes) [List branches](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#list-branches) [Inspect a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#inspect-a-branch) [Inspect a commit](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#inspect-a-commit) [Delete a branch](https://docs.gitbutler.com/cli-guides/cli-tutorial/inspecting#delete-a-branch) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/cli-guides/cli-tutorial/inspecting.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22cli-guides/cli-tutorial/inspecting%22) --- # but clean | GitButler Docs Commands \>\_ but clean ========= Remove empty branches from the workspace. A branch is considered empty if it has no local commits and (by default) no upstream-only commits. Stacks with uncommitted changes assigned to them in the GitButler app are skipped entirely. The entire operation is recorded as a single oplog entry, so it can be undone with `but undo`. [Examples](https://docs.gitbutler.com/commands/but-clean#examples) ------------------------------------------------------------------- Remove all empty branches: but clean Preview which branches would be removed: but clean --dry-run Pull latest changes first, then clean: but clean --pull Also remove branches that only have upstream commits: but clean --include-upstream **Usage:** `but clean [OPTIONS]` [Options](https://docs.gitbutler.com/commands/but-clean#options) ----------------------------------------------------------------- * `--dry-run` — Preview which branches would be removed without actually deleting them * `--pull` — Pull latest changes from the remote before cleaning * `--include-upstream` — Also remove branches that have upstream-only commits but no local commits or changes Last updated on [Previous\ \ but apply](https://docs.gitbutler.com/commands/but-apply) [Next\ \ but pick](https://docs.gitbutler.com/commands/but-pick) ### On this page [Examples](https://docs.gitbutler.com/commands/but-clean#examples) [Options](https://docs.gitbutler.com/commands/but-clean#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-clean.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-clean%22) --- # but apply | GitButler Docs Commands \>\_ but apply ========= Apply a branch. 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. **Usage:** `but apply ` [Arguments](https://docs.gitbutler.com/commands/but-apply#arguments) --------------------------------------------------------------------- * `` — The branch to apply (required) Last updated on [Previous\ \ but unapply](https://docs.gitbutler.com/commands/but-unapply) [Next\ \ but clean](https://docs.gitbutler.com/commands/but-clean) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-apply#arguments) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-apply.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-apply%22) --- # but pull | GitButler Docs Commands \>\_ but pull ======== Updates all applied branches to be up to date with the target branch. 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. **Usage:** `but pull [OPTIONS]` [Options](https://docs.gitbutler.com/commands/but-pull#options) ---------------------------------------------------------------- * `-c`, `--check` — Only check the status without updating (equivalent to the old but base check) Last updated on [Previous\ \ but push](https://docs.gitbutler.com/commands/but-push) [Next\ \ but pr](https://docs.gitbutler.com/commands/but-pr) ### On this page [Options](https://docs.gitbutler.com/commands/but-pull#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-pull.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-pull%22) --- # but redo | GitButler Docs Commands \>\_ but redo ======== Redo the last undo. **Usage:** `but redo` Last updated on [Previous\ \ but undo](https://docs.gitbutler.com/commands/but-undo) [Next\ \ but gui](https://docs.gitbutler.com/commands/but-gui) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-redo.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-redo%22) --- # but diff | GitButler Docs Commands \>\_ but diff ======== Displays the diff of changes in the repo. Without any arguments, it shows the diff of all uncommitted changes. Optionally, provide one CLI ID to show the diff for an uncommitted file, branch, commit, committed file, or worktree. `TARGET` accepts at most one entity. To show several entities, run this command once per entity. **Usage:** `but diff [TARGET]` [Arguments](https://docs.gitbutler.com/commands/but-diff#arguments) -------------------------------------------------------------------- * `` — The CLI ID of the entity to show the diff for. If omitted shows the diff of all uncommitted changes. For more details about CLI IDs, see but help cli-ids. Last updated on [Previous\ \ but status](https://docs.gitbutler.com/commands/but-status) [Next\ \ but show](https://docs.gitbutler.com/commands/but-show) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-diff#arguments) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-diff.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-diff%22) --- # but push | GitButler Docs Commands \>\_ but push ======== Push changes in a branch to remote. `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" **Usage:** `but push [BRANCH_ID] [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-push#arguments) -------------------------------------------------------------------- * `` — Branch name or CLI ID to push. If not specified, will list all branches and prompt for selection in interactive mode [Options](https://docs.gitbutler.com/commands/but-push#options) ---------------------------------------------------------------- * `-f`, `--with-force` — Force push even if it's not fast-forward (default: `true`) * `-s`, `--skip-force-push-protection` — Skip force push protection checks * `--no-hooks` — Bypass pre-push hooks * `-d`, `--dry-run` — Show what would be pushed without actually pushing * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but pick](https://docs.gitbutler.com/commands/but-pick) [Next\ \ but pull](https://docs.gitbutler.com/commands/but-pull) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-push#arguments) [Options](https://docs.gitbutler.com/commands/but-push#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-push.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-push%22) --- # but squash | GitButler Docs Commands \>\_ but squash ========== Squash commits, branches, or changes. Squash is flexible in the ways it can move changes around. It can * Squash commits into other commits * Squash branches into commits * Move changes between commits * Amend uncommitted changes into a commit * Uncommit commits * Uncommit changes in commits * Uncommit branches If no message-related flag is passed when squashing commits or branches, an editor may be opened where the new message can be composed; other squashes keep the target's message. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but squash [SOURCES] [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-squash#arguments) ---------------------------------------------------------------------- * `` — The sources to squash. If --target is provided and is omitted, the uncommitted area (zz) is used. If is one or more commits they will be squashed into the target. If is one or more branches all the commits on the branches will be squashed into the target and the branches will be removed. When the target is the uncommitted area (zz), all commits on the branches are uncommitted. If TARGET is omitted and is exactly one branch all commits on the branch will be squashed. If is one or more uncommitted files or hunks they will be squashed into the target. If is the uncommitted area (zz) all uncommitted changes will be squashed into the target. If is a committed file those changes will be moved into the target. All changes must come from the same commit. It is not possible to move changes from multiple source commits into a single target. It is not possible to mix sources of different types, i.e., all sources must either be commits, branches, uncommitted files, zz, or committed files. [Options](https://docs.gitbutler.com/commands/but-squash#options) ------------------------------------------------------------------ * `-m`, `--message` `` — The message to use for the new commit. Can be supplied any number of times, each value being appended to the preceding ones with a blank line in between. This cannot be used when TARGET is the uncommitted area (zz). * `--no-message` — Creates the commit without a commit message. This cannot be used when TARGET is the uncommitted area (zz). * `-u`, `--use-target-message` — Use the message of the target. The message of the source(s) will be discarded. This cannot be used when TARGET is the uncommitted area (zz). * `--use-source-message` — Use the message of the source(s). The message of the target will be discarded. Cannot be used if are not committed, if TARGET is the uncommitted area (zz), or if moving committed changes between commits. * `-t`, `--target` `` — The target to squash into. If TARGET is a commit the sources will be added to the commit. If TARGET is a branch the sources will be added to that branch's newest commit (its tip). If TARGET is the uncommitted area (zz) the sources will be uncommitted. * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but amend](https://docs.gitbutler.com/commands/but-amend) [Next\ \ but move](https://docs.gitbutler.com/commands/but-move) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-squash#arguments) [Options](https://docs.gitbutler.com/commands/but-squash#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-squash.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-squash%22) --- # but absorb | GitButler Docs Commands \>\_ but absorb ========== Amends changes into the appropriate commits where they belong. 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 assigned to a branch in the GitButler app, it will be amended into a commit there * If there are no commits on that branch, a new commit is created there * Changes are amended into the topmost commit of the leftmost (first) branch Optionally an identifier to an Uncommitted File may be provided. * If an Uncommitted File id is provided, absorb will be performed for just that file * 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. **Usage:** `but absorb [SOURCE] [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-absorb#arguments) ---------------------------------------------------------------------- * `` — If the Source is an uncommitted change - the change will be absorbed. If not provided, everything that is uncommitted will be absorbed [Options](https://docs.gitbutler.com/commands/but-absorb#options) ------------------------------------------------------------------ * `--dry-run` — Show the absorption plan without making any changes * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but land](https://docs.gitbutler.com/commands/but-land) [Next\ \ but reword](https://docs.gitbutler.com/commands/but-reword) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-absorb#arguments) [Options](https://docs.gitbutler.com/commands/but-absorb#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-absorb.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-absorb%22) --- # but teardown | GitButler Docs Commands \>\_ but teardown ============ Exit GitButler mode and return to normal Git workflow. This command: * Creates an oplog snapshot of the current state * Finds the first active branch and checks it out * Alternatively, use `--checkout-to ` to override this default * 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. [Examples](https://docs.gitbutler.com/commands/but-teardown#examples) ---------------------------------------------------------------------- Exit GitButler mode: but teardown but teardown --checkout-to my-feature-branch **Usage:** `but teardown [OPTIONS]` [Options](https://docs.gitbutler.com/commands/but-teardown#options) -------------------------------------------------------------------- * `-c`, `--checkout-to` `` — Explicit override for which local branch to checkout to Last updated on [Previous\ \ but setup](https://docs.gitbutler.com/commands/but-setup) [Next\ \ but status](https://docs.gitbutler.com/commands/but-status) ### On this page [Examples](https://docs.gitbutler.com/commands/but-teardown#examples) [Options](https://docs.gitbutler.com/commands/but-teardown#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-teardown.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-teardown%22) --- # but discard | GitButler Docs Commands \>\_ but discard =========== Discard branches, commits, or changes. Changes may be selected by branch, commit, committed file, uncommitted file, or uncommitted hunk CLI ID. Use `zz`, or omit ``, to discard all uncommitted changes. All provided changes must be the same kind. Committed files must come from the same commit. The entire operation is recorded as a single oplog entry, so it can be undone with `but undo`. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but discard [CHANGES]` [Arguments](https://docs.gitbutler.com/commands/but-discard#arguments) ----------------------------------------------------------------------- * `` — One or more branches, commits, or changes to discard. If omitted all uncommitted changes will be discarded. Last updated on [Previous\ \ but branch](https://docs.gitbutler.com/commands/but-branch) [Next\ \ but resolve](https://docs.gitbutler.com/commands/but-resolve) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-discard#arguments) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-discard.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-discard%22) --- # but reword | GitButler Docs Commands \>\_ but reword ========== Edit the commit message of the specified commit. 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 recreate 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](https://docs.gitbutler.com/commands/but-reword#arguments) ---------------------------------------------------------------------- * `` — Commit ID to edit the message for, or branch ID to rename (required) [Options](https://docs.gitbutler.com/commands/but-reword#options) ------------------------------------------------------------------ * `-m`, `--message` `` — The new commit message or branch name. If not provided, opens an editor * `-f`, `--fix-formatting` — Format the existing commit message to 72-char line wrapping without opening an editor * `--diff` — Always show diff inside the editor. By default the diff will be shown unless it's large. The diff will always be shown if --diff is passed, regardless of the size of the diff. (default: `false`) * `--no-diff` — Never show the diff inside the editor (default: `false`) * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but absorb](https://docs.gitbutler.com/commands/but-absorb) [Next\ \ but uncommit](https://docs.gitbutler.com/commands/but-uncommit) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-reword#arguments) [Options](https://docs.gitbutler.com/commands/but-reword#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-reword.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-reword%22) --- # but status | GitButler Docs Commands \>\_ but status ========== Overview of the project workspace state. This shows uncommitted files, 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](https://docs.gitbutler.com/commands/but-status#examples) -------------------------------------------------------------------- Normal usage: but status Shorthand with listing files modified but status -f **Usage:** `but status [OPTIONS]` [Options](https://docs.gitbutler.com/commands/but-status#options) ------------------------------------------------------------------ * `-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`) Last updated on [Previous\ \ but teardown](https://docs.gitbutler.com/commands/but-teardown) [Next\ \ but diff](https://docs.gitbutler.com/commands/but-diff) ### On this page [Examples](https://docs.gitbutler.com/commands/but-status#examples) [Options](https://docs.gitbutler.com/commands/but-status#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-status.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-status%22) --- # but setup | GitButler Docs Commands \>\_ but setup ========= Sets up a GitButler project from a git repository in the current directory. 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. [Examples](https://docs.gitbutler.com/commands/but-setup#examples) ------------------------------------------------------------------- Initialize a new git repository and set up GitButler: but setup --init **Usage:** `but setup [OPTIONS]` [Options](https://docs.gitbutler.com/commands/but-setup#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. Last updated on [Previous\ \ Commands Overview](https://docs.gitbutler.com/commands/commands-overview) [Next\ \ but teardown](https://docs.gitbutler.com/commands/but-teardown) ### On this page [Examples](https://docs.gitbutler.com/commands/but-setup#examples) [Options](https://docs.gitbutler.com/commands/but-setup#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-setup.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-setup%22) --- # but unapply | GitButler Docs Commands \>\_ but unapply =========== Unapply a branch. 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 `. 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`. The identifier can be: * A CLI ID pointing to a stack or branch (e.g., "bu" from `but status`) * A branch name If a branch name (or an identifier pointing to a branch) is provided, the entire stack containing that branch will be unapplied. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but unapply ` [Arguments](https://docs.gitbutler.com/commands/but-unapply#arguments) ----------------------------------------------------------------------- * `` — The branch or stack to unapply (required) Last updated on [Previous\ \ but resolve](https://docs.gitbutler.com/commands/but-resolve) [Next\ \ but apply](https://docs.gitbutler.com/commands/but-apply) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-unapply#arguments) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-unapply.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-unapply%22) --- # but amend | GitButler Docs Commands \>\_ but amend ========= Amend uncommitted changes into a commit or branch. Sources must be uncommitted files or hunks. To move changes that are already committed, or to combine commits, use `but squash`. If the target is a branch, the changes are amended into that branch's newest commit (its tip). Name the commit explicitly to amend into anything below the tip. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but amend [SOURCES] [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-amend#arguments) --------------------------------------------------------------------- * `` — One or more uncommitted files or hunks to amend. If omitted, all changes in the uncommitted area (zz) are amended. [Options](https://docs.gitbutler.com/commands/but-amend#options) ----------------------------------------------------------------- * `-t`, `--target` `` — The commit or branch to amend into (required) * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but uncommit](https://docs.gitbutler.com/commands/but-uncommit) [Next\ \ but squash](https://docs.gitbutler.com/commands/but-squash) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-amend#arguments) [Options](https://docs.gitbutler.com/commands/but-amend#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-amend.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-amend%22) --- # but worktree | GitButler Docs Commands \>\_ but worktree ============ Manage linked worktrees (experimental, requires the \`worktreeManipulation\` feature flag). Without a subcommand, lists the worktrees. **Usage:** `but worktree ` [Subcommands](https://docs.gitbutler.com/commands/but-worktree#subcommands) ---------------------------------------------------------------------------- ### [`but worktree list`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-list) List linked worktrees, most recently updated first. By default this lists every active worktree and the three most recently updated archived ones. A worktree is shown by its name, followed by the branch it has checked out when that differs from the name, and its path. **Usage:** `but worktree list [OPTIONS]` **Options:** * `--archived` — List all archived worktrees * `--active` — List all active worktrees ### [`but worktree archive`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-archive) Hide a worktree from the workspace **Usage:** `but worktree archive ` **Arguments:** * `` — The worktree, by CLI ID (see but wt list) or name (required) ### [`but worktree unarchive`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-unarchive) Show an archived worktree in the workspace again **Usage:** `but worktree unarchive ` **Arguments:** * `` — The worktree, by CLI ID (see but wt list) or name (required) ### [`but worktree remove`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-remove) Remove a worktree from disk, like `git worktree remove`. This works on archived worktrees too, and keeps the branch the worktree had checked out. **Usage:** `but worktree remove [OPTIONS]` **Arguments:** * `` — The worktree, by CLI ID (see but wt list) or name (required) **Options:** * `-f`, `--force` — Remove the worktree even if it has uncommitted changes Last updated on [Previous\ \ but open](https://docs.gitbutler.com/commands/but-open) [Next\ \ Workspace Branch](https://docs.gitbutler.com/workspace-branch) ### On this page [Subcommands](https://docs.gitbutler.com/commands/but-worktree#subcommands) [`but worktree list`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-list) [`but worktree archive`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-archive) [`but worktree unarchive`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-unarchive) [`but worktree remove`](https://docs.gitbutler.com/commands/but-worktree#but-worktree-remove) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-worktree.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-worktree%22) --- # but uncommit | GitButler Docs Commands \>\_ but uncommit ============ Uncommit commits, branches, or committed files. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but uncommit [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-uncommit#arguments) ------------------------------------------------------------------------ * `` — One or more commits, branches, or committed files to uncommit. Sources must all be the same kind. (required) [Options](https://docs.gitbutler.com/commands/but-uncommit#options) -------------------------------------------------------------------- * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but reword](https://docs.gitbutler.com/commands/but-reword) [Next\ \ but amend](https://docs.gitbutler.com/commands/but-amend) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-uncommit#arguments) [Options](https://docs.gitbutler.com/commands/but-uncommit#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-uncommit.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-uncommit%22) --- # but show | GitButler Docs Commands \>\_ but show ======== Shows detailed information about a commit or branch. 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. [Examples](https://docs.gitbutler.com/commands/but-show#examples) ------------------------------------------------------------------ Show commit details by short commit ID: but show a1b2c3d Show commit details by CLI ID: but show c5 Show branch commits by branch name: but show my-feature-branch Show branch with full commit details: but show my-feature-branch --verbose **Usage:** `but show [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-show#arguments) -------------------------------------------------------------------- * `` — The commit ID (short or full SHA), branch name, or CLI ID to show details for (required) [Options](https://docs.gitbutler.com/commands/but-show#options) ---------------------------------------------------------------- * `-v`, `--verbose` — Show full commit messages and files changed for each commit Last updated on [Previous\ \ but diff](https://docs.gitbutler.com/commands/but-diff) [Next\ \ but help cli-ids](https://docs.gitbutler.com/commands/but-help-cli-ids) ### On this page [Examples](https://docs.gitbutler.com/commands/but-show#examples) [Arguments](https://docs.gitbutler.com/commands/but-show#arguments) [Options](https://docs.gitbutler.com/commands/but-show#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-show.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-show%22) --- # but move | GitButler Docs Commands \>\_ but move ======== Move commits and changes around. Move a set of `` around relative to a `TARGET`. `` is a set of commits, a set of committed files or a single branch. You are not allowed to mix kinds of sources (e.g. commits and committed files) in a single command. `TARGET` is one of `--above`, `--below`, `--unstack` or `--branch` and defines how `` should be moved. Depending on how `` and `TARGET` are combined, a commit and/or branch may be created as part of the move. **A branch is created when:** * You move a commit or committed file relative to a branch * You unstack a commit or committed file **A commit is created when:** * You move a committed file relative to a commit or branch * You unstack a committed file Note the overlap between the above conditions. For example, unstacking a committed file both creates a new commit for the file and a branch for the commit. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but move [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-move#arguments) -------------------------------------------------------------------- * `` — One or more sources to move. You may provide one of the following kinds of sources: * Commits * Committed files * All files must come from the same commit * A branch * Branches can only be moved one at a time Mixing sources in a single command is not allowed. The order of the sources does not matter. Providing any of the sources as an argument for a target such as --above or --below is an error. (required) [Options](https://docs.gitbutler.com/commands/but-move#options) ---------------------------------------------------------------- * `-b`, `--branch` `` — Place on the branch BRANCH. If BRANCH exists, commits or committed files are moved onto its tip. A branch source is instead stacked on top of BRANCH, equivalent to --above BRANCH. If BRANCH does not exist, it is created as an unstacked branch for commit or committed-file sources. Using a branch source with a nonexistent BRANCH is an error. If BRANCH is a linked worktree or a branch checked out in one, commit or committed-file sources are moved onto the tip of that worktree's branch. If BRANCH is omitted, an unstacked branch with a generated name is created. This is exactly equivalent to --unstack and is allowed for any source kind. Attempting to place on a branch that exists but is not applied is an error. * `-A`, `--above` `` — Place above BRANCH\_OR\_COMMIT. If BRANCH\_OR\_COMMIT is a commit, are placed on the same branch as the targeted commit. If BRANCH\_OR\_COMMIT is a branch, the sources are placed on a new branch above the targeted branch. This target is applicable for all kinds of . * `-B`, `--below` `` — Place below BRANCH\_OR\_COMMIT. If BRANCH\_OR\_COMMIT is a commit, the are placed on the same branch as the targeted commit. If BRANCH\_OR\_COMMIT is a branch, are placed on a new branch below the targeted branch. Branches are treated as buckets, meaning that "below a branch" is treated as below the oldest ancestor on that branch. If BRANCH\_OR\_COMMIT is a linked worktree, are placed on the tip of the branch that worktree has checked out. This target is only applicable for that are commits or committed files. * `--unstack` — Unstack from their current stacks. \--unstack does not take an argument, so --unstack and --unstack are equivalent. * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but squash](https://docs.gitbutler.com/commands/but-squash) [Next\ \ but oplog](https://docs.gitbutler.com/commands/but-oplog) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-move#arguments) [Options](https://docs.gitbutler.com/commands/but-move#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-move.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-move%22) --- # but commit | GitButler Docs Commands \>\_ but commit ========== Create a commit. By default, all uncommitted changes are included in the commit. This can be controlled with change flags such as `--empty` and `--interactive`, or by providing `CHANGES` as positional arguments. If there are no branches applied, a new branch is created for the commit. If there is only one stack of branches applied, the commit is placed at the tip of that stack. Otherwise, the targeting flags `--above`, `--below` and `--branch` control where the commit is placed. Note that only one of the targeting flags can be provided at a time. The commit is expected to have a commit message unless `--no-message` is provided. If neither of `--no-message` nor `--message` is provided, the user's preferred editor is opened to input a message. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but commit [CHANGES] [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-commit#arguments) ---------------------------------------------------------------------- * `` — One or more changes to commit. A change can either be a file or a hunk. [Options](https://docs.gitbutler.com/commands/but-commit#options) ------------------------------------------------------------------ * `-m`, `--message` `` — The message to use for the commit. Can be supplied any amount of times, each value being appended to the preceding ones with a blank line in between. * `--no-message` — Creates the commit without a commit message * `-b`, `--branch` `` — Place the commit on the branch BRANCH. If BRANCH does not exist, it is created as an unstacked branch. If BRANCH is omitted, an unstacked branch with a generated name is created. If BRANCH is a linked worktree or a branch checked out in one, the commit is placed on the tip of that worktree's branch. Attempting to place a commit on a branch that exists but is not applied is an error. * `-A`, `--above` `` — Place the commit above BRANCH\_OR\_COMMIT, which must be an applied branch or commit. If BRANCH\_OR\_COMMIT is a commit, the new commit is placed on the same branch as the targeted commit. If BRANCH\_OR\_COMMIT is a branch, the new commit is placed on a new branch above the targeted branch. * `-B`, `--below` `` — Place the commit below BRANCH\_OR\_COMMIT, which must be an applied branch or commit. If BRANCH\_OR\_COMMIT is a commit, the new commit is placed on the same branch as the targeted commit. If BRANCH\_OR\_COMMIT is a branch, the new commit is placed on a new branch below the targeted branch. Branches are treated as buckets, meaning that "below a branch" is treated as below the oldest ancestor on that branch. If BRANCH\_OR\_COMMIT is a linked worktree, the new commit is placed on the tip of the branch that worktree has checked out. * `--empty` — Forces the commit to be empty regardless of repository state * `-i`, `--interactive` — Open the TUI to interactively select what to commit * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but help cli-ids](https://docs.gitbutler.com/commands/but-help-cli-ids) [Next\ \ but branch](https://docs.gitbutler.com/commands/but-branch) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-commit#arguments) [Options](https://docs.gitbutler.com/commands/but-commit#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-commit.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-commit%22) --- # but land | GitButler Docs Commands \>\_ but land ======== Land a branch directly onto the target branch. Lands the branch onto the configured target (for example `origin/master`) without going through a pull request — the "just push to the target" workflow. By default the target is fast-forwarded to the branch tip when possible (no merge commit); otherwise a merge commit is created. For a local (`gb-local`) target the refs are moved locally; otherwise the result is pushed to the remote. After landing, the remaining applied branches are reconciled onto the moved target, just like `but pull`. Requires an active GitButler workspace. Updating the target is direct and not easily reversible, so a confirmation is required (use `--yes` to skip it in scripts). When NOT to use this: if your project lands changes through pull requests / code review, use `but push` and open a PR (`but pr new`) instead — `but land` deliberately bypasses that process. On a real remote, a branch protected against direct pushes will reject the land. Landing a segment with other segments below it is refused unless `--whole-stack` is passed with the stack's top segment, which lands the entire stack. [Examples](https://docs.gitbutler.com/commands/but-land#examples) ------------------------------------------------------------------ Land a branch by its CLI ID: but land bu Land a branch by name, forcing a merge commit: but land my-feature-branch --no-ff Land an entire stack by naming its top segment: but land top-branch --whole-stack **Usage:** `but land [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-land#arguments) -------------------------------------------------------------------- * `` — Branch ID or name to land onto the target branch (required) [Options](https://docs.gitbutler.com/commands/but-land#options) ---------------------------------------------------------------- * `--yes` — Skip the confirmation prompt * `--no-ff` — Always create a merge commit, even when the branch can be fast-forwarded * `--whole-stack` — Land the entire stack: BRANCH must be the top segment, and the segments below it are published to the target along with it Last updated on [Previous\ \ but pr](https://docs.gitbutler.com/commands/but-pr) [Next\ \ but absorb](https://docs.gitbutler.com/commands/but-absorb) ### On this page [Examples](https://docs.gitbutler.com/commands/but-land#examples) [Arguments](https://docs.gitbutler.com/commands/but-land#arguments) [Options](https://docs.gitbutler.com/commands/but-land#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-land.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-land%22) --- # but branch | GitButler Docs Commands \>\_ but branch ========== Commands for managing 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`. To rename an applied branch, use `but reword -m `. **Usage:** `but branch ` [Subcommands](https://docs.gitbutler.com/commands/but-branch#subcommands) -------------------------------------------------------------------------- ### [`but branch new`](https://docs.gitbutler.com/commands/but-branch#but-branch-new) Create a new branch. Use `--above` or `--below` to created stacked branches. Omitting these create a new unstacked branch. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but branch new [NAME] [OPTIONS]` **Arguments:** * `` — Name of the new branch. If omitted the new branch will get a generated name. **Options:** * `-A`, `--above` `` — Place the branch above BRANCH\_OR\_COMMIT, which must be an applied branch or commit. If BRANCH\_OR\_COMMIT is a commit, the new branch is created above the commit. If BRANCH\_OR\_COMMIT is a branch, the new branch is created above the targeted branch. * `-B`, `--below` `` — Place the branch below BRANCH\_OR\_COMMIT, which must be an applied branch or commit. If BRANCH\_OR\_COMMIT is a commit, the new branch is created below the commit. If BRANCH\_OR\_COMMIT is a branch, the new branch is created below the targeted branch. * `-s`, `--switch` — Switch to the newly created branch instead of applying it to the GitButler workspace * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. ### [`but branch delete`](https://docs.gitbutler.com/commands/but-branch#but-branch-delete) Delete branchs from the workspace **Usage:** `but branch delete ` **Arguments:** * `` — One or more branches to delete (required) ### [`but branch list`](https://docs.gitbutler.com/commands/but-branch#but-branch-list) List the branches in the repository By default, shows the active branch and the 20 most recently updated branches. You can use the `--all` flag to show all branches, `--local` to show only local branches, or `--remote` to show only remote branches. You can also filter branch names by specifying a substring, such as `but branch list feature` to show only branches with "feature" in the name. If you want to check for review status, you can add `--review` to fetch and display pull request or merge request information for each branch. This will make the command slower as it needs to query the forge. By default, the command checks if each branch merges cleanly into the _upstream base target branch_ (not your workspace). You can disable this check with `--no-check` to make the command faster. By default it also calculates the number of commits each branch is ahead of the base branch. You can disable this with `--no-ahead` to make the command faster. **Usage:** `but branch list [FILTER] [OPTIONS]` **Arguments:** * `` — Filter branches by name (case-insensitive substring match) **Options:** * `-l`, `--local` — Show only local branches * `-r`, `--remote` — Show only remote branches * `-a`, `--all` — Show all branches (not just active + 20 most recent) * `--no-ahead` — Don't calculate and show number of commits ahead of base (faster) * `--review` — Fetch and display review information (PRs, MRs, etc.) * `--no-check` — Don't check if each branch merges cleanly into upstream * `--empty` — Include branches with no commits on them (hidden by default) ### [`but branch show`](https://docs.gitbutler.com/commands/but-branch#but-branch-show) Show commits ahead of base for a specific branch This shows the list of commits that are on the specified branch but not yet integrated into the base target branch. You can also choose to fetch and display review information, show files modified in each commit with line counts, generate an AI summary of the branch changes, and check if the branch merges cleanly into upstream. **Usage:** `but branch show [OPTIONS]` **Arguments:** * `` — CLI ID or name of the branch to show (required) **Options:** * `-r`, `--review` — Fetch and display review information * `-f`, `--files` — Show files modified in each commit with line counts * `--ai` — Generate AI summary of the branch changes * `--check` — Check if the branch merges cleanly into upstream and identify conflicting commits ### [`but branch update`](https://docs.gitbutler.com/commands/but-branch#but-branch-update) Update your local branch with the content of its remote counterpart. This allows you to resolve the divergence between your local branch and its tracked remote in different ways. **Usage:** `but branch update [OPTIONS]` **Arguments:** * `` — Name of the local branch to integrate (required) **Options:** * `-s`, `--strategy` `` — Strategy to use for the integration. If no strategy is specified, we default to pull-rebase (default: `pull-rebase`) * `--dry-run` — Preview the resulting branch state without persisting changes * `-v`, `--verbose` — Show additional dry-run details like the current divergence * `-i`, `--interactive` — Open the generated integration script in an editor Last updated on [Previous\ \ but commit](https://docs.gitbutler.com/commands/but-commit) [Next\ \ but discard](https://docs.gitbutler.com/commands/but-discard) ### On this page [Subcommands](https://docs.gitbutler.com/commands/but-branch#subcommands) [`but branch new`](https://docs.gitbutler.com/commands/but-branch#but-branch-new) [`but branch delete`](https://docs.gitbutler.com/commands/but-branch#but-branch-delete) [`but branch list`](https://docs.gitbutler.com/commands/but-branch#but-branch-list) [`but branch show`](https://docs.gitbutler.com/commands/but-branch#but-branch-show) [`but branch update`](https://docs.gitbutler.com/commands/but-branch#but-branch-update) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-branch.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-branch%22) --- # but pr | GitButler Docs Commands \>\_ but pr ====== Commands for creating and managing reviews on a forge, e.g. GitHub PRs or GitLab MRs. If you are authenticated with a forge using but config forge auth, you can use the but pr or but mr 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 [OPTIONS]` [Subcommands](https://docs.gitbutler.com/commands/but-pr#subcommands) ---------------------------------------------------------------------- ### [`but pr new`](https://docs.gitbutler.com/commands/but-pr#but-pr-new) Create a new review for a branch. If no branch is specified, you will be prompted to select one. If there is only one branch without a review, you will be asked to confirm. If the branch is part of a stack, GitButler pushes that branch and its ancestors and creates missing reviews from the bottom upward. It also updates stack metadata using native GitHub stacks when enabled and supported, or review descriptions otherwise. **Usage:** `but pr new [BRANCH] [OPTIONS]` **Arguments:** * `` — The branch to create a review for **Options:** * `-m`, `--message` `` — review title and description. The first line is the title, the rest is the description * `-F`, `--file` `` — Read review 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 * `--no-hooks` — Bypass pre-push hooks * `-t`, `--default` — Use the default content for the review title and description, skipping any prompts. If the branch contains only a single commit, the commit message will be used (default: `false`) * `-d`, `--draft` — Whether to create reviews as a draft (default: `false`) ### [`but pr auto-merge`](https://docs.gitbutler.com/commands/but-pr#but-pr-auto-merge) Enable or disable the automatic merging of a review or reviews. If no reviews are specified, you will be prompted to select one or multiple of the review associated with branches in your workspace **Usage:** `but pr auto-merge [SELECTOR] [OPTIONS]` **Arguments:** * `` — The target of this operation. This can be one or multiple (comma-separated): * Branch names, * Branch IDs, * Stack IDs (in which case, all the reviews associated with the stacked branches are selected), * Associated review IDs (i.e. PR numeric IDs or MR numeric IDs, without the symbol). **Options:** * `-d`, `--off` — Whether to disable the automatic merging of the review(s) (default: `false`) ### [`but pr set-draft`](https://docs.gitbutler.com/commands/but-pr#but-pr-set-draft) Set an existing review (or set of reviews) as draft. If no reviews are specified, you will be prompted to select one or multiple of the review associated with branches in your workspace **Usage:** `but pr set-draft [SELECTOR]` **Arguments:** * `` — The target of this operation. This can be one or multiple (comma-separated): * Branch names, * Branch IDs, * Stack IDs (in which case, all the reviews associated with the stacked branches are selected), * Associated review IDs (i.e. PR numeric IDs or MR numeric IDs, without the symbol). ### [`but pr set-ready`](https://docs.gitbutler.com/commands/but-pr#but-pr-set-ready) Set an existing review (or set of reviews) as ready-to-review. If no reviews are specified, you will be prompted to select one or multiple of the review associated with branches in your workspace **Usage:** `but pr set-ready [SELECTOR]` **Arguments:** * `` — The target of this operation. This can be one or multiple (comma-separated): * Branch names, * Branch IDs, * Stack IDs (in which case, all the reviews associated with the stacked branches are selected), * Associated review IDs (i.e. PR numeric IDs or MR numeric IDs, without the symbol). ### [`but pr template`](https://docs.gitbutler.com/commands/but-pr#but-pr-template) Configure the template to use for review descriptions. This will list all available templates found in the repository and allow you to select one **Usage:** `but pr template [TEMPLATE_PATH]` **Arguments:** * `` — Path to the review template file within the repository [Options](https://docs.gitbutler.com/commands/but-pr#options) -------------------------------------------------------------- * `-d`, `--draft` — Whether to create reviews as a draft (default: `false`) Last updated on [Previous\ \ but pull](https://docs.gitbutler.com/commands/but-pull) [Next\ \ but land](https://docs.gitbutler.com/commands/but-land) ### On this page [Subcommands](https://docs.gitbutler.com/commands/but-pr#subcommands) [`but pr new`](https://docs.gitbutler.com/commands/but-pr#but-pr-new) [`but pr auto-merge`](https://docs.gitbutler.com/commands/but-pr#but-pr-auto-merge) [`but pr set-draft`](https://docs.gitbutler.com/commands/but-pr#but-pr-set-draft) [`but pr set-ready`](https://docs.gitbutler.com/commands/but-pr#but-pr-set-ready) [`but pr template`](https://docs.gitbutler.com/commands/but-pr#but-pr-template) [Options](https://docs.gitbutler.com/commands/but-pr#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-pr.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-pr%22) --- # but skill | GitButler Docs Commands \>\_ but skill ========= Manage AI agent skills for GitButler. Skills provide enhanced AI capabilities for working with GitButler through Claude Code, Codex, and other AI assistants. Use `but skill install` to install the GitButler skill files. By default, it prompts for scope (repository or global home directory) and then format. When run outside a git repository, local scope is unavailable and the default install location is global (home directory). You can still install to a custom location with `--path` using an absolute or `~` path. [Examples](https://docs.gitbutler.com/commands/but-skill#examples) ------------------------------------------------------------------- Install interactively (prompts for scope and format): but skill install Install the skill globally: but skill install --global **Usage:** `but skill ` [Subcommands](https://docs.gitbutler.com/commands/but-skill#subcommands) ------------------------------------------------------------------------- ### [`but skill install`](https://docs.gitbutler.com/commands/but-skill#but-skill-install) Install the GitButler CLI skill files for Coding agents By default, the command prompts you to choose installation scope first (current repository or global home directory), then prompts you to select a skill folder format (Agent Skills / .agents, Claude Code, OpenCode, Codex, GitHub Copilot, Cursor, Windsurf, Poolside) unless you specify a custom path with --path. When run outside a git repository, local scope is unavailable and the default install location is global (home directory). You can still install to a custom location with `--path` using an absolute or `~` path. Use --global to install the skill in a global location instead of the current repository. In non-interactive mode, a detected agent uses its global skill directory; otherwise specify --path or --detect. [Examples](https://docs.gitbutler.com/commands/but-skill#examples-1) --------------------------------------------------------------------- Install interactively (prompts for scope and format): but skill install Install globally (prompts for format): but skill install --global Install to a custom path: but skill install --path .agents/skills/gitbutler Auto-detect installation location (update existing installations): but skill install --detect **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). Outside a repository, relative paths require --global * `-d`, `--detect` — Refresh existing installations in place, updating every GitButler skill found in the current scope (local before global) ### [`but skill check`](https://docs.gitbutler.com/commands/but-skill#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](https://docs.gitbutler.com/commands/but-skill#examples-2) --------------------------------------------------------------------- Check all installed skills: but skill check Check and automatically update outdated skills: but skill check --update Check only global installations: 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 Last updated on [Previous\ \ but agent](https://docs.gitbutler.com/commands/but-agent) [Next\ \ but open](https://docs.gitbutler.com/commands/but-open) ### On this page [Examples](https://docs.gitbutler.com/commands/but-skill#examples) [Subcommands](https://docs.gitbutler.com/commands/but-skill#subcommands) [`but skill install`](https://docs.gitbutler.com/commands/but-skill#but-skill-install) [Examples](https://docs.gitbutler.com/commands/but-skill#examples-1) [`but skill check`](https://docs.gitbutler.com/commands/but-skill#but-skill-check) [Examples](https://docs.gitbutler.com/commands/but-skill#examples-2) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-skill.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-skill%22) --- # but help cli-ids | GitButler Docs Commands \>\_ but help cli-ids ================ Smart IDs to reference commits, branches and more in \`but\`. CLI IDs are used by `but` to reference things such as commits, branches and files. While obvious identifiers like full commit hashes and entire branch names are viable CLI IDs, there are also various shorter identifiers that can be used in place of the full names. In general, `but status` will show all currently available CLI IDs in front of the "thing". Typical CLI IDs include: * **Commit:** * The entire commit ID * The entire change ID * Any prefix of the commit ID or change ID that is unique in the current context. `but status` highlights the shortest possible prefix. * **Branch:** * The entire branch name * An exact short ID for the branch name, as shown by `but status` * **Uncommitted file:** A path-derived ID that is typically 1-3 characters * **Uncommitted hunk:** `:` * Run `but diff` to show all current uncommitted hunks and their IDs * **Uncommitted area:** Always `zz` * **Committed file:** `:` * Run `but status -f` to show committed files Many CLI IDs depend on the context and may change if the context changes, such as when new data is written to files, commits are made or rearranged and branches are created or deleted. Some CLI IDs are more stable than others. For example, a commit's change ID is stable even when commits are made and moved around, but the minimum prefix may increase as other IDs are introduced. Most but not all commands accept CLI IDs to perform various actions. See the documentation for the individual command (`but --help`) for details on how to use CLI IDs for that command in particular. **Usage:** `but help cli-ids` Last updated on [Previous\ \ but show](https://docs.gitbutler.com/commands/but-show) [Next\ \ but commit](https://docs.gitbutler.com/commands/but-commit) ### On this page No Headings [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-help-cli-ids.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-help-cli-ids%22) --- # Commands Overview | GitButler Docs Commands \>\_ Commands Overview ================= Your fast index to all of the available commands [Command reference](https://docs.gitbutler.com/commands/commands-overview#command-reference) --------------------------------------------------------------------------------------------- ### [Basics](https://docs.gitbutler.com/commands/commands-overview#basics) * [setup](https://docs.gitbutler.com/commands/but-setup) : Set up a Git repository to be managed by GitButler * [teardown](https://docs.gitbutler.com/commands/but-teardown) : Exit GitButler mode and return to normal Git ### [Inspection](https://docs.gitbutler.com/commands/commands-overview#inspection) * [status](https://docs.gitbutler.com/commands/but-status) : Show the project workspace state * [diff](https://docs.gitbutler.com/commands/but-diff) : Show a diff for the workspace or a CLI ID * [show](https://docs.gitbutler.com/commands/but-show) : Show information about a commit or branch * [help cli-ids](https://docs.gitbutler.com/commands/but-help-cli-ids) : Learn how to use IDs from command output ### [Branching and committing](https://docs.gitbutler.com/commands/commands-overview#branching-and-committing) * [commit](https://docs.gitbutler.com/commands/but-commit) : Commit changes to a stack * [branch](https://docs.gitbutler.com/commands/but-branch) : Commands for managing branches * [discard](https://docs.gitbutler.com/commands/but-discard) : Discard uncommitted changes * [resolve](https://docs.gitbutler.com/commands/but-resolve) : Resolve conflicts in a commit * [unapply](https://docs.gitbutler.com/commands/but-unapply) : Unapply a branch from the workspace * [apply](https://docs.gitbutler.com/commands/but-apply) : Apply a branch to the workspace * [clean](https://docs.gitbutler.com/commands/but-clean) : Remove empty branches from the workspace * [pick](https://docs.gitbutler.com/commands/but-pick) : Cherry-pick a commit from an unapplied branch ### [Server interactions](https://docs.gitbutler.com/commands/commands-overview#server-interactions) * [push](https://docs.gitbutler.com/commands/but-push) : Push changes in a branch to remote * [pull](https://docs.gitbutler.com/commands/but-pull) : Pull upstream changes and update your branches * [pr](https://docs.gitbutler.com/commands/but-pr) : Create and manage reviews on GitHub, GitLab, and other forges * [land](https://docs.gitbutler.com/commands/but-land) : Land a branch directly onto the target branch ### [Editing commits](https://docs.gitbutler.com/commands/commands-overview#editing-commits) * [absorb](https://docs.gitbutler.com/commands/but-absorb) : Amend changes into the commits where they belong * [reword](https://docs.gitbutler.com/commands/but-reword) : Edit a commit message or branch name * [uncommit](https://docs.gitbutler.com/commands/but-uncommit) : Move commit changes back to the uncommitted area * [amend](https://docs.gitbutler.com/commands/but-amend) : Amend a file change into a commit * [squash](https://docs.gitbutler.com/commands/but-squash) : Squash commits together * [move](https://docs.gitbutler.com/commands/but-move) : Move a commit or branch to a different location ### [Operations log](https://docs.gitbutler.com/commands/commands-overview#operations-log) * [oplog](https://docs.gitbutler.com/commands/but-oplog) : View and manage operation history * [undo](https://docs.gitbutler.com/commands/but-undo) : Undo the last operation * [redo](https://docs.gitbutler.com/commands/but-redo) : Redo the last undo ### [Helper commands](https://docs.gitbutler.com/commands/commands-overview#helper-commands) * [gui](https://docs.gitbutler.com/commands/but-gui) : Open the GitButler GUI for the current project * [tui](https://docs.gitbutler.com/commands/but-tui) : Open the interactive terminal UI * [update](https://docs.gitbutler.com/commands/but-update) : Manage GitButler CLI and app updates * [completions](https://docs.gitbutler.com/commands/but-completions) : Generate shell completions * [alias](https://docs.gitbutler.com/commands/but-alias) : Manage command aliases * [config](https://docs.gitbutler.com/commands/but-config) : View and manage GitButler configuration * [agent](https://docs.gitbutler.com/commands/but-agent) : Set up GitButler for AI coding agents * [skill](https://docs.gitbutler.com/commands/but-skill) : Manage AI agent skills for GitButler Last updated on [Previous\ \ Wrap Up](https://docs.gitbutler.com/cli-guides/cli-tutorial/conclusion) [Next\ \ but setup](https://docs.gitbutler.com/commands/but-setup) ### On this page [Command reference](https://docs.gitbutler.com/commands/commands-overview#command-reference) [Basics](https://docs.gitbutler.com/commands/commands-overview#basics) [Inspection](https://docs.gitbutler.com/commands/commands-overview#inspection) [Branching and committing](https://docs.gitbutler.com/commands/commands-overview#branching-and-committing) [Server interactions](https://docs.gitbutler.com/commands/commands-overview#server-interactions) [Editing commits](https://docs.gitbutler.com/commands/commands-overview#editing-commits) [Operations log](https://docs.gitbutler.com/commands/commands-overview#operations-log) [Helper commands](https://docs.gitbutler.com/commands/commands-overview#helper-commands) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/commands-overview.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/commands-overview%22) --- # but agent | GitButler Docs Commands \>\_ but agent ========= Set up GitButler for AI coding agents. Runs a guided setup wizard for installing GitButler agent skills and writing workflow steering instructions into supported agent instruction files. [Examples](https://docs.gitbutler.com/commands/but-agent#examples) ------------------------------------------------------------------- Start the interactive setup wizard (`but agent setup` is equivalent): but agent Print the default generated steering text: but agent setup --print **Usage:** `but agent ` [Subcommands](https://docs.gitbutler.com/commands/but-agent#subcommands) ------------------------------------------------------------------------- ### [`but agent setup`](https://docs.gitbutler.com/commands/but-agent#but-agent-setup) Configure GitButler skills and workflow instructions for coding agents. Starts an interactive wizard that generates GitButler workflow steering, installs selected agent skills, and optionally writes the generated steering into agent instruction files. [Examples](https://docs.gitbutler.com/commands/but-agent#examples-1) --------------------------------------------------------------------- Start the setup wizard: but agent setup Print the default steering text without modifying files: but agent setup --print **Usage:** `but agent setup [OPTIONS]` **Options:** * `--print` — Print the default generated steering text without prompting or modifying files Last updated on [Previous\ \ but config](https://docs.gitbutler.com/commands/but-config) [Next\ \ but skill](https://docs.gitbutler.com/commands/but-skill) ### On this page [Examples](https://docs.gitbutler.com/commands/but-agent#examples) [Subcommands](https://docs.gitbutler.com/commands/but-agent#subcommands) [`but agent setup`](https://docs.gitbutler.com/commands/but-agent#but-agent-setup) [Examples](https://docs.gitbutler.com/commands/but-agent#examples-1) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-agent.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-agent%22) --- # but resolve | GitButler Docs Commands \>\_ but resolve =========== Resolve conflicts in a commit or in uncommitted files. When a commit is in a conflicted state (marked with conflicts during rebase), use this command to enter resolution mode, resolve the conflicts, and finalize. Uncommitted files marked `{conflicted}` by `but status` are resolved with `but resolve ...` once they hold the desired content (or were deleted). [Workflow](https://docs.gitbutler.com/commands/but-resolve#workflow) --------------------------------------------------------------------- 1. Enter resolution mode: `but resolve ` 2. Resolve conflicts in your editor (remove conflict markers) 3. Check remaining conflicts: `but resolve status` 4. Finalize resolution: `but resolve finish` Or cancel: `but resolve cancel` Alternatively, resolve with AI in one step: `but resolve --ai`, or `but resolve --ai` to resolve all conflicted commits, oldest first. When in resolution mode, `but status` will also show that you're resolving conflicts. **Usage:** `but resolve [TARGETS] [OPTIONS]` [Subcommands](https://docs.gitbutler.com/commands/but-resolve#subcommands) --------------------------------------------------------------------------- ### [`but resolve conflicts`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-conflicts) List the conflicts of a conflicted commit, without entering resolution mode. Each conflict is shown with its ours side (the new base the commit was rebased onto), the common ancestor, and its theirs side (the commit's own version), numbered per file for use with `but resolve apply`. **Usage:** `but resolve conflicts [COMMIT]` **Arguments:** * `` — A conflicted commit, or a branch (meaning its oldest conflicted commit). Defaults to the first conflicted branch's oldest conflicted commit ### [`but resolve apply`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-apply) Resolve conflicts of a conflicted commit, without entering resolution mode. Targets one conflict (`:`, numbers from `but resolve conflicts`) or every conflict in a file (`` with `--ours`/`--theirs`). The replacement content for mixed resolutions is read from `--file` or stdin. Resolving only some conflicts keeps the commit conflicted with the rest, so conflicts can be worked off incrementally; the commit id changes with every apply. Undo with `but undo`. **Usage:** `but resolve apply [OPTIONS]` **Arguments:** * `` — The conflicted file, optionally with a 1-based conflict number (:) (required) **Options:** * `--commit` `` — A conflicted commit, or a branch (meaning its oldest conflicted commit — branch names stay stable across applies, unlike commit ids). Defaults to the first conflicted branch's oldest conflicted commit * `--ours` — Take the ours side: the new base the commit was rebased onto * `--theirs` — Take the theirs side: the commit's own version * `--ai` — Let the configured AI model merge the targeted conflicts * `-F`, `--file` `` — Read the replacement content from this file (otherwise from stdin) ### [`but resolve status`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-status) Show the status of conflict resolution, listing remaining conflicted files. **Usage:** `but resolve status` ### [`but resolve finish`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-finish) Finalize conflict resolution and return to workspace mode. This commits the resolved changes, rebases any commits on top of the resolved commit, and returns to the normal workspace. **Usage:** `but resolve finish` ### [`but resolve cancel`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-cancel) Cancel conflict resolution and return to workspace mode. This discards all changes made during resolution and restores the workspace to its pre-resolution state. **Usage:** `but resolve cancel [OPTIONS]` **Options:** * `-f`, `--force` — Forcibly remove any changes made [Options](https://docs.gitbutler.com/commands/but-resolve#options) ------------------------------------------------------------------- * `--ai` — Resolve the conflicts with the configured AI model and apply the result. With a commit ID this resolves only that commit; without one it resolves all conflicted commits in the workspace, oldest first. Undo the result with but undo. Last updated on [Previous\ \ but discard](https://docs.gitbutler.com/commands/but-discard) [Next\ \ but unapply](https://docs.gitbutler.com/commands/but-unapply) ### On this page [Workflow](https://docs.gitbutler.com/commands/but-resolve#workflow) [Subcommands](https://docs.gitbutler.com/commands/but-resolve#subcommands) [`but resolve conflicts`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-conflicts) [`but resolve apply`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-apply) [`but resolve status`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-status) [`but resolve finish`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-finish) [`but resolve cancel`](https://docs.gitbutler.com/commands/but-resolve#but-resolve-cancel) [Options](https://docs.gitbutler.com/commands/but-resolve#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-resolve.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-resolve%22) --- # but pick | GitButler Docs Commands \>\_ but pick ======== Cherry-pick commits into an applied branch. Each source commit is copied to the target location as a new commit. If there are no branches applied, a new branch is created for the picked commits. If there is only one stack of branches applied, the commits are placed at the tip of that stack. Otherwise, the targeting flags `--above`, `--below`, and `--branch` control where the commits are placed. Only one targeting flag can be provided at a time. For more details about CLI IDs, see `but help cli-ids`. **Usage:** `but pick [OPTIONS]` [Arguments](https://docs.gitbutler.com/commands/but-pick#arguments) -------------------------------------------------------------------- * `` — The sources to cherry-pick (required) [Options](https://docs.gitbutler.com/commands/but-pick#options) ---------------------------------------------------------------- * `-b`, `--branch` `` — Place the picked commits on the branch BRANCH. If BRANCH does not exist, it is created as an unstacked branch. If BRANCH is omitted, an unstacked branch with a generated name is created. Attempting to pick onto a branch that exists but is not applied is an error. * `-A`, `--above` `` — Place the picked commits above BRANCH\_OR\_COMMIT. If BRANCH\_OR\_COMMIT is a commit, the picked commits are placed on the same branch as the targeted commit. If BRANCH\_OR\_COMMIT is a branch, the picked commits are placed on a new branch above the targeted branch. * `-B`, `--below` `` — Place the picked commits below BRANCH\_OR\_COMMIT. If BRANCH\_OR\_COMMIT is a commit, the picked commits are placed on the same branch as the targeted commit. If BRANCH\_OR\_COMMIT is a branch, the picked commits are placed on a new branch below the targeted branch. Branches are treated as buckets, meaning that "below a branch" is treated as below the oldest ancestor on that branch. * `--allow-merged` — Allow targeting branches and commits that are already merged upstream. By default, mutations refuse to touch history that has landed in the target branch, since the results tend to conflict on the next but pull. Last updated on [Previous\ \ but clean](https://docs.gitbutler.com/commands/but-clean) [Next\ \ but push](https://docs.gitbutler.com/commands/but-push) ### On this page [Arguments](https://docs.gitbutler.com/commands/but-pick#arguments) [Options](https://docs.gitbutler.com/commands/but-pick#options) [Edit on GitHub](https://github.com/gitbutlerapp/gitbutler-docs/blob/main/content/docs/commands/but-pick.mdx) [Give us feedback](https://github.com/gitbutlerapp/gitbutler-docs/issues/new?label=docs&title=Feedback+for+page+%22commands/but-pick%22) ---