A few days later, I answer my own question. My answer isn't a very good answer. It's only a workaround and I have tested it only tentatively and only on a Debian 11 bullseye platform (so the answer probably wants adaptation for use on Windows); but since no other answer has yet been posted here it is.
To work around the problem as I have done, one should do the following.
First, make a new directory $HOME/bak
(if it does not already exist) and subdirectory $HOME/bak/vim
(this should be new)—where $HOME
is your home directory.
Second, add this line to the per-user configuration file $HOME/.vimrc:
set backupdir=$HOME/bak/vim
(Again, substitute the proper value for $HOME. For example, my username is thb
, so I have added, set backupdir=/home/thb/bak/vim
.) If $HOME/.vimrc does not exist, then create it and add the above line.
Third, if Vim is running, exit and, if you wish, restart.
Why does this solution work? Actually, I am unsure that it does work, but since I have implemented it a few days ago, I have not seen the problem to occur again. The intent is to funnel backups, including spurious backups, into a single directory that keeps the backups out of the user's way. However, once I had put the funnel in place, the problem seemed to disappear altogether for some reason. No spurious backups seem to be going into the funnel, but only ordinary backups explicitly requested by set backup
. No spurious backups seem to be going anywhere, whereas I used to encounter one or two spurious backups a day.
It is as though the funnel had frightened the spurious backups away.
I do not know the reason the funnel has frightened the spurious backups away (if indeed it has), since I still do not know why the spurious backups started haunting me in the first place. I do not doubt that a logical reason exists, only I do not know what the reason is.
Anyway, in case this workaround is useful to anyone, there it is.
CONJECTURE
I used to encounter the problem occasionally (once or twice a month) on Debian 10 buster. After installing Debian 11 bullseye, the frequency increased to once or twice a day, as I said. I have never been able to reproduce the problem at will.
I conjecture therefore that the problem descends from a race condition: when I am relaxed and not focusing on reproducing the problem, some quick, unconscious sequence of keystrokes of mine is sometimes overloading an internal buffer of Vim's before Vim can clear the buffer. Perhaps it's when I type :w
plus something else immediately before or after. I don't know, but whatever it is panics Vim, upon which Vim, to be safe, writes a backup to avoid losing the buffer.
If the conjecture is right, then setting aside a separate, safe backup directory seems to have soothed Vim's panic. Or perhaps, once the backupdir
configuration is set, Vim internally diverts onto a different, quicker codepath that outpaces my keystrokes. Hence, no panic and no spurious backup.
DIAGNOSTIC
In chat elsewhere, @filbranden has given a potentially useful procedure. I have achieved no concrete result from it but the procedure might prove of use to someone else.
Try using strace: strace -f -s 1024 -tt -o ~/vim-strace.txt vim
, then reproduce the problem. Inside the ~/vim-strace.txt
file you'll find a line where it's opening foo.bak
(for writing) and you can see the PID of the process that did that. Look up for an exec
(might be execv
or execl
etc.) that shows what command was executed in that process. That might give you a hint...
UPDATE
Three weeks later, I can report that the above-described workaround has worked flawlessly.
I do not know why the workaround works, but with the workaround in place, spurious backups apparently no longer occur at all.
:set bex?
tells mebackupext=~
. This is why I do not understand the reason Vim is emitting the filefoo.bak
at seemingly random intervals. If I:set backup
, then Vim will producefoo~
, as one would expect. Apparently, thefoo.bak
comes from somewhere else.strace -f -s 1024 -tt -o ~/vim-strace.txt vim
, then reproduce the problem. Inside the~/vim-strace.txt
file you'll find a line where it's openingfoo.bak
(for writing) and you can see the PID of the process that did that. Look up for anexec
(might beexecv
orexecl
etc.) that shows what command was executed in that process. That might give you a hint...