git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Stefan Haller <lists@haller-berlin.de>,
	Phillip Wood <phillip.wood123@gmail.com>,
	Phillip Wood <phillip.wood@dunelm.org.uk>
Subject: Re: [PATCH v2 4/6] rebase --continue: refuse to commit after failed command
Date: Fri, 21 Apr 2023 14:05:04 -0700	[thread overview]
Message-ID: <xmqqsfcthrpb.fsf@gitster.g> (raw)
In-Reply-To: <9356d14b09a468d8ef2884cd7d76e59ec5c16691.1682089075.git.gitgitgadget@gmail.com> (Phillip Wood via GitGitGadget's message of "Fri, 21 Apr 2023 14:57:52 +0000")

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> If a commit cannot be picked because it would overwrite an untracked
> file then "git rebase --continue" should refuse to commit any staged
> changes as the commit was not picked.

It makes perfect sense to refuse blindly committing.  But this makes
me wonder what the procedure for the user to recover.  In the simplest
case, the untracked file may be expendable and the user would wish to
easily redo the step after removing it?  Like

	$ git rebase
	... stops with "merging will overwrite untracked 'foo'" ...
	$ git rebase --continue
	... refuses thanks to the fix in this step ...
	$ rm foo
	... now what?  "git rebase --redo"?  "git rebase --continue"?
	
> Do this by using the existing
> check for a missing author script in run_git_commit() which prevents
> "rebase --continue" from committing staged changes after failed exec
> commands.

Depending on the recovery procedure, this may or may not be a wise
design decision, even though it may be the quickest way to implement
it.  If the recovery procedure involves redoing the failed step from
scratch (i.e. "rm foo && git reset --hard && git rebase" would try
to restart by replaying the failed step anew), then loss of author
script file has no downside.  If we want to salvage as much as what
was done in the initial attempt, maybe not.

> When fast-forwarding it is not necessary to write the author script as

I'd prefer a comma before "it is not" here.

> we're reusing an existing commit, not creating a new one. If a
> fast-forwarded commit is modified by an "edit" or "reword" command then
> the modification is committed with "git commit --amend" which reuses the
> author of the commit being amended so the author script is not needed.

OK.

> baf8ec8d3a (rebase -r: don't write .git/MERGE_MSG when fast-forwarding,
> 2021-08-20) changed run_git_commit() to allow a missing author script
> when rewording a commit. This changes extends that to allow a missing

It is unclear to me what "This changes extends" refers to.  Could
you rephrase?

> author script whenever the commit is being amended.
>
> If we're not fast-forwarding then we must remove the author script if
> the pick fails.

The changes described in these three paragraphs are about efforts
that were made needed only because the approach chosen to stop
"continue" from continuing in this situation happens to be to remove
the author script.  If it were done differently (perhaps by adding
another flag file that "continue" pays attention to), none of them
may be necessary?

> @@ -4141,6 +4140,7 @@ static int do_merge(struct repository *r,
>  	if (ret < 0) {
>  		error(_("could not even attempt to merge '%.*s'"),
>  		      merge_arg_len, arg);
> +		unlink(rebase_path_author_script());
>  		goto leave_merge;
>  	}

I agree that this is the right location to add new code to stop
"continue" from moving forward.  I do not know if the "unlink the
author script" is the right choice of such a new code, though.

Coming back to my first point, perhaps adding an advice() after this
error() would help end users who see this error to learn what to do
to move forward?

> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> index ff0afad63e2..c1fe55dc2c1 100755
> --- a/t/t3404-rebase-interactive.sh
> +++ b/t/t3404-rebase-interactive.sh
> @@ -1288,6 +1288,12 @@ test_expect_success 'rebase -i commits that overwrite untracked files (pick)' '
>  	test_must_fail git rebase --continue &&
>  	test_cmp_rev HEAD F &&
>  	rm file6 &&

Before the pre-context is an attempt to run "git rebase -i" to
replay a commit that adds file6, stop the sequence by marking a step
as "edit" to take control back.  Then we create file6 manually in
the working tree and make sure that "git rebase --continue" fails in
the pre-context we can see here.

The recovery I asked about earlier is done with "rm file6" in this
case.

> +	test_path_is_missing .git/rebase-merge/author-script &&

This is testing the implementation.  The failed "continue" would
have removed the file thanks to the change we saw earlier.

> +	echo changed >file1 &&
> +	git add file1 &&
> +	test_must_fail git rebase --continue 2>err &&

Then we make some edit, and try to "--continue".  Why should this
fail?  Is it because the earlier "rebase --continue" that failed
did not replay the original commit due to untracked file and the
user needs to redo the step in its entirety before the working tree
becomes ready to take any further changes?

> +	grep "error: you have staged changes in your working tree" err &&
> +	git reset --hard HEAD &&

And this "reset --hard" is another thing in the recovery procedure
the user needs to take (the other one being the removal of file6 we
have seen earlier).  After that, "rebase --continue" will replay the
step that was interrupted by the untracked file6 that was in the
working tree.  OK.

>  	git rebase --continue &&
>  	test_cmp_rev HEAD I
>  '

We of course do not want to become overly "helpful" and run "reset
--hard" ourselves when we issue the "could not even attempt to
merge" message, but when we step back and see what the user wanted
to do, this is still not entirely satisfactory, is it?

My understanding of what the user wanted to do (and let's pretend
that creation of file6 in the middle was merely for test writer's
convenience and in the real scenario of what the user wanted to do,
there was the file left untracked from the beginning before the
rebase started) is to redo the A---F---I chain, making a bit of
change to F when it is recreated, and then replay I on top of the
result of tweaked F.  But instead of allowing them to edit F by
doing some modification to file1, we ended up forcing the user to
discard the edit made to file1 with "reset --hard", and "continue"
replayed I on top of the replayed F that "edit" did not have a
chance to modify.

Of course, the user can now go back to A and replay F and I on top,
essentially redoing the "rebase -i" with FAKE_LINES="edit 1 2" and
this time, because untracked file6 is gone, it may work better and
F may allow to be tweaked.  But then it does not look any better
than saying "git rebase --abort" before doing the final "continue",
which will also allow the user to redo the whole thing from scratch
again.

So, I dunno.


  parent reply	other threads:[~2023-04-21 21:05 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-19 14:48 [PATCH] rebase -i: do not update "done" when rescheduling command Phillip Wood via GitGitGadget
2023-03-20  7:29 ` Stefan Haller
2023-03-20 17:46 ` Junio C Hamano
2023-03-24 10:50   ` Phillip Wood
2023-03-24 15:49     ` Junio C Hamano
2023-03-24 16:22       ` Phillip Wood
2023-03-27  7:04 ` Johannes Schindelin
2023-08-03 12:56   ` Phillip Wood
2023-08-23  8:54     ` Johannes Schindelin
2023-04-21 14:57 ` [PATCH v2 0/6] rebase -i: impove handling of failed commands Phillip Wood via GitGitGadget
2023-04-21 14:57   ` [PATCH v2 1/6] rebase -i: move unlink() calls Phillip Wood via GitGitGadget
2023-04-21 17:22     ` Junio C Hamano
2023-04-27 10:15       ` Phillip Wood
2023-04-21 14:57   ` [PATCH v2 2/6] rebase -i: remove patch file after conflict resolution Phillip Wood via GitGitGadget
2023-04-21 19:01     ` Junio C Hamano
2023-04-27 10:17       ` Phillip Wood
2023-06-21 20:14     ` Glen Choo
2023-07-14 10:08       ` Phillip Wood
2023-07-14 16:51         ` Junio C Hamano
2023-07-17 15:39           ` Phillip Wood
2023-04-21 14:57   ` [PATCH v2 3/6] sequencer: factor out part of pick_commits() Phillip Wood via GitGitGadget
2023-04-21 19:12     ` Eric Sunshine
2023-04-21 19:31     ` Junio C Hamano
2023-04-21 20:00       ` Phillip Wood
2023-04-21 21:21         ` Junio C Hamano
2023-04-21 14:57   ` [PATCH v2 4/6] rebase --continue: refuse to commit after failed command Phillip Wood via GitGitGadget
2023-04-21 19:14     ` Eric Sunshine
2023-04-21 21:05     ` Junio C Hamano [this message]
2023-06-21 20:35     ` Glen Choo
2023-04-21 14:57   ` [PATCH v2 5/6] rebase: fix rewritten list for failed pick Phillip Wood via GitGitGadget
2023-06-21 20:49     ` Glen Choo
2023-07-25 15:42       ` Phillip Wood
2023-07-25 16:46         ` Glen Choo
2023-07-26 13:08           ` Phillip Wood
2023-07-26 17:48             ` Glen Choo
2023-07-28 13:19               ` Phillip Wood
2023-04-21 14:57   ` [PATCH v2 6/6] rebase -i: fix adding failed command to the todo list Phillip Wood via GitGitGadget
2023-06-21 20:59     ` Glen Choo
2023-04-21 16:56   ` [PATCH v2 0/6] rebase -i: impove handling of failed commands Junio C Hamano
2023-06-21 20:07   ` Glen Choo
2023-08-01 15:23   ` [PATCH v3 0/7] " Phillip Wood via GitGitGadget
2023-08-01 15:23     ` [PATCH v3 1/7] rebase -i: move unlink() calls Phillip Wood via GitGitGadget
2023-08-01 17:22       ` Junio C Hamano
2023-08-01 18:42         ` Phillip Wood
2023-08-01 19:31           ` Junio C Hamano
2023-08-01 15:23     ` [PATCH v3 2/7] rebase -i: remove patch file after conflict resolution Phillip Wood via GitGitGadget
2023-08-01 17:23       ` Junio C Hamano
2023-08-01 18:47         ` Phillip Wood
2023-08-01 15:23     ` [PATCH v3 3/7] sequencer: use rebase_path_message() Phillip Wood via GitGitGadget
2023-08-01 17:23       ` Junio C Hamano
2023-08-01 18:49         ` Phillip Wood
2023-08-02 22:02           ` Junio C Hamano
2023-08-01 15:23     ` [PATCH v3 4/7] sequencer: factor out part of pick_commits() Phillip Wood via GitGitGadget
2023-08-23  8:55       ` Johannes Schindelin
2023-08-01 15:23     ` [PATCH v3 5/7] rebase: fix rewritten list for failed pick Phillip Wood via GitGitGadget
2023-08-23  8:55       ` Johannes Schindelin
2023-09-04 14:31         ` Phillip Wood
2023-08-01 15:23     ` [PATCH v3 6/7] rebase --continue: refuse to commit after failed command Phillip Wood via GitGitGadget
2023-08-23  9:01       ` Johannes Schindelin
2023-09-04 14:37         ` Phillip Wood
2023-09-05 11:17           ` Johannes Schindelin
2023-09-05 14:57             ` Junio C Hamano
2023-09-05 15:25             ` Phillip Wood
2023-08-01 15:23     ` [PATCH v3 7/7] rebase -i: fix adding failed command to the todo list Phillip Wood via GitGitGadget
2023-08-02 22:10     ` [PATCH v3 0/7] rebase -i: impove handling of failed commands Junio C Hamano
2023-08-03 13:06       ` Phillip Wood
2023-08-09 13:08       ` Phillip Wood
2023-08-07 20:16     ` Glen Choo
2023-08-09 10:06       ` Phillip Wood
2023-09-06 15:22     ` [PATCH v4 " Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 1/7] rebase -i: move unlink() calls Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 2/7] rebase -i: remove patch file after conflict resolution Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 3/7] sequencer: use rebase_path_message() Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 4/7] sequencer: factor out part of pick_commits() Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 5/7] rebase: fix rewritten list for failed pick Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 6/7] rebase --continue: refuse to commit after failed command Phillip Wood via GitGitGadget
2023-09-06 15:22       ` [PATCH v4 7/7] rebase -i: fix adding failed command to the todo list Phillip Wood via GitGitGadget
2023-09-06 21:01       ` [PATCH v4 0/7] rebase -i: impove handling of failed commands Junio C Hamano
2023-09-07  9:56       ` Johannes Schindelin
2023-09-07 20:33         ` Junio C Hamano

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=xmqqsfcthrpb.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=lists@haller-berlin.de \
    --cc=phillip.wood123@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    /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).