From: Adam Spiers <git@adamspiers.org>
To: git mailing list <git@vger.kernel.org>
Subject: RFC: new git-splice subcommand for non-interactive branch splicing
Date: Fri, 27 May 2016 15:08:11 +0100 [thread overview]
Message-ID: <20160527140811.GB11256@pacific.linksys.moosehall> (raw)
Hi all,
I finally got around to implementing a new git subcommand which I've
wanted for quite a while. I've called it git-splice.
Description
-----------
git-splice(1) non-interactively splices the current branch by removing
a range of commits from within it and/or cherry-picking a range of
commits into it. It's essentially just a glorified wrapper around
cherry-pick and rebase -i.
Usage
-----
Examples:
# Remove commit A from the current branch
git splice A^!
# Remove commits A..B from the current branch
git splice A..B
# Remove commits A..B from the current branch, and cherry-pick
# commits C..D at the same point
git splice A..B C..D
# Cherry-pick commits C..D, splicing them in just after commit A
git splice A C..D
# Remove first commit mentioning 'foo', and insert all commits
# in the 'elsewhere' branch which mention 'bar'
git splice --grep=foo -n1 HEAD -- --grep=bar HEAD..elsewhere
# Abort a splice which failed during cherry-pick or rebase
git splice --abort
# Resume a splice after manually fixing conflicts caused by
# cherry-pick or rebase
git splice --continue
N.B. Obviously this command rewrites history! As with git rebase,
you should be aware of all the implications of history rewriting
before using it.
Code
----
Currently this is in alpha state:
https://github.com/git/git/compare/master...aspiers:splice
and I reserve the right to rewrite the history of that branch in the
near future ;-)
I realise that the code does not yet conform to the coding standards
of the git project. For example, it relies on non-POSIX bash
features, like arrays. I would be happy to fix this if there is a
chance git-splice might be accepted for inclusion within the git
distribution. (Presumably contrib/ is another possibility.)
Also, I haven't yet written a proper man page for it.
Motivation
----------
I wrote git-splice as the next step in the journey towards being able
to implement a tool which automatically (or at least
semi-automatically) splits a linear sequence of commits into a commit
graph where ancestry exactly mirrors commit "dependency".[0] In other
words, in this commit graph, a commit B would have commit A as an
ancestor if and *only* if commit B cannot cleanly apply without A
already being present in the branch. As a corollary, if commit F
depends on D and E, but D and E are mutually independent, F would
need to depend on a merge commit which contains D and E.
Such a tool could be useful for a few reasons. Firstly, large patch
series are much harder to review than single commits or small patch
series, but typical development workflows often lead to large patch
series.
For example, if I work privately on a new feature for some hours /
days / weeks, I will typically amass a bunch of commits which are not
all directly related to the new feature: there are often refactorings,
fixes for bugs discovered during development of the new feature, etc.
I doubt I'm the only git user not disciplined enough to maintain neat
branch organization for the whole of a long period of hacking!
i.e. religiously maintaining one branch per bugfix, one branch per
refactoring, and one branch for the new feature.[1] Typically, tidying
up the branches comes a bit later, when I want to start feeding stuff
upstream for review.
Therefore being able to reduce the effort involved with breaking a
large patch series into smaller related chunks seems potentially very
useful.
As well as making reviews smaller easier, this allows both the reviews
and any corresponding CI to proceed in a more parallelized fashion.
Some review systems can implicitly discourage reviews of large patch
series, by treating each commit as a review in its own right and/or not
providing sophisticated support for patch series. Gerrit is one
example; gitlab and GitHub are counter-examples.
I'm sure there are other use cases which I didn't think of yet.
Next steps, and the future
--------------------------
Obviously, I'd welcome thoughts on whether it would make sense to
include this in the git distribution.
In the longer term however, I'd like to write two more subcommands:
- git-transplant(1) which wraps around git-splice(1) and enables
easy non-interactive transplanting of a range of commits from
one branch to another. This should be pretty straightforward
to implement.
- git-explode(1) which wraps around git-transplant(1) and
git-deps(1), and automatically breaks a linear sequence of commits
into multiple smaller sequences, forming a commit graph where
ancestry mirrors commit dependency, as mentioned above. I expect
this to be more difficult, and would probably write it in Python.
Ideally, this tool would also be able to integrate with other
workflow management tools[1] in order to effectively create /
manage topic branches and track dependencies between them.
Eventually, the utopia I'm dreaming about would become a reality and
look something like this:
git checkout -b new-feature
while in_long_frenzied_period_of_hacking; do
# don't worry too much about branch maintenance here, just hack
git add ...
git commit ...
done
# Break lots of commits from new-feature into new topic branches:
git explode
# List topic branches
git work list
# Manually complete tidy-up of those branches
git push ...
git send-email ...
Feedback on any of this is very welcome!
Thanks,
Adam
[0] https://github.com/aspiers/git-deps/#user-content-use-case-2-splitting-a-patch-series
This type of dependency could be described as textual or syntactic or
lexical, and is automatically detected by git-deps:
https://github.com/aspiers/git-deps/
which I wrote a couple of years ago and previously announced on this list:
http://thread.gmane.org/gmane.comp.version-control.git/262000/focus=262606
Of course, this is a somewhat naive approach in that it has no
awareness of semantic dependencies, e.g. commit A changing file X
in a way which only makes sense if commit B changing file Y is
already present. However in my experience it's still a useful
start in the right direction, saving a lot of time by detecting
the "obvious" dependencies, and often revealing dependencies which
I would have otherwise missed.
[1] There are tools which can help with this, e.g. topgit, git-flow,
and gitwork, which IMHO is particularly interesting.
next reply other threads:[~2016-05-27 14:13 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-27 14:08 Adam Spiers [this message]
2016-05-27 15:27 ` RFC: new git-splice subcommand for non-interactive branch splicing Johannes Schindelin
2016-05-27 16:36 ` Adam Spiers
2016-05-28 7:06 ` Johannes Schindelin
2016-05-28 11:24 ` Adam Spiers
2016-05-30 0:34 ` RFC: new git-transplant subcommand for non-interactively moving commits between branches Adam Spiers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160527140811.GB11256@pacific.linksys.moosehall \
--to=git@adamspiers.org \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).