Subject: Re: [RFC PATCH v2] revert: Implement --abort processing

From: Jonathan Nieder <[email-masked]>
Date: Sat, 11 Jun 2011 06:22:13 -0500

Ramkumar Ramachandra wrote:

>  I've persisted the TODO early, and made it complain when an existing
>  cherry-pick/ revert is in progress.  Further, as Junio suggested,
>  I've made no attempt to touch the index or the worktree during the
>  --abort operation: I simply update HEAD and leave the user to do the
>  rest.

Is that what Junio was suggesting?  I thought he was saying that
cherry-pick shouldn't support an --abort option at all, since the
"right" semantics are hard to find.

I have sympathy for that point of view, too, but it's hard to
come up with the right choice.

On one hand: "git am" has an --abort option so you can say, "Forget
it; I'm going to go back to my mailer and make a better mailbox."
"git rebase" has an --abort option to let you to walk away in a
comfortable state, instead of leaving the HEAD detached and halfway
through replaying your work.  "git bisect" has a reset subcommand for
a similar reason.  All of the abort actions just mentioned take a
somewhat weird state (e.g., patch series partially applied, maybe with
conflicts) and go back to something more familiar.  Which is useful,
especially for people just starting out.

It applies equally to cherry-pick: a user doing something crazy like

	git cherry-pick HEAD..linux-next

to incorporate all patches from linux-next on top of her local changes
is creating a mess; there is appeal in having a way to say "clear that
away and take me back to something I knew".

On the other hand: all three of the above "abort" actions can be a
pain in the neck in practice.  The worst case is when I forget about
the sequence in progress and do something else, and only later want to
clear the state:

 http://thread.gmane.org/gmane.comp.version-control.git/164002/focus=164046

There are other cases, too, like when after partially rebasing I
decide this isn't a good direction for the original branch after all
but I want to end the rebase and develop HEAD as a new branch instead.
The --abort command is quite destructive and not very flexible.

I guess if I were in your shoes, I'd be tempted to start by saving the
old HEAD and making it visible as a pseudo-ref or something,
advertising that, and then observing people's behavior with the hope
of using that knowledge to come up with good semantics for a command
to cancel cherry-picks of commit ranges.  Do people use "reset --hard"
or "reset --merge"?  Do they throw away all the commits cherry-picked
or just a few?  Do they ever intend to abort like this even after
veering from the standard sequence, like in Linus's example?  After
aborting a multiple cherry-pick, what does a person generally do next?

The documentation could say:

	To wipe out everything and get back to where you started, use:

		git reset --hard PRE_CHERRY_PICK_HEAD

What if instead of --abort something else were simpler to think about?
As a random example, I can imagine a "git sequencer --edit" command
that would present the sequence in an editor and let me revise the
plan --- would that do the trick?

	1
	2
	3
	4
	* YOU ARE HERE
	5
	6
	7
	8

 - Remove lines 5-8: removes sequencer state, leaves HEAD as is
 - Remove everything: rewinds to abort sequence
 - Add a line 2.5 between 2 and 3: rewind to 2, cherry-pick 2.5,
   continue.

And having said that, I personally start to see an --abort command as
interesting, because it is a specific case that could help flesh out a
more general behavior of rewinding some day years from now.

Which is to say: if you have a story about what --abort will be used
for, the life of others evaluating the thing becomes better and the
upsides and downsides can be seen in perspective.  A story like "am
and rebase have --abort, so cherry-pick should have one, too" is
harder to think about.

Hope that helps.