Efficiently manage Git branches without leaving your local branch
Project description
git branchless
Efficiently manage topic branches without leaving your local branch
Motivation
Sometimes, I am working on multiple changes to a Git repository. I want to add all of my changes to a single branch, but send them upstream in small, reviewable chunks.
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 upstream 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
$ 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
for each of those topics among commits in the range @{upstream}..HEAD
.
Each topic branch is the result of applying the topic's commits on top of
the common ancestor of your branch and the upstream branch, that is,
git merge-base @{upstream} HEAD
.
For example, if you have a history like
$ git log --graph --oneline
* 2708e12 [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 Initial commit
Then this command will create or update two branches that branch away from HEAD:
$ git branchless
$ git log --graph --oneline --all
* 2708e12 (HEAD) [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 Initial commit
git branchless
ignores commits whose subject does not start with a topic tag.
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 trying to apply 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:
$ ln -s $PWD/git-branchless-pick ~/bin/
$ 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.
Related Articles
-
In Stacked Diffs Versus Pull Requests, Jackson Gabbard describes the advantages of a patch-based workflow (using Phabricator) over the pull-request model;
git-branchless
can be used to implement that workflow, even when you have to use pull-requests. -
In My unorthodox, branchless git workflow, Drew DeVault explains some advantages of a branchless workflow.
Related Projects
- Stacked Git implements a similar
workflow. It provides a comprehensive set of commands to manage commit
metadata, whereas
git branchless
only offers one command and requires the user to use standard Git tools for everything else.
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file git-branchless-0.0.5.tar.gz
.
File metadata
- Download URL: git-branchless-0.0.5.tar.gz
- Upload date:
- Size: 11.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | abf5c4b07e86b2b7b08e01f5ab7f433c682821c6d83f46c4ece7e7bdda78b030 |
|
MD5 | 6206cf430226bf4c7e4f8148d8832c6a |
|
BLAKE2b-256 | 53962c9e89019b063c450b5aafc4c5d4d44a0f63d634cca4f9c87b39849ddfaf |
File details
Details for the file git_branchless-0.0.5-py3-none-any.whl
.
File metadata
- Download URL: git_branchless-0.0.5-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | eba206ff029daa7202f902bbc2aebe5006bfa7a8a38252a707b68d841a1c3a94 |
|
MD5 | bb30e8c9f57813c5ec7389dea92fc192 |
|
BLAKE2b-256 | ea3a971f4e2f9575527ca26bfc70ab5e8bc51f8dd754923ebed9e4e2493f143b |