git-explode
is a tool for automatically exploding a single git
branch into a number of smaller branches which are textually
independent. It uses git-deps to automatically detect
textual dependencies between the commits in the branch, and calculates
the grouping and ordering of commits into independent sub-topics from
which the new branches are created.
I have blogged about git-explode and related tools, and also publically spoken about the tool several times:
- a presentation at the openSUSE Summit in Nashville, Apr 2019
- a presentation at the OpenStack PTG in Denver, Sept 2018 (watch the video)
- a presentation at the London Git User Meetup in May 2018 (watch the video)
The most obvious use case for this tool is helping improve the "hygiene" of branch management, so that each branch in your repository is tightly and cleanly scoped to a single logical topic.
For example during work on feature branch, you might become aware of an opportunity to refactor some existing code, and might decide to take advantage of that opportunity immediately, by adding refactoring commits to the tip of the feature branch. And during the refactoring, you may even spot a bug, and end up also adding a bugfix to the same feature branch.
So now you have a feature branch which is polluted by commits which perform refactoring and bugfixing. If you were to submit this branch for code review as a single GitHub pull request (or GitLab merge request, or Gerrit change topic), it would be a lot harder for your collaborators to review than if you had separately submitted three smaller reviews, one for the bugfix, one for the refactoring, and one for the new feature.
In this scenario, git-explode
comes to the rescue! Rather than you
having to manually separate out the commits into topic branches, it
can do all the hard work for you with a single command.
Astute readers will note that textual independence (as detected by
git-deps
and used by git-explode
) is not the same as semantic /
logical independence. Textual independence means that the changes can
be applied in any order without incurring conflicts, but this is not a
reliable indicator of logical independence. (This caveat is also
noted in the README for git-deps.)
For example a change to a function and corresponding changes to the
tests and/or documentation for that function would typically exist in
different files. So if those changes were in separate commits within
a branch, running git-explode
on the branch would place those
commits in separate branches even though they are logically related,
because changes in different files (or even in different areas of the
same files) are textually independent.
So in this case, git-explode
would not behave exactly how we might
want. And for as long as AI is an unsolved problem, it is very
unlikely that it will ever develop totally reliable behaviour.
So does that mean git-explode
is useless? Absolutely not!
Firstly, when best practices for commit structuring are adhered to, changes which are strongly logically related should be placed within the same commit anyway. So in the example above, a change to a function and corresponding changes to the tests and/or documentation for that function should all be within a single commit. (Although this is not the only valid approach; for a more advanced meta-history grouping mechanism, see git-dendrify.)
Secondly, whilst textual independence does not imply logical
independence, the converse is much more commonly true: logical
independence typically implies textual independence. So while it
might not be too uncommon for git-explode
to separate
logically-related changes into different branches, it should be pretty
rare that it groups logically unrelated changes on the same branch.
Combining this with the fact that git
makes it easier to join
commits on separate branches back together into one branch than to
split them apart suggests that git-explode
still has plenty of
potential for saving effort.
Thirdly, it is often unhelpful to allow the quest for the perfect become the enemy of the good - a tool does not have to be perfect to be useful; it only has to be better than performing the same task without the tool.
Further discussion on these points can be found in an old thread from the git mailing list.
Ultimately though, "the proof is in the pudding", so try it out and see!
As already explained above, the most obvious use case is cleaning up the mess caused by logically independent commits all mashed together into one branch. However here are some further use cases. If you can think of others, please submit them!
If you need to backport or forward-port changes between two branches,
git-explode
could be used to first decompose the source branch into
textually independent topic branches. Then before any porting starts,
informed decisions can be made about which topics to port and which
not to port, and in which order. Each decomposed topic branch is
guaranteed to be textually independent from the others, so they can be
ported separately - indeed even concurrently by different people -
thereby greatly reducing the risk of conflicts when the independent
topic branches are merged together into the target branch.
Emmet's idea about a company who needs to publish a private codebase but needs to clean it up first. Similar to 1. but on a bigger scale.
Split giant commit into commits one per hunk, then regroup into topics along with previous related commits. (Note that the previous related commits are required here for the regrouping to work, since hunks within a single commit are by definition independent of each other.)
Please see the INSTALL.rst file.
Usage is fairly self-explanatory if you run git explode -h
:
usage: git-explode [-h] [--version] [-d] [-p PREFIX] [-c NUM] BASE HEAD Explode linear sequence of commits into topic branches positional arguments: BASE base of sequence to explode HEAD head of sequence to explode optional arguments: -h, --help show this help message and exit --version show program's version number and exit -d, --debug Show debugging -p PREFIX, --prefix PREFIX prefix for all created topic branches -c NUM, --context-lines NUM Number of lines of diff context to use [1]
Please see the CONTRIBUTING.rst file.
I first announced the intention to build this tool on the git mailing list in May 2016; however at the time I was under the mistaken impression that I could build it out of the git-splice and git-transplant commands which I was working on at that time.
Thanks to SUSE's generous Hack Week policy, I have had the luxury of working on this as a Hack Week project.
In May 2018 I took advantage of another Hack Week to apply more polish and make the first release. This was in preparation for demonstrating the software at a Meetup event of the Git London User Group.
Released under GPL version 2 in order to be consistent with git's license, but I'm open to the idea of dual-licensing if there's a convincing reason.