Skip to main content

git branchless

PyPi

Motivation

Sometimes, I am working on multiple changes to a Git repository. I want to combine all of my changes in a single branch, but send them upstream in small, reviewable chunks. Refer to the related articles for some advantages of this workflow.

Git already supports this workflow via git format-patch and git send-email, however, many projects prefer to receive patches as pull requests. To make proposed changes easy to review, you'll want to submit a separate pull request for each independent change. With a branchless workflow, the sole local branch typically contains multiple independent changes. To submit those as pull requests, you need to create a separate branch for each change. Running git branchless creates the desired branches without requiring you to switch back and forth between branches. This allows you to submit small pull requests while enjoying the benefits of a branchless workflow. After making any changes to your worktree's branch you can easily update the generated branches: just re-run git branchless.

Installation

git branchless currently depends on an unreleased version of git revise.

$ pip install --user git-revise@git+https://github.com/mystor/git-revise.git@e27bc1631f5da6041c2fa7e3d1f5a9fecfb3ef57
$ pip install --user git-branchless

Usage

Create some commits with commit messages starting with [<topic>] where <topic> is a valid branch name. Then run git branchless to create a branch <topic> with the given commits.

For example, if you have created a commit history like

$ git log --graph --oneline
* 2708e12 (HEAD -> master) [my-awesome-feature] Initial support for feature
* c6dd3ab [my-awesome-feature] Some more work on feature
* 683de4b [some-unrelated-fix] Unrelated fix
* 3eee379 Local commit without topic tag
* 2ec4d51 (origin/master) Initial commit

Then this command will (re)create two branches:

$ git branchless
$ git log --graph --oneline --all
* 2708e12 (HEAD -> master) [my-awesome-feature] Initial support for feature
* c6dd3ab [my-awesome-feature] Some more work on feature
* 683de4b [some-unrelated-fix] Unrelated fix
* 3eee379 Local commit without topic tag
| * 7645890 (my-awesome-feature) Initial support for feature
| * e420fd6 Some more work on feature
|/
| * d5f4bb2 (some-unrelated-fix) Unrelated fix
|/
* 2ec4d51 (origin/master) Initial commit

By default, git branchless looks only at commits in the range @{upstream}..HEAD. It ignores commits whose subject does not start with a topic tag.

Created branches based on the common ancestor of your branch and the upstream branch, that is, git merge-base @{upstream} HEAD.

To avoid conflicts, you can specify dependencies between branches. For example use [child:parent1:parent2] to base child off both parent1 and parent2. The order here does not matter because it will be determined by which topic occurs first in the commit log.

By default, when dependencies are added to generated branches, the commit message will include their topic tags. You can turn this off for all branches with the --trim-subject option, or for a single dependency by adding the + character before a dependency specification (like [child:+parent]).

If there is a merge conflict when applying a commit, you will be shown potentially missing dependencies. You can either add the missing dependencies, or resolve the conflict. You can tell Git to remember your conflict resolution by enabling git rerere (use git config rerere.enabled true; git config rerere.autoUpdate true).

Instead of the default topic tag delimiters ([ and ]), you can set Git configuration values branchless.subjectPrefixPrefix and branchless.subjectPrefixSuffix, respectively.

Integrating Commits from Other Branches

You can use git-branchless-pick to integrate other commit ranges into your branch:

$ git branchless-pick ..some-branch 

This starts an interactive rebase, prompting you to cherry-pick all missing commits from some-branch, prefixing their commit subjects with [some-branch]. Old commits with such a subject are dropped, so this allows you to quickly update to the latest upstream version of a ref that has been force-pushed.

Here's how you would use this to cherry-pick GitHub pull requests:

$ git config --add remote.origin.fetch '+refs/pull/*/head:refs/remotes/origin/pr-*'
$ git fetch origin
$ git branchless-pick $(git merge-base origin/pr-123 HEAD)..origin/pr-123

Tips

  • You can use git revise to efficiently modify your commit messages to contain the [<topic>] tags. This command lets you edit all commit messages in @{upstream}..HEAD.

    $ git revise --interactive --edit
    

    Like git revise, you can use git branchless during an interactive rebase.

  • git-autofixup can eliminate some of the busywork involved in creating fixup commits.

Related Articles

Peer Projects

While git branchless only offers one command and relies on standard Git tools for everything else, there are some tools that offer a more comprehensive set of commands to achieve a similar workflow:

Unlike its peers, git branchless never modifies any worktree files, since it uses git revise internally. This makes it faster, and avoids invalidating builds.

Contributing

Submit feedback at https://github.com/krobelus/git-branchless/ or at the public mailing list by sending email to mailto:~krobelus/git-branchless@lists.sr.ht.

Metadata

Release files for git-branchless 0.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for git-branchless 0.0.6
File Size Uploaded
git-branchless-0.0.6.tar.gz 11.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for git-branchless 0.0.6
File Interpreter ABI Platform
git_branchless-0.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 22.6 kB

Release files / git-branchless-0.0.6.tar.gz

Download URL git-branchless-0.0.6.tar.gz
Size 11.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6a03e01f77a075daabe03ccf586acc2f54e838481ffc4afa44b5377fd60e7fd7
BLAKE2b-256 checksum
How to use checksums
73ebc62224f163325ad72d7e7974e3de1c360f401d513a58e7e34e71a06c02a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.5

Release files / git_branchless-0.0.6-py3-none-any.whl

Download URL git_branchless-0.0.6-py3-none-any.whl
Size 11.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
96b75be45397bcd4208ff8ca761b89eb9cd5a1df4cfa08773b85c141f6c6db61
BLAKE2b-256 checksum
How to use checksums
6beef293000e5dbf7f639c97e9cfa441589c8ffb1c6312ed3338c2f60894d96b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.5

Release history Release notifications | RSS feed

This release

0.0.6 This release

2 release files

0.0.5

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page