DevOps  

Clean branches: The GitButler Way to Trunk-Based Development

GitButler is a new Git client that enhances developer workflow by enabling seamless multitasking and efficient version control management. Unlike traditional Git clients, GitButler introduces the concept of "virtual branches," allowing developers to work on multiple branches simultaneously within the same working directory. This approach minimizes context switching and branch creation, streamlining the development process.

Traditional Git Workflow v/s GitButler flow

Scenario: You are working on a feature, and a critical bug appears in production. This bug needs to be tackled now.

Traditional Git Workflow

  • You switch branches (like feature-1, bugfix-2, etc.) whenever you work on something new.
  • This means you must keep changing the state of your code, stash changes, or commit early to switch tasks.
  • It can get messy if you’re working on multiple things at the same time.

GitButler Flow

  • You stay on one base branch (such as primary or development).
  • You create virtual branches for each task without switching to a different code base.

Trunk-based development involves working on a single branch, typically the primary or master branch, and avoiding the creation of long-lived feature branches. However, there are some common fears that prevent developers from pushing to the central and adopting trunk-based development:

  1. Breaking the build. Since we need to commit to the master as regularly as possible, we might push unfinished code or bugs.
  2. Code isolation: Pushing unfinished code can pollute the entire codebase by introducing regressions and breaking other features.

How does GitButler help?

GitButler provides the concept of virtual branches.

A virtual branch is a local, lightweight representation of a line of work (such as a feature or bug fix), tracked by GitButler, but not an actual Git branch until you decide to push it.

They,

  • Exist only on your machine.
  • Track changes automatically by context (e.g., file paths, commit messages).
  • Let you work on multiple features or fixes in parallel without creating Git noise.

GitButler supports, but does not enforce, trunk-based development.

What does GitButler do?

  • Enables clean, local isolation of changes (via virtual branches).
  • Makes it easier to work on small, atomic units of work.
  • Helps you manage multiple tasks in parallel without polluting your Git repo.
  • Simplifies preparing code for integration, whether that involves a direct push or a pull request (PR).
  • Encourages local-first, fast-moving workflows.
  • Lowers the barrier to short-lived branches and atomic commits.

What does GitButler not do?

  • It does not force direct commits to the main branch.
  • It still requires you to push changes and optionally open PRs, which can become long-lived branches unless your team is disciplined.
  • It doesn’t replace a cultural or process commitment to continuous integration.

Getting started with GitButler

  • Install GitButler and sign in.
  • You will get this screen.
    GitButler
  • Clone the repository using the standard Git Bash.
  • Once done, click on ‘Add new project’ and select the one that you have just cloned.
    New Project
  • For best use of the tool, enable both options. For the second one, ensure your repository is on GitHub, as it will prompt you to authorize on GitHub.
  • The second option will not work if your repo is on Azure. Once done, click on ‘Let’s go’.
  • Once all setup is completed, you will get the following screen.
    Setup
  • From here, you can open VS Code and start working or create a new ‘virtual branch’
  • As soon as you create some files in VS Code, a new virtual branch is automatically created in GitButler.
     VS code
  • In VS Code, I have just created the index.html, index.css, and index.js. If you have authorized the GitHub feature, you can drag and drop files to generate a pull request (PR) directly. If not, you can create your PR as usual. For the sake of the demo, I will focus on the virtual branches and push the initial files directly.
  • After merging the initial files into the main branch and completing the PR, use GitButler and click on the refresh icon next to ‘Trunk’ in the left pane. You will see the following.
    Trunk
  • Click on ‘merge into common branch’ to update. By doing so, your ‘Workspace’ will be automatically updated and contain the latest changes.

The initial setup is done. Let’s get started with virtual branches.

Step 1. Begin writing the HTML code for the calculator app.

After typing and saving the first line, a new virtual branch is created automatically.

Calculator app

When you click on the changes in ‘Changed files’, a new pane will open with the changes made.

Changed files

Step 2. If you make some changes in the CSS file, this file will appear under ‘Changed files’.

CSS File

Note that after creating the two textboxes and applying the essential CSS, the web page appears as shown in the screenshot below.

Textboxes

Step 3. You can drag and drop the index.css file in the next column to create a new virtual branch just for the CSS changes.

Suppose this action does not work. Click on ‘New Branch+’ in the next column and drag the file you want to the new column.

New Branch

Step 4. To have a tidier workspace, you rename the virtual branches.

To do so, double click on the actual name (in our case ‘Virtual branch’ and ‘Virtual branch1’) of the branches and type the new name.

Workspace

Step 5. Here is one superpower of GitButler.

Let’s say, for some reason, you do not need the CSS changes. Usually, you would comment on the whole file.

When using GitButler, you can choose to unapply the CSS changes by clicking on the three dots under the virtual branch and selecting unapply.

Virtual branch

In GitButler, you will see that the virtual branch is no longer in the exact location. It is now under ‘Branches’.

Sandbox

When you refresh the webpage, you will see that the CSS change is removed.

Webpage

Step 6. To unapply the changes, click on the virtual branch name under ‘Branches’ and click on ‘Apply’.

Apply

You will see the virtual branch reappear in your workspace, and the CSS changes will be applied again.

You will also see a small history.

Small history

When you refresh your webpage, the CSS changes will be restored.

You will also see the CSS file back again in VS Code.

After making your changes to the file and saving it, the file will reappear in the virtual branch. It did not appear before because GitButler performed a kind of ‘virtual commit’ and did not display any changes.

Virtual commit

Note. This is particularly useful in situations where you are working on your development and an unforeseen bug is detected in production.

Instead of having to stash the changes related to your development or create a new branch for it, you can make a virtual branch for your development and a new one for the bug. Since each virtual branch is independent, the new virtual branch

will be based on the trunk, and you can work, commit, and push the fix for the bug, then seamlessly return to your development without needing to be a Git expert.

Step 7. Committing to virtual branches.

To do so, click on the ‘Start commit’ button.

You can either enter the commit message yourself or, if you have an OpenAI API token, enable the feature to generate a commit message using AI.

AI

You will see a history of the commit. Remember, this is a commit on the virtual branch. You will not see this on the actual branch or commit on GitHub or Azure.

Step 8. However, if you close GitButler and then reopen it, you will see the virtual branch and the commit.

When you click on ‘Push’, the virtual branch is pushed to the remote and becomes a non-virtual branch.

On GitButler, the virtual branch changes to the following.

Push

On the remote, we see our branch.

On remote

When we examine the commit, we will see the commit message that was entered when the virtual branch was committed.

Commit

Note. If a conflict arises in your virtual branch when updating the workspace after merging a pull request, GitButler will notify you.

Conclusion

GitButler offers a fresh, developer-centric approach to managing code, helping teams bridge the gap between conventional Git workflows and the fast-paced demands of Trunk-Based Development (TBD). By introducing local-first virtual branches, GitButler enables developers to work in isolated, focused units of change, eliminating the overhead of long-lived branches and constant context switching.

While GitButler doesn’t enforce TBD outright, it supports its core principles: frequent integration, rapid feedback, and a continuously releasable main branch. When combined with best practices such as small, fast merges, feature flags, and CI/CD automation, GitButler becomes a powerful enabler for teams transitioning to an actual DevOps model.

Importantly, GitButler is open-source, providing developers with complete transparency, flexibility, and the opportunity to shape the tool alongside the community. Whether you're modernizing your workflow or just aiming to ship more confidently and collaboratively, GitButler is a valuable ally in evolving how your team builds software.