Recover a vim file from the .un~ file without the undo command - vim

How can I restore a vim file from the undo file without hitting undo?
I had a vim file that I saved while adding text. Then I ran a python command that emptied the file's contents, and I can see some of the words the file contained in the file's .un~ file. When I try to undo in the file, it says Already at latest change. I can't find the swap file in my swap files directory.

As the other answers have noted, you can't recover the whole file from vim's undo files, simply because vim seems to only keep diffs in the undo files, not the whole contents. (That makes a lot of sense, as it's space efficient.)
One thing you can try though, is to extract what's possible from your undo file:
$ strings <undo-file>
The output will not be pretty, but you could end up finding something that's valuable to you.

You can't. The undo information is linked to Vim's last knowledge of the file's contents; when they don't correspond any more, Vim cannot re-apply the changes. This is documented at :help undo-persistence:
Vim will detect if an undo file is no longer synchronized with the file it was
written for (with a hash of the file contents) and ignore it when the file was
changed after the undo file was written, to prevent corruption.
Best you can do is try to manually salvage recognizable bits in the undo file, e.g. with a hex editor, or Vim's binary mode.

It is not exactly possible, as the undo file only contains the text that was changed in a single change. If you at some point reloaded the file, the undofile should contain the complete buffer for that and starting from there one could theorectically recover the file (by going through the undo states).
I have written about this before at the vim_use mailinglist here and here (which even contains a patch, that let's you force reading in the undo-file)
You could try to patch vim and see if you can recover at least some data.

A reminder that if you have set in your .vimrc file
set backupdir=$HOME/tmp
You may have temp copies of the files that are readable and that can be renamed

Related

What are some use cases of :e in Vim?

I was reading :help :edit but I really don't understand the following sentence:
This is useful to re-edit the current file, when it has been changed outside of Vim
And what does start all over mean in :help :edit!?
This is useful if you want to start all over again
Could anyone please provide some use cases of them?
"Changed outside of Vim" means that the file that you're editing has been written to by another program. :e will load the latest version, and :e! will do that even if you have unsaved changes.
Loading the current file from the file system is useful if you're following a log, or viewing a generated file that gets updated when you run :make and other situations.
One use for this is to throw away the changes you've made since the last save with :w and go back to the most recent saved version. Which is to say, it's not necessary for the file to have changed behind Vim's back for this to be useful. Although Vim has enough undo depth that you can usually undo your way to back to the unmodified state, it's cumbersome. You can easily "overshoot" and then have to redo. The status line shows you whether the file is [Modified] or not, but as you undo, it gets overwritten with information about each undo, so you have to use Ctrl-G to re-display the file status.
I had no idea :e by itself with no argument did this re-loading, by the way; I have been using :e% for years!

Undo recovery from swap file in vim

Right before committing a major change, I accidentally "recovered" the file from an old and outdated swap file in vim. My changes seem to be gone. I've tried exploring the undo tree but large chunks of changes are still missing. Is there anyway I can undo the recover operation or am I doomed?
The following works for me to recover the file, with undo history as well:
Assume you have my_file, that has some persistent undo history + unsaved changes in .my_file.swp
Open file with vim, and press r to get the recovery version
Save recovery version to temporary location e.g. :w /tmp/%
Close without saving (:q!). Open file again, and press d to delete swap file
Optional: compare /tmp/my_file and my_file to make sure you want the recovered version
Manually add changes from /tmp/my_file (e.g. ggdG and :r /tmp/% )
This can probably be simplified, but this works for me.
PS: This does not give you the undo history for the changes between the on-disk and recovered version of the file, that appears as one big edit in the history.
After accidentally recovering the file you can simply type :q! to exit vim without saving the recovered changes - this will leave your original file intact and the swap file where it is.
The next time you open the file, you'll see the same prompt - press D to delete the swap file, or abort and find it manually (and possibly delete any other swap files in the same location)
I just tried this myself (with persistent undo enabled; Vim version 7.3.823). The old changes were still showing (in :undolist, though I usually use a plugin like Gundo or Undotree to visualize it), but when attempting to restore, I get
E438: u_undo: line numbers wrong
Seems like Vim cannot handle this situation. Note that you've been warned; the recovery explictly warns:
Recovery completed. You should check if everything is OK.
E308: Warning: Original file may have been changed

Stop Vim from saving a file if content has not changed

In GUI text editors I've seen, when text has not changed (or has changed and been reverted to its original state), the Save option is greyed out to indicate so.
For something similar, can Vim disable saving a file in such a case? That is, doing the :w would not actually change the mtime of the file.
You can use the :update command (:up for short) which writes the file only if the buffer has been modified. If you felt strongly you could add an update option to gvim's File menu, but maybe the Ex command is sufficient.
WRITING WITH MULTIPLE BUFFERS *buffer-write*
*:wa* *:wall*
:wa[ll] Write all changed buffers. Buffers without a file
name or which are readonly are not written. {not in
Vi}
:wa[ll]! Write all changed buffers, even the ones that are
readonly. Buffers without a file name are not
written. {not in Vi}
:wa will save all changed files
:xa will save all changed files, and then quit vim.

How to mantain or export folds when copying a file in Vim

Every time I copy a file the folds are lost. I understand why this happens, but I can''t figure out out to "export" or "maintain" the folds. Any suggestions? (otherwise I have to rename the view files one by one if I copy a entire folder).
EDIT: I'm folding lines by writting for instance: :1,80 fo
Read the lovely manual, :help foldmethod.
With the manual folds you are using:
The manual folds are lost when you abandon the file. To save the folds use
the :mkview command. The view can be restored later with :loadview.
Or, you can set foldmethod=marker, and then :fold will litter your file with {{{ and }}} to indicate where the folds are. Since the default value is manual, you'll have to set it to marker, either in a modeline or in your vimrc.
Or you can use :saveas.
It will make a copy of your file and its view into a new file with its own view.
Your original file and view will be left untouched.
:edit original.md
:saveas copy.md
The only downside is that if you have file marks (A-Z), they will be moved (not copied, moved) to your new file.

Vim: Maintain the history of a file after it has been changed and reloaded

If I'm editing a file in Vim, then some external program changes the file, Vim tells me:
W11: Warning: File "test.erl" has changed since editing started
See ":help W11" for more info.
[O]K, (L)oad File:
If I Load the file, though, all the undo history is lost.
Is there any way to avoid that?
Update: it appears that this is one of the new features in Vim 7.3: https://groups.google.com/group/vim_announce/browse_thread/thread/66c02efd1523554b
I don't believe this is possible.
There is a very useful patch available for the vim source code available here that keeps the undo history after exiting vim and restarting. However, I've just tried it and it seems to fail when the file is edited externally. It might be worth contacting the author or reporting a bug on the patch website to see if this can be overcome.
G'day,
I'm not sure but does setting autoread, i.e. entering :set autoread leave the undo history for the file when it changes?
Hmmmm. I'm thinking probably not because the change history is maintained as line numbers and vim doesn't know if those line numbers are still relevant to the changed file.
BTW WTF are you editing a file that is being changed by external forces anyway? Sounds dangerous to me. (-:
This is a workaround I used before Vim 7.3:
" :e usually clears undo history, so we don't really do :e any more.
" Instead we delete the contents of the buffer, then read the file in, which
" is an operation we can undo. We must delete the top (empty) line also.
:map :e<Enter> :%d<Enter>:r<Enter>:0<Enter>dd
When you see the warning prompt, you would have to hit ok instead of load, and then perform the load yourself: :e<Enter>
There are two disadvantages (although I found the tradeoff acceptable):
You lose the line you were on. Your cursor is left sitting at the top of the file.
Vim still thinks the buffer is out of sync with the file, so when you next save, you may need to do :w! instead of the normal :w, and you will need to hit y to confirm the overwrite.
Edit: There might be a workaround for the second problem.
Edit: The first problem could be addressed with a bit more scripting (see :h line.)
I don't see how vim could keep track of something it didn't do.
So, as to the question, I would suggest - source control ... but that's probably not the answer you're looking for.

Resources