git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: Adam Spiers <git@adamspiers.org>
Cc: git mailing list <git@vger.kernel.org>
Subject: Re: RFC: new git-splice subcommand for non-interactive branch splicing
Date: Sat, 28 May 2016 09:06:59 +0200 (CEST)	[thread overview]
Message-ID: <alpine.DEB.2.20.1605280841000.4449@virtualbox> (raw)
In-Reply-To: <20160527163652.GC11256@pacific.linksys.moosehall>

Hi Adam,

please reply-to-all on this list.

On Fri, 27 May 2016, Adam Spiers wrote:

> 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.

Would it not make sense to enhance `rebase -i`, then?

I, for one, plan to port my Git garden shears (at least partially) once I
managed to get my rebase--helper work in. The shears script is kind of a
"--preseve-merges done right":

	https://github.com/git-for-windows/build-extra/blob/master/shears.sh

It allows you to (re-)create a branch structure like this:

	bud
	pick cafebabe XYZ
	pick 01234567 Another patch
	mark the-first-branch

	bud
	pick 98765432 This patch was unrelated
	mark the-second-branch

	bud
	merge the-first-branch
	merge the-second-branch

Of course, this is interactive. But quite frankly, you want to be able to
perform quite complicated stuff, and I think the command-line offers only
an inadequate interface for this.

> 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 have two workflows for that. The simpler one:

	git checkout other-branch
	git commit
	git checkout @{-1}

Sometimes I need to call `git stash -p` before, and `git stash apply`
after those calls.

The more complicated one comes in handy when a complete rebuild takes a
long time, and branch switching would trigger a rebuild:

	# Here, I stash what I *want* on the other branch
	git stash -p
	git worktree add throwaway other-branch
	cd throwaway
	git stash apply
	git commit

I did use the approach you proposed a couple of times: just commit in the
middle, and sort things out later. The problem: I frequently forgot, and
if I did not, reordering the commits resulted in stupid and avoidable
merge conflicts.

> > > 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.

Okay, but in case of merge conflicts, you still have to switch to the
other branch, right?

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

That assumes a workflow where you develop on one big messy branch and
later sort it out into the appropriate, separate branches, right? I admit
that I used to do that, too, but ever since worktrees arrived, I do not do
that anymore: it resulted in too much clean-up work. Better to put the
commits into the correct branch right away. Of course, that is just *my*
preference.

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

cherry-pick also sports --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.

Yes, of course. Because

A - B - C - D

might need to resolve into

A - M1 - C - M3
  X        /
B - M2 - D

> > 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?

I think it deserves more prominent a place than a footnote.

> > 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.

I'd love to see those examples where it worked, because it sure did not
work for me (I wasted two weeks to implement that script that I never used
successfully).

> I have made a large bunch of small commits to a single text file
> (design document).  Some are possibly contentious; some aren't.

Ah. Well, as I said, I changed my workflow to use multiple worktrees with
multiple branches. The contentious changes would go into at least one
branch, more likely multiple. The uncontentious changes would go into
another.

And most likely at least some of those branches would cause merge
conflicts. However, they would do so only once, not multiple times during
the cleaning-up phase.

I did actually track the time at some stage to determine what is faster.
Sorting things into multiple branches won hands down (in my hands). And
no: I did not believe it would.

> 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.

I do not buy that. When you introduce a section way down in the document
for which you have to introduce a new definition in one of the first
sections, logically those two changes belong to the same topic branch. Yet
git-deps would have no chance to determine that.

> > 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 :-)

Yep, I will definitely follow your progress!

Ciao,
Johannes

  reply	other threads:[~2016-05-28  7:07 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
2016-05-28  7:06     ` Johannes Schindelin [this message]
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=alpine.DEB.2.20.1605280841000.4449@virtualbox \
    --to=johannes.schindelin@gmx.de \
    --cc=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).