22

I have a way to handle swap files.

And it works but it takes a while.

Here goes:

  • First I try to find the original vim session -- track down if the PID is still alive -- and if the PID is still alive I go try and find that vim session and save the file and quit... and I'm done (stop here) -- If I can't open the vim session I kill the PID... and have to recover the file.

  • try to view the diff

    • I hit r to recover the file
    • save the recovered file to a temporary file
    • quit vim
    • do a command line vimdiff between the two
    • manually fix any conflicts
    • save the file
    • quit vim
    • delete the temporary file
    • reopen vim
    • done

I wanted to find a way to do the same thing but more efficiently.

How do I view the diff of the file with the recovered file, resolve any differences, save the file without quitting vim or using plugins?

3
  • 2
    you might be interested in my Recover plugin Mar 15, 2018 at 15:41
  • Recover does not support Neovim atm.
    – tejasvi88
    Jul 6, 2021 at 15:28
  • 1
    defaults.vim defines a command for viewing the changes made to a buffer, including the changes made during recovery. Unfortunately defaults.vim is not sourced if a user .vimrc is present. See :help :recover and :help :DiffOrig. Feb 20, 2023 at 4:10

5 Answers 5

25

Here is the vim commands you need to view the diff, resolve any differences, and save the file. All done without quitting vim or using plugins.

From the command line, open the file, there will be a command line prompt, choose to "recover the file" by selecting r, then the rest of the steps are all inside vim:

  1. save the recovered file (if the destination file exists, then overwrite)
    • :sav! ~/.recovered
  2. open the original (not-recovered file) in a new window
    • :vsplit
    • ctrl-w w
    • :bn
    • e
    • on the left, is the recovered file
    • on the right, is the un-recovered file
  3. diff the two files
    • :diffthis
    • ctrl-w w
    • :diffthis
    • now we have a diff of the two files (see man vimdiff)
  4. resolve any conflicts (see man vimdiff for more info)
  5. save any changes made to the unresolved file
  6. delete the swap file
    • :!rm -v path/to/.file.swp
  7. quit vim
    • :q

I am sure there are better methods because my solution requires 7 steps. If you have a better solution please edit my solution or provide a better solution.

p.s. I must give credit where credit is due.

I started with the solution from http://vim.wikia.com/wiki/Swap_file_%22...%22already_exists!_-_so_diff_it

I modified the linked solution because

  • the linked solution does not handle opening a file that is under a directory
  • the instructions on that page were not clear and required lots of time for me to reverse engineer what was needed... hence this written solution
4
  • 3
    I won't edit your solution, because I don't know if it's really an improvement or not, but personally I would do :windo diffthis instead of :diffthis <C-w> :diffthis. Also, I believe the <C-w>s in your answer should be <C-w> ws instead; this will switch between windows, which seems to be the goal.
    – brhfl
    Mar 15, 2018 at 18:28
  • This is amazing up until man vimdiff at which point I'm lost. The vimdiff manpages I have seen online and on my laptop are quite terse and no help here.
    – Aaron Hall
    Apr 27, 2021 at 3:11
  • vimdiff has the basic features similar to kompare or beyondcompare. i suggest reading a good how to tutorial or guide. the main keys i use in vimdiff are: do, dp, next change ]c, prev change [c, switch window ctrl+w ctrl+w. Apr 27, 2021 at 12:18
  • This is a great answer! What do you think of using :echo delete(&dir ."/". expand("%") . ".swp") to delete the swap? source Jul 8, 2021 at 17:52
10

View diff of a swap file without plugins

Without plugins, you can use vim alternate-file. Wikia source: Diff current buffer and the original file

In short, try this:

:diffthis | :vnew | r # | exe "norm! ggdd" | :diffthis

Explained:

" start diff in current window with restored swap file
:diffthis 

" read origin file in new vsplit
:vnew | r # 

" Note: origin file is read to buffer,
" but first line is epmty
" It's a feature, so let's delete first empty line 
:exe "norm! ggdd" 

" start diff mode in vsplit
:diffthis

View and merge diff of a swap file using Recover plugin

Also, there is a plugin Recover.vim.

Found a swap file by the name "test/normal/.testfile.swp"
        owned by: chrisbra   dated: Wed Nov 28 16:26:42 2012
        file name: ~chrisbra/code/git/vim/Recover/test/normal/testfile
        modified: YES
        user name: chrisbra   host name: R500
        process ID: 4878 [not existing]
While opening file "test/normal/testfile"
            dated: Tue Nov  6 20:11:55 2012
Please choose:
[C]ompare, (O)pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort, (D)elete:

After merge, you can delete swap-file using command :FinishRecovery

3
  • 1
    Hi @BLayer, thx. Updated answer - added solution using alternate-file
    – Yasen
    Jul 2, 2019 at 9:40
  • Recover.vim plugin works fine for me with Neovim v0.4.4 @tejasvi88
    – Martin
    Aug 4, 2021 at 9:22
  • i have not tried your solution. but your solution looks significantly better because my solution requires 7 steps and your solution looks like it is only 1-2 steps. Feb 1, 2023 at 17:40
2

Based off Trevor's answer, I made the following commands for dealing with swap files:

noremap <LEADER>s <C-w>o:sav! ~/.vim/.recovered<CR>:vs<CR><C-w>w:bn<CR>
noremap <LEADER>t  :wa<CR>:bp\|bd #<CR><C-o>

Upon reaching the ATTENTION: Found a swap file... prompt, I

  • type r to recover the swap
  • type <LEADER>s to save the swapped version as .recovered and open the original in a new split
  • type e at the swap prompt to edit the original file
  • type :windo diffthis to diff the two files
  • make any necessary changes to the original
  • type <LEADER>t to write the original file, close it, and reopen it
  • type d at the swap prompt to delete the swap file
  • close the .recovered file (typing something like :bp<CR>:bp\|bd #<CR>).
1

This answer has my upvote but I think in many cases it is wrong for my workflow, especially for what is likely to be small changes which is usually the case for me. Instead, I suggest using:

The (R)ecover option when attempting to open a file with an extant .swp file.

It restores the buffer to the swap file's state without saving.

Then if you then want to see the diff on the buffer from the saved state, you can run the following command in command mode:

:w !diff % -

The above writes the buffer to the standard input of the diff command, which gets the name of the file as the first argument, effectively diffing the buffer versus the saved file, allowing you to determine what changed and make further updates before saving, if you so desire.

The above is usually sufficient for what I want to know about the swap file and I can continue without leaving vim.

I think this is so useful that I have created the below alias command for my vimrc file:

command! -nargs=0 Diff w ~diff % -

Usage is simply:

:Diff

If the diff is too large or you are still not certain, then as the message after (R)estore says, you can just save the buffer to a new file name and quit without saving to the original file:

:w filename.backup
:q!

then you can use, for example, vimdiff to check out the differences:

$ vimdiff filename filename.backup
0

Fortify @trevor-boyd-smith and @brhfl suggestions by amending the "delete swap file" command to purge ALL .swp and .recovered files. NB: Update paths, if necessary.

:!rm -v {~/.vim_tmp/file.sw*,~/file.recovered}
1
  • Welcome to vi.se. Note that for such a little modification of an existing answer you can simply edit the answer (the edit will be reviewed by the community) it makes it more likely that users will read your contribution.
    – statox
    Feb 25, 2022 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.