Branchless workflow for Git
git-branchless is a suite of tools to help you visualize, navigate, manipulate, and repair your commit graph. It's based off of the branchless Mercurial workflows at large companies such as Google and Facebook.
Undo almost anything:
- Amended commits.
- Merges and rebases (e.g. if you resolved a conflict wrongly).
- Branch creations, updates, and deletions.
git reflog is a tool to view the previous position of a single reference (like
HEAD), which can be used to undo operations. But since it only tracks the position of a single reference, complicated operations like rebases can be tedious to reverse-engineer.
git undo operates at a higher level of abstraction: the entire state of your repository.
git reflog also fundamentally can't be used to undo some rare operations, such as certain branch creations, updates, and deletions. See the architecture document for more details.
git undo handle?
git undo relies on features in recent versions of Git to work properly. See the compatibility chart.
git undo can't undo the following. You can find the design document to handle some of these cases in issue #10.
- "Uncommitting" a commit by undoing the commit and restoring its changes to the working copy.
- In stock Git, this can be accomplished with
git reset HEAD^.
- This scenario would be better implemented with a custom
git uncommitcommand instead. See issue #3.
- In stock Git, this can be accomplished with
- Undoing the staging or unstaging of files. This is tracked by issue #10 above.
- Undoing back into the middle of a conflict, such that
git statusshows a message like
path/to/file (both modified), so that you can resolve that specific conflict differently. This is tracked by issue #10 above.
git undo is not intended to handle changes to untracked files.
Comparison to other Git undo tools
gitjk: Requires a shell alias. Only undoes most recent command. Only handles some Git operations (e.g. doesn't handle rebases).
git-extras/git-undo: Only undoes commits at current
git-annex undo: Only undoes the most recent change to a given file or directory.
thefuck: Only undoes historical shell commands. Only handles some Git operations (e.g. doesn't handle rebases).
Visualize your commit history with the smartlog (
Why not `git log --graph`?
git log --graph only shows commits which have branches attached with them. If you prefer to work without branches, then
git log --graph won't work for you.
To support users who rewrite their commit graph extensively,
git sl also points out commits which have been abandoned and need to be repaired (descendants of commits marked with
rewritten as abcd1234). They can be automatically fixed up with
git restack, or manually handled.
Edit your commit graph without fear:
Why not `git rebase -i`?
Interactive rebasing with
git rebase -i is fully supported, but it has a couple of shortcomings:
git rebase -ican only repair linear series of commits, not trees. If you modify a commit with multiple children, then you have to be sure to rebase all of the other children commits appropriately.
- You have to commit to a plan of action before starting the rebase. For some use-cases, it can be easier to operate on individual commits at a time, rather than an entire series of commits all at once.
When you use
git rebase -i with
git-branchless, you will be prompted to repair your commit graph if you abandon any commits.
The branchless workflow is designed for use in a repository with a single main branch that all commits are rebased onto, but works with other setups as well. It improves developer velocity by encouraging fast and frequent commits, and helps developers operate on these commits fearlessly (see Design goals).
In the branchless workflow, the commits you're working on are inferred based on your activity, so you no longer need branches to keep track of them. Nonetheless, branches are sometimes convenient, and
git-branchless fully supports them. If you prefer, you can continue to use your normal workflow and benefit from features like
git sl or
git undo without going entirely branchless.
Short version: run
cargo install --locked git-branchless, then run
git branchless init in your repository.
git-branchless is currently in alpha. Be prepared for breaking changes, as some of the workflows and architecture may change in the future. It's believed that there are no major bugs, but it has not yet been comprehensively battle-tested. You can see the known issues in the issue tracker.
git-branchless follows semantic versioning. New 0.x.y versions, and new major versions after reaching 1.0.0, may change the on-disk format in a backward-incompatible way.
To be notified about new versions, select Watch » Custom » Releases in Github's notifications menu at the top of the page. Or use GitPunch to deliver notifications by email.
There's a lot of promising tooling developing in this space. See Related tools for more information.