git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Adam Spiers <git@adamspiers.org>
To: git mailing list <git@vger.kernel.org>
Subject: Re: RFC: new git-splice subcommand for non-interactive branch splicing
Date: Fri, 27 May 2016 17:36:52 +0100	[thread overview]
Message-ID: <20160527163652.GC11256@pacific.linksys.moosehall> (raw)
In-Reply-To: <alpine.DEB.2.20.1605271701500.4449@virtualbox>

Hi Johannes,

Thanks for the quick reply!  Responses inline below:

On Fri, May 27, 2016 at 05:27:14PM +0200, Johannes Schindelin wrote:
> On Fri, 27 May 2016, Adam Spiers wrote:
> 
> > 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.
> 
> It sounds as if you could accomplish the same with
> 
>       git checkout -b former-commits <split>
>       git checkout -b latter-commits <base>
>       git cherry-pick <split>..HEAD@{2}

Not really - that is missing several features which git-splice
provides, e.g.

  - The ability to remove a non-consecutive list of commits
    from the branch.

  - The ability to insert commits at the same time as removing
    (granted, that's just in extra cherry-pick your method, but again
    that's another thing to orchestrate).

  - The ability to specify commits to remove / insert using
    arguments understood by git-rev-list.

  - The patch-id magic which is built into git-rebase.  This
    would kick in if any of the commits to insert are already
    in <split>..HEAD@{2} (using your reference terminology).

  - A single command to orchestrate the whole workflow, including
    cleanup, and --abort and --continue when manual conflict
    resolution is required.  This modularity should help a lot when
    building further tools which wrap around it in order to perform
    more complex tasks.

This last point is perhaps the most important.  Of course it's
possible to do this manually already.  But the whole point of
git-splice is to automate it in a convenient and reliable manner.

> > Next steps, and the future
> > --------------------------
> > 
> > Obviously, I'd welcome thoughts on whether it would make sense to
> > include this in the git distribution.
> 
> Far be I from discouraging you to work on these scripts, but I think that
> a really good place for such subcommands is a separate repository, as you
> have it already. There are already some rarely used subcommands in
> libexec/git-core/ cluttering up the space and I would be reluctant to add
> even more subcommands to the default Git installation delivered to every
> user.

Sure, I appreciate the difficulty in deciding where to draw the line.
My feeling is that rebase -i provides something tremendously
important, which the vast majority of users use on a regular basis,
but that git is currently missing a convenient way to
*non-interactively* perform the same magic which rebase -i
facilitates.  And removing / reordering commits is surely one of the
most common use cases of rebase -i, so I think a lot of people could
benefit from some porcelain to automate that and allow building
higher-level tools on top of it.

I suspect the most popular use-case in the short term would be the
infamous "oops, I only just noticed that I put that commit on the
wrong branch, and now there's already a whole bunch of other commits
on top of it".  I would expect that reducing this solution to a single
git-transplant(1) command would be pretty attractive for a lot of
people.  And of course GUIs / IDEs could incorporate it into their
more beautiful front-ends.  However, if it's not in git core, that's
unlikely to happen.

> You can *always* just extend the PATH so that git-splice can be found;
> Then `git splice ...` will do exactly what you want. That is e.g. how
> git-flow works.

Sure, I've been using that trick since at least 2009 ;-) [0]

> (Of course I hope that you will maintain your scripts
> much, much better than git-flow, i.e. not abandon all users).

I hope so too ;-)

> > 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.
> 
> This is just cherry-pick with a range...

No it's not:

  - git-transplant would be able to splice commits from one branch
    *into* (i.e. inside, *not* onto) another branch.

  - git-transplant would also take care of removing the commits from
    the source branch, but not before they were safely inside the
    destination branch.

  - git-transplant would orchestrate the whole workflow with a single
    command, complete with --abort and --continue.

> >   - 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.
> 
> You mean something like Darcs on top of Git. Essentially, you want to end
> up with an octopus merge of branches whose commits would conflict if
> exchanged.

Something like that, yes, but it's not as simple as a single octopus
merge.  It would support arbitrarily deep DAGs of topic branches.

> I implemented the logic for this in a shell script somewhere, so it is not
> *all* that hard (Python not required). But I ended up never quite using it
> because it turns out that in practice, the commit "dependency" (as defined
> by the commit diffs) does not really reflect the true dependency.
>
> For example,

[snipped examples]

Sure - I already covered this concern in footnote [0] of my previous
mail; maybe you missed that?  As I said there, in my experience, I
have found it very useful to be able to automatically detect textual
dependencies via git-deps, even though they do not represent the
entire set of dependencies.  I've even recorded a YouTube screencast
demonstrating one such use case[1].  So please don't let the question
for perfection become the enemy of the good ;-)

> So I think that this is a nice exercise, but in practice it will require a
> human to determine which commits really depend on each other.

Of course - this is exactly why I wrote "or at least
semi-automatically" in the first mail of this thread.  But even though
git-deps / git-explode can never automatically handle *all*
dependencies, they can handle enough dependencies to be significantly
useful.  I have concrete real-world experience of that.  In fact there
is one scenario I am working on right now which is current proof of
this (no coincidence, since that's what motivated me to take this next
step on this journey and write git-splice):

I have made a large bunch of small commits to a single text file
(design document).  Some are possibly contentious; some aren't.  So I
need to split them out into a series of smaller independent patch
series which I can submit to gerrit for review, thereby making life
easier for the reviewers and minimizing any bottlenecks where reviews
for one change are blocked because another change hasn't been reviewed
yet.  And in this case, because the changes are all applying to a
single file containing only natural language, git-deps correctly
determines *all* dependencies, not just textual ones.

> You would render me *really* impressed if you could come up with an
> automated way to determine logical dependencies between patches.

Hey, I would *really* impress myself if I could do that, too; after
all, that would be a pretty sophisticated form of artificial
intelligence :-)

Thanks again for the feedback!

Adam


[0] https://github.com/aspiers/git-config/commit/287685408326

    BTW there are currently 36 git-* scripts in that repo; you may or
    may not find it interesting to browse through them.

[1] https://github.com/aspiers/git-deps#use-case-1-porting-between-branches

    In this case, git-deps can serve as an early warning system to
    flag when a backporting task's cost:reward ratio would be too
    high to justify starting work on it.

  reply	other threads:[~2016-05-27 16:37 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-27 14:08 RFC: new git-splice subcommand for non-interactive branch splicing Adam Spiers
2016-05-27 15:27 ` Johannes Schindelin
2016-05-27 16:36   ` Adam Spiers [this message]
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=20160527163652.GC11256@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).