Steven Lu
Steven Lu

Reputation: 43427

Retain undo history if file is edited outside of Vim

The Vim undofile is purged when the file is edited outside the editor.

How can I get it so I can revert the file to older versions even if it was edited outside of Vim? Is this possible?

Upvotes: 6

Views: 578

Answers (3)

Steven Lu
Steven Lu

Reputation: 43427

Looking at the setup I've been driving since 2015:

let vimtmp = $HOME . '/.tmp/' . getpid()
silent! call mkdir(vimtmp, "p", 0700)
let &backupdir=vimtmp
let &directory=vimtmp
set backup

I'm contemplating bringing this forward into my new 2023 lua nvim config.

There are a few properties of doing what I did here:

  • Each vim process stores swap and backup into fresh new dirs named after their pid
  • In practice this has kept me from encountering a lot of the kind-of-annoying-now-with-my-new-fresh-config dialog of swapfile found, do you want to edit anyway or abort. This is because a new process will get directory in its own pid specific directory and vim works like any typical editor, the file gets clobbered when you save. That's what's expected. And now I have the option in the event of system crashes to find all past swap and backup files that may have been left behind. In practice over nearly 10 years I never leveraged this but it feels nice to have it available.
  • Although this did not address the issue of undofile "corruption" caused by external file modification events, at least conceptually speaking I don't even see how this could be possible without the internal undo mechanism gaining the smarts to detect such events and inserting non-diff-based journaling. Granted... this should be done because vim CAN recognize when the file gets externally modified, e.g. I had a au FileChangedShell * echo "Warning: File changed on disk!!" in my config. This worked well in practice and always picked up a change instantly, but reading vim's own documentation on this aucmd it's not clear we should expect it to always detect actual file changes...

So I'm still kind of undecided here on whether to carry this behavior forward to my new fresh config but it's definitely tempting. What I can say is that vim/nvim checking for swapfiles present before editing the file has not been helpful behavior for me because in practice it's always been instantly able to re-load the buffer with the state of the file whenever (typically a second instance of vim) it is changed underneath. So inside vim I'll never really be looking at some old shadow version of the file, which would be annoying (and what the default swap check behavior is intended to protect against).

I think what I'm going to be doing in the next few days is considering the actual behavior and that means find out if there is a more modern lua-based replacement for the undo tree plugin I have been very happy with up till now which is mbbill/undotree. Furthermore I shall want to investigate how the config i'd been driving for a decade has handled changed files, whether undoing past an external file change event is being managed in a good way and whether a simple way to improve it exists.

In addition to the above pasted config, I was also setting

set undodir=~/.tmp
set undolevels=10000
set undofile

This means that although my swap file and backup locations are isolated in pid specific files (so, fresh for each vim instance), the undofile is NOT. I feel like my experience has been that this worked really well (undoing past external change actually shows me the external change, just not as nicely as I might perhaps want (some kind of diff) but correct enough in its behavior to leave me satisfied). But that's only from memory since this sort of thing doesn't happen much. usually only when i have two vims with one file open and alternate editing from each because of forgetfulness.

Upvotes: 1

cforbish
cforbish

Reputation: 8819

If you mean the undo that is invoked by the letter u, on my system I do not see the file returned by undofile(@%), even if I did I do not think I would be able to delete it. It does not effect my ability to use the u key.

If you mean some other person/program modified a file that you currently have open in vim, you should be given a notification the file has changed. Options are OK and Load File. If you press OK, you can press the u key and forcefully write :w!. This will wipe out the other persons/programs changes.

Please explain in more detail if neither of these answers apply to you.

Upvotes: -1

perreal
perreal

Reputation: 97938

You can use vim backup:

set backup                   " enable backup file
set backupdir=~/.vim/backups " backup directory

then you can go and grab the last backup vim saved in case you want to revert after an external edit but this is not like undofile. From vim wiki:

However, note that if a file is modified externally without Vim, Vim will not be able to read the undo history back when you start editing the file again and the undo tree information will be lost. There is no way to get it back.

Upvotes: 2

Related Questions