Package: git-branchless
git branchlessMotivationSometimes, I am working on multiple changes to aGitrepository.  I want
to combine all of my changes in a single branch, but send them upstream in
small, reviewable chunks. Refer tothe related articlesfor some advantages of this workflow.Git already supports this workflow viagit format-patchandgit 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.
Runninggit branchlesscreates 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-rungit branchless.Installationgit branchlesscurrently depends on an unreleased version ofgit revise.$pipinstall--usergit-revise@git+https://github.com/mystor/git-revise.git@e27bc1631f5da6041c2fa7e3d1f5a9fecfb3ef57
$pipinstall--usergit-branchlessUsageCreate some commits with commit messages starting with[<topic>]where<topic>is a valid branch name.  Then rungit branchlessto 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 commitThen 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 commitBy default,git branchlesslooks 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 basechildoff bothparent1andparent2. 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-subjectoption, 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 enablinggit rerere(usegit config rerere.enabled true; git config rerere.autoUpdate true).Instead of the default topic tag delimiters ([and]), you can
set Git configuration valuesbranchless.subjectPrefixPrefixandbranchless.subjectPrefixSuffix, respectively.Integrating Commits from Other BranchesYou can usegit-branchless-pickto integrate
other commit ranges into your branch:$gitbranchless-pick..some-branchThis starts an interactive rebase, prompting you to cherry-pick all
missing commits fromsome-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:$gitconfig--addremote.origin.fetch'+refs/pull/*/head:refs/remotes/origin/pr-*'$gitfetchorigin
$gitbranchless-pick$(gitmerge-baseorigin/pr-123HEAD)..origin/pr-123TipsYou can usegit reviseto efficiently modify your commit messages
to contain the[<topic>]tags. This command lets you edit all commit
messages in@{upstream}..HEAD.$gitrevise--interactive--editLikegit revise, you can usegit branchlessduring an interactive rebase.git-autofixupcan eliminate
some of the busywork involved in creating fixup commits.Related ArticlesInStacked Diffs Versus Pull Requests, Jackson Gabbard
describes the advantages of a patch-based workflow (usingPhabricator)
over the one-branch-per-reviewable-change model;git branchlesscan be used
to implement the first workflow, even when you have to use pull-requests.InMy unorthodox, branchless git workflow, Drew
DeVault explains some advantages of a branchless workflow.Peer ProjectsWhilegit branchlessonly 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:Stacked Gitgit psgh-stackUnlike its peers,git branchlessnever modifies any worktree files,
since it usesgit reviseinternally.  This makes it faster, and avoids
invalidating builds.ContributingSubmit feedback athttps://github.com/krobelus/git-branchless/or at thepublic mailing listby
sending email tomailto:~krobelus/git-branchless@lists.sr.ht.