el_nektarin
el_nektarin

Reputation: 373

How to fix a Git am error ".git/rebase-apply still exists but mbox given"?

I have a folder which contains .patch files only. When I run a command

for myPatch in /d/FolderWithPatches/*.patch; do git am "$myPatch"; done

I receive a fatal: previous rebase directory .git/rebase-apply still exists but mbox given. error. I tried both using git am --abort and simply deleting the rebase-apply folder - neither of this helped actually. Can you help me to fix my issue?

EDIT: I know the issue on Git error: previous rebase directory .git/rebase-apply still exists but mbox given. The answers provided there don't help me to deal with the problem.

Upvotes: 3

Views: 1956

Answers (1)

VonC
VonC

Reputation: 1330012

You now (2024) have a --retry option, that you can combine with additional parameters (like --3way) to see if the issue persists or not.

With Git 2.46 (Q3 2024), batch 14, "git am"(man) has a safety feature to prevent it from starting a new session when there already is a session going.
It reliably triggers when a mbox is given on the command line, but it has to rely on the tty-ness of the standard input.
Add an explicit way to opt out of this safety with a command line option.

See commit 62c71ac, commit 53ce2e3 (06 Jun 2024) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 42b8b5b, 17 Jun 2024)

am: add explicit "--retry" option

Signed-off-by: Jeff King

After a patch fails, you can ask "git am"(man) to try applying it again with new options by running without any of the resume options.
E.g.:

git am <patch
# oops, it failed; let's try again
git am --3way

But since this second command has no explicit resume option (like "--continue"), it looks just like an invocation to read a fresh patch from stdin.
To avoid confusing the two cases, there are some heuristics, courtesy of 8d18550 ("builtin-am: reject patches when there's a session in progress", 2015-08-04, Git v2.6.0-rc0 -- merge listed in batch #2):

if (in_progress) {
  /*
   * Catch user error to feed us patches when there is a session in progress:
   *
   * 1. mbox path(s) are provided on the command-line.  
   * 2. stdin is not a tty: the user is trying to feed us a patch from standard input.
   * This is somewhat unreliable -- stdin could be `/dev/null` for example 
   * and the caller did not intend to feed us a patch but wanted to continue unattended.
  */
if (argc || (resume_mode == RESUME_FALSE && !isatty(0)))
die(_("previous rebase directory %s still exists but mbox given."),
  state.dir);

if (resume_mode == RESUME_FALSE)
  resume_mode = RESUME_APPLY;
[...]

So if no resume command is given, then we require that stdin be a tty, and otherwise complain about (potentially) receiving an mbox on stdin.
But of course you might not actually have a terminal available! And sadly there is no explicit way to hit this same code path; this is the only place that sets RESUME_APPLY.
So you're stuck, and scripts like our test suite have to bend over backwards to create a pseudo-tty.

Let's provide an explicit option to trigger this mode.
The code turns out to be quite simple; just setting "resume_mode" to RESUME_FALSE is enough to dodge the tty check, and then our state is the same as it would be with the heuristic case (which we'll continue to allow).

When we don't have a session in progress, there's already code to complain when resume_mode is set (but we'll add a new test to cover that).

It does, however, mean we're not testing the tty heuristic at all.

git am now includes in its man page:

--retry

Try to apply the last conflicting patch again.
This is generally only useful for passing extra options to the retry attempt (e.g., --3way), since otherwise you'll just see the same failure again.

Upvotes: 1

Related Questions