# GitButler Rust Backend Architecture: A Deep Dive into the Modular Design

> Explore the GitButler Rust backend architecture featuring a modular crate design and a global Context for efficient virtual branch state and octopus-merge calculations.

- Repository: [GitButler/gitbutler](https://github.com/gitbutlerapp/gitbutler)
- Tags: architecture
- Published: 2026-02-16

---

**GitButler's Rust backend employs a layered crate architecture centered on a global Context, virtual branch state management, and octopus-merge workspace calculations to enable advanced stacked development workflows.**

GitButler is an open-source Git client that reimagines version control through virtual branches and stacked changes. The GitButler Rust backend architecture provides the foundation for these capabilities through a carefully modularized system of crates that handle repository context, persistent state, and high-level branch operations.

## Application Context and Global State

The **Context** (`but_ctx::Context`) serves as the central entry point for every backend operation. Defined in [`crates/but-ctx/src/lib.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/but-ctx/src/lib.rs), this struct provides lazy-loaded repository access, global settings, and thread-safe permission management.

The Context maintains:
- **Global settings** (`AppSettings`) loaded from the user configuration directory.
- **Lazy-loaded repositories** for both `gix` (pure-Rust) and `git2` (libgit2) via `OnDemand` wrappers.
- **Cached workspace projection** (`but_graph::projection::Workspace`) for fast access to the current working state.
- **Permission tokens** to prevent deadlocks during nested operations.

All mutable operations require explicit **permissions** obtained through `ctx.exclusive_worktree_access()` (for writes) or `ctx.shared_worktree_access()` (for reads). This design prevents deadlocks when nested calls also need repository locks.

```rust
use but_ctx::Context;

let ctx = Context::open("/path/to/repo")?;
let repo = ctx.repo.get()?;               // gix repository (fast diffing)
let git2 = ctx.git2_repo.get()?;          // libgit2 for legacy ops
let (repo, ws, db) = ctx.workspace_and_db()?; // Cached workspace + DB

```

## Virtual Branch Management

Virtual branches in GitButler are implemented as **Stacks**—user-visible work streams stored separately from Git's native ref namespace. The `gitbutler_stack` crate manages this state through three core types.

**Stack** ([`crates/gitbutler-stack/src/stack.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-stack/src/stack.rs)) represents a high-level virtual branch with an ID, display order, workspace inclusion flag, and branch heads.

**StackBranch** ([`crates/gitbutler-stack/src/stack_branch.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-stack/src/stack_branch.rs)) wraps individual Git references within a stack, storing the head OID, display name, and associated PR numbers.

**VirtualBranchesHandle** ([`crates/gitbutler-stack/src/state.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-stack/src/state.rs)) provides thread-safe CRUD operations on the [`virtual_branches.toml`](https://github.com/gitbutlerapp/gitbutler/blob/main/virtual_branches.toml) file that persists stack metadata.

```rust
use gitbutler_stack::VirtualBranchesHandle;
use gitbutler_branch_actions::BranchCreateRequest;

// Acquire exclusive permission
let mut perm = ctx.exclusive_worktree_access().write_permission()?;

// Create a new virtual branch (stack)
let create_req = BranchCreateRequest {
    name: Some("feature/login".to_string()),
    order: None,
    ..Default::default()
};
let stack = gitbutler_branch_actions::create_virtual_branch(&ctx, &create_req, &mut perm)?;

println!("Created stack {} with id {}", stack.name, stack.id);

```

## Workspace Calculation and Octopus Merging

The **Workspace** represents a merged view of all applied stacks and the base branch, enabling fast diffing and safe checkouts. Located in [`crates/gitbutler-workspace/src/lib.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-workspace/src/lib.rs), the workspace is computed as an **octopus merge** of the default target commit and all applied stack heads.

Key functions include:
- **`workspace_base`** – Computes the merge-base of all stack heads and the default target.
- **`WorkspaceState::create`** – Builds the merged tree IDs for both heads and base.
- **`update_uncommitted_changes`** – Reapplies uncommitted changes on top of a new workspace snapshot.

The octopus merge is performed in `merge_workspace`, which iteratively merges each head into the running result with `fail_on_conflict(true)` to abort on conflicts.

```rust
use gitbutler_workspace::{workspace_base, WorkspaceState, update_uncommitted_changes};

// Computing the workspace base
let base_oid = gitbutler_workspace::workspace_base(&ctx, &perm)?;
println!("Workspace base OID: {}", base_oid);

// Capturing workspace state for change management
let old_ws = WorkspaceState::create(ctx, &perm)?;
// ... perform branch operations ...
let new_ws = WorkspaceState::create(ctx, &perm)?;

// Reapply uncommitted changes to new workspace state
let mut exclusive = ctx.exclusive_worktree_access().write_permission()?;
update_uncommitted_changes(ctx, old_ws, new_ws, &mut exclusive)?;

```

## High-Level Branch Actions API

All user-facing operations delegate to the **actions** module in [`crates/gitbutler-branch-actions/src/actions.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-branch-actions/src/actions.rs). This API orchestrates permission checks, workspace mode validation, and state changes while providing a stable interface for both CLI and GUI front-ends.

Notable actions include:
- **`create_virtual_branch`** – Creates new stacks with proper ordering and persistence.
- **`amend`** – Rewrites the tip of a stack by creating a new commit and updating the reference.
- **`squash_commits`** – Combines a range of commits into a single commit.
- **`move_branch`** – Reorders stacks by updating the `order` field and persisting changes.
- **`integrate_upstream_commits`** – Pulls remote changes into a stack while respecting upstream tracking.
- **`unapply_stack`** – Removes a stack from the workspace while preserving metadata.

Source: `[actions.rs (crates/gitbutler-branch-actions/src/actions.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-branch-actions/src/actions.rs)`

## Git Integration Layer

GitButler abstracts over two Git libraries to balance performance and compatibility. The **dual library strategy** allows different operations to use the most efficient underlying implementation.

**`gix`** (pure-Rust) handles performance-critical operations like fast diffing, merge-base calculation, and safe merging. The Context provides `clone_repo_for_merging` optimized for `gix` operations.

**`git2`** (libgit2 bindings) handles legacy operations requiring working-tree checkout, detailed reflog access, and commit creation.

The Context lazily initializes both repositories via `OnDemand` wrappers, allowing crates to select the appropriate API. For example, `workspace_base` uses `gix` for merge-base calculation, while `unapply_stack` uses `git2` for checkout operations.

## CLI and GUI Front-Ends

Both the command-line interface and the desktop application share identical backend logic through the Context API, ensuring consistent behavior across interfaces.

**CLI Implementation** ([`crates/but/src/main.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/but/src/main.rs)) parses command-line arguments and forwards them to the actions API. Commands like `but create` or `but stack squash` eventually call `gitbutler_branch_actions::create_virtual_branch` or related functions.

**Tauri GUI** (`crates/gitbutler-tauri`) provides the desktop interface built with Svelte and TypeScript. The Rust side exposes Tauri commands that invoke the same Context-based APIs used by the CLI, ensuring the GUI and CLI remain functionally equivalent.

Source: `[but CLI entry (crates/but/src/main.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but/src/main.rs)`

## Key Source Files

| File | Purpose |
|------|---------|
| `[Context (crates/but-ctx/src/lib.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but-ctx/src/lib.rs)` | Global application context, lazy repo loading, permission handling. |
| `[VirtualBranchesHandle (crates/gitbutler-stack/src/state.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-stack/src/state.rs)` | Reads/writes [`virtual_branches.toml`](https://github.com/gitbutlerapp/gitbutler/blob/main/virtual_branches.toml); CRUD for stacks. |
| `[Stack (crates/gitbutler-stack/src/stack.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-stack/src/stack.rs)` | Core data model for a virtual branch (stack). |
| `[StackBranch (crates/gitbutler-stack/src/stack_branch.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-stack/src/stack_branch.rs)` | Representation of individual heads within a stack. |
| `[workspace_base & WorkspaceState (crates/gitbutler-workspace/src/lib.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-workspace/src/lib.rs)` | Octopus merge of applied stacks; provides base OID. |
| `[Branch Creation (crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs)` | Implements `create_virtual_branch` and related logic. |
| `[High‑level actions (crates/gitbutler-branch-actions/src/actions.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-branch-actions/src/actions.rs)` | Public API used by CLI/GUI for all branch operations. |
| `[Watcher Handler (crates/gitbutler-watcher/src/handler.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-watcher/src/handler.rs)` | Filesystem event handling (auto‑refresh of workspace). |
| `[CLI entry point (crates/but/src/main.rs)](https://github.com/gitbutlerapp/gitbutler/blob/master/crates/but/src/main.rs)` | Parses command‑line arguments and forwards to the action layer. |
| `[Tauri GUI (crates/gitbutler-tauri)](https://github.com/gitbutlerapp/gitbutler/tree/master/crates/gitbutler-tauri)` | Front‑end UI that calls the same Rust backend via Tauri commands. |

## Summary

- The **Context** (`but_ctx::Context`) serves as the central entry point, managing lazy-loaded repositories and permission tokens for thread-safe operations.
- **Virtual branches** are modeled as **Stacks** stored in [`virtual_branches.toml`](https://github.com/gitbutlerapp/gitbutler/blob/main/virtual_branches.toml), managed by `VirtualBranchesHandle` for persistence and CRUD operations.
- The **Workspace** computes an **octopus merge** of all applied stacks and the base branch, providing a unified working directory view via `WorkspaceState`.
- **High-level actions** in `gitbutler_branch_actions` orchestrate user operations like creating, squashing, and reordering branches while enforcing permission safety.
- **Dual Git libraries** (`gix` for performance, `git2` for compatibility) allow the backend to optimize operations while maintaining broad Git compatibility.
- **Shared backend** between CLI (`but`) and Tauri GUI ensures identical behavior across interfaces through the same `Context`-based APIs.

## Frequently Asked Questions

### What is the purpose of the Context in GitButler's backend?

The **Context** (`but_ctx::Context`) acts as the central facade for all backend operations. It provides lazy-loaded access to both `gix` and `git2` repositories, manages global application settings, and controls access permissions through `RepoExclusive` and `RepoShared` tokens to prevent deadlocks during nested operations.

### How does GitButler store virtual branch metadata?

Virtual branch metadata is persisted in a **TOML file** ([`virtual_branches.toml`](https://github.com/gitbutlerapp/gitbutler/blob/main/virtual_branches.toml)) within the repository. The `VirtualBranchesHandle` type in [`crates/gitbutler-stack/src/state.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-stack/src/state.rs) provides thread-safe CRUD operations on this file, while the `Stack` and `StackBranch` types model the in-memory representation of virtual branches and their constituent heads.

### What is an octopus merge in GitButler's workspace calculation?

The **octopus merge** is a Git operation that combines multiple branch heads into a single tree. In [`crates/gitbutler-workspace/src/lib.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-workspace/src/lib.rs), the `merge_workspace` function iteratively merges the default target commit with all applied stack heads to create the `WorkspaceState`. This produces a unified working directory view that incorporates changes from all active virtual branches simultaneously.

### Why does GitButler use both gix and git2 libraries?

GitButler employs a **dual library strategy** to balance performance and compatibility. The **`gix`** crate (pure-Rust) handles performance-critical operations like fast diffing, merge-base calculation, and safe merging. The **`git2`** crate (libgit2 bindings) handles legacy operations requiring working-tree checkout, detailed reflog access, and commit creation. The Context lazily initializes both repositories, allowing each crate to select the most efficient API for its specific task.