Let’s walk through a hypothetical scenario of using Butler Flow day-to-day, showing how its mechanics reduce friction.
Setup: choose your target branch
First, your project defines a target branch (say main or production). This is the baseline for all work. Every change is implicitly relative to that branch. Without a target branch, virtual branching doesn’t function.
Setup: choose your target branch
First, your project defines a target branch (say main or production). This is the baseline for all work. Every change is implicitly relative to that branch. Without a target branch, virtual branching doesn’t function.
Start working on a change
You start coding. As soon as you begin editing, GitButler sees that you don’t have an active virtual branch, so it auto-creates one for you. Now your work is tracked under, say, virtual/1234 (just a conceptual name).
You develop your feature or fix. All changes are owned by this virtual branch.
Meanwhile, your teammate is also working on virtual/abcd. Their upstream branch exists in the central Git repository.
Bringing in a teammate’s work for integration
Let’s say you want to merge or test your teammate’s changes together with yours before a shared PR. In a traditional flow, you’d either:
- Switch to their branch, merge main into it, test, then switch back; or
- Rebase both branches locally; or
- Create a feature-integration branch that merges them.
But in Butler Flow, you can simply apply their branch on top of your working directory — without switching context — effectively layering their changes on top of yours.
You still haven’t merged anything upstream; you’re just testing integration locally.
Review & PR
Each virtual branch is reviewable independently. You push your virtual branch upstream (or push a corresponding real Git branch), create a PR, and teammates review it.
Because you could test integration locally with other branches, you have confidence that your changes play well with other developers’ work. That makes reviews more reliable and less risky.
Merge and cleanup
Upon final review, you merge your branch into the target branch (the usual Git operation: rebase, merge, squash, whatever your team policy). When that merge is done, GitButler recognizes that the virtual branch is fully integrated, and automatically disposes of it (when you update base and GitButler sees that the branch is include). That cleanup is transparent to you.
This automatic lifecycle (start, review, merge, dispose) is what keeps your workspace clean.
When Butler Flow shines (and when it doesn’t)
Good fits: where you’ll see big wins
- Teams shipping frequently — if you’re deploying multiple times per day or every day, the friction of merging and conflict resolution looms large. Butler Flow’s early integration and minimal context switching can really help.
- Medium to large codebases — when there is more surface area for merge conflicts and more people changing related parts, catching conflicts early pays big dividends.
- Interdependent work — when multiple devs are touching overlapping modules or shared areas, you need a way to safely test combinations before merging. Butler Flow makes that easier.
- Desire to reduce branch overhead — if your team finds branch management (cleanup, rebase, switching) draining, the automation in Butler Flow alleviates that burden.
Less ideal or challenging scenarios
- Small teams or solo projects — if you rarely have overlapping work and you deploy infrequently, the gains may be marginal relative to adopting a new toolchain.
- Highly restricted legacy environments — environments where you can’t install or integrate GitButler, or where existing tooling is rigid, may block adoption.
- Rigid Git workflows / policies — if your team is unwilling or unable to change merge rules, branch discipline, or adopt new abstractions, Butler Flow will face resistance.
- Complex, long-running feature branches — while Butler Flow supports longer-lived branches, its strength is in keeping branches short and integrative. If you have massive features that take weeks isolated, you may lose some benefit.
Best practices for adopting Butler Flow
Here are guidelines and patterns to get the most out of Butler Flow (and avoid pitfalls).
-
Keep branches small & focused The more isolated and short-lived the virtual branch, the easier it is to integrate. If a branch goes on for too long, it builds drift and conflicts
-
Merge often / integrate continuously Bring upstream changes from the target branch frequently. Use the “apply” mechanism to test interactions early. Don’t wait until the end.
-
Review early and in isolation Use branches in isolation for review; use the apply / test combination feature only when needed. Don’t blindly layer many branches before review.
-
Have a clear merging policy Decide whether your team favors squash merges, rebase, or standard merge. Be consistent. Butler Flow doesn’t remove decision-making; it just improves your flexibility.
-
Train developers on the mental model Because virtual branching is unfamiliar, invest time in onboarding, documentation, and pair programming. Help your team internalize the idea that changes are “owned” by branches but can be composed.
-
Integrate with CI / test pipelines Make sure your continuous integration and test systems understand or work well with GitButler / virtual branch setups. For example, your workflows for PR testing, merge hooks, code scanning should be compatible.
-
Limit stacking of many branches Avoid situations where a developer has dozens of virtual branches applied simultaneously. That could lead to complexity. Use discipline to integrate and finish branches.
-
Monitor for conflict hotspots Using analytics or logs, find parts of the codebase that often produce conflicts when branches are applied. These may need better modularization, clearer boundaries, or refactoring.
Conclusion
In our first post, we introduced you to Butler Flow. Here we've covered a bit more of the practical use of Butler Flow. In our next and final part, we'll take an even deeper dive into some examples. Make sure to checkout the docs on Butler Flow and join our discord server to chat with the team!

Written by PJ Hagerty
PJ Hagerty is a well-known figure in the tech industry, particularly within the developer relations and DevOps communities. He's also Head of Developer and Community Relations at GitButler.



