Incremental backup in central backup directory
From Vim Tips Wiki
created July 22, 2005 · complexity basic · author Sylvain Lafleur · version 5.7
Before using Vim, I used a nice little editor called Crimson. It had a nice backup feature that I used all the time. It could be set to automatically backup the current file whenever it was opened up. And all the backups would go to a dedicated backup directory. Furthermore, it kept the full directory structure.
- I edit the file e:\project1\web\show_users.asp, when i open it up, a backup would be created at f:\vim_backups\E\project1\web\show_users.001
- If I close my editor and re-open the file again in the afternoon, i would get another backup at f:\vim_backups\E\project1\web\show_users.002
This could lead to a huge number of files but it's easier to retrieve data that is there many times, than to retrieve data that does not exist anymore. Also, a simple zip takes care or any hard drive space issues. I have gone many times to that backup directory because my supervisor wanted the page to go back to what it was two days ago. It's been very useful.
In Vim, however, only 1 backup is created, and it's in the current directory. You can easily modify Vim to save all backups in a single directory, using the :set backupdir option but then you still only have the one latest backup. I created this short set of commands to make Vim have similar functionality as Crimson for backups (it uses date and time instead of numbers for the backup extension). It's the first version, so there might be some bugs, feel free to add/improve to your hearts content. Also, it's set up for Windows Vim right now, but it should be fairly easy to modify it for use on *nix machines.
step1:set variables this_root_backup_dir = the root directory where all backups will be saved this_dir = current directory of file you just opened this_filename = current filename of file you just opened this_drive = drive where the file you just opened is located (Windows) this_backup_dir_drive = drive that should exist in this_root_backup_dir this_backup_dir = full backup path starting from the root backup directory step2:check if the necessary drive letter exist in root backup directory, if not create it step3:check if the necessary directory exist in root backup directory, if not create it step4:set the new backupdir option for vim
I have these line in my vimrc file:
"Incremental backups, will copy the backup file to a specific backup "directory and follow the tree structure of the file's directory "This allows for backup up from multiple drives (on Windows) and easy "navigation through the backups afterwards. let g:this_root_backup_dir = 'f:\vim_backups' let g:this_dir = expand('%:p:h') let g:this_filename = expand('%') let g:this_drive = strpart(g:this_dir, 0, 1) let g:this_backup_dir_drive = g:this_root_backup_dir . '\' . g:this_drive let g:this_backup_dir = g:this_backup_dir_drive . '\' . strpart(g:this_dir, 3) "--make DRIVE directory if it doesn't exist if !filewritable(g:this_backup_dir_drive) silent execute expand('!mkdir ' . g:this_backup_dir_drive) endif "--make directory under DRIVE if it doesn't exist if !filewritable(g:this_backup_dir) silent execute expand('!mkdir ' . g:this_backup_dir) endif "--set new backup dir execute expand('set backupdir=' . g:this_backup_dir)
Found first bug: Error occurs when you open a file with a space in either the directory or the filename.
I fixed it with a substitute command, replacing all spaces with an underscore.
:let this_dir=expand("%:p:h") :let this_filename=expand("%")
:let this_dir=substitute(expand("%:p:h")," ","_","g") :let this_filename=substitute(expand("%")," ","_","g")
You really should use a version control system for this, like cvs or subversion. Then the text editor doesn't enter into it at all.
You could write very simple hooks to VIM that check in any changes automatically when you enter or exit the editor.
For Windows, try Subversion with TortoiseSVN: http://tortoisesvn.tigris.org/
augroup backup autocmd! autocmd BufWritePre,FileWritePre * let &l:backupext = '~' . strftime('%F') . '~' augroup END