31

Undo is nice to have in Vim. But sometimes, at a known good point, I want to erase my undo history - to be able to use u to undo individual changes, but only back to a certain point. (For instance, this might be when I last committed.)

One way to accomplish this would be to close and reopen the file - the undo history starts clean at that point. But that's a hassle.

In the past, I accomplished this with :edit!. But in Vim 7.3, that doesn't discard the undo history.

Is there another way to do this, apart from closing the file?

3
  • so you actually just want to restore the state of the file as it was on your last commit? you want essentially just remap the 'u' key to something like git checkout -f file or hg rollback file?
    – akira
    Nov 24, 2010 at 18:34
  • @akira - no, I want to be able to use u to undo individual changes, but not past the point where I last committed. Exactly as if, every time I committed, I closed the file and re-opened it. Which is what :edit! used to do - it was like closing the file and reopening it. This doesn't HAVE to be tied to a commit point, that's just the time when I'd most frequently want it. Nov 24, 2010 at 20:08
  • ah, that makes the problem much clearer. you should change your question a bit.
    – akira
    Nov 24, 2010 at 20:24

6 Answers 6

16
:set undoreload=0 | edit

should do what you're asking for.

1
  • 1
    Ha! Just turn that feature off, eh? :) Not sure why it took me so long to notice this. Oct 21, 2012 at 12:32
8

The old :edit! behaviour in a one-liner:

:exe "set ul=-1 | e! | set ul=" . &ul
2
  • That does work. Would you mind explaining it? Jun 7, 2012 at 20:06
  • Concatenate the value of the undolevels setting on the end of the string of commands (so that it can be restored) and executes them. For more info see the documentation: :h :exe, :h :bar, :h :set-args, :h 'ul' and :h :edit!.
    – Aldrik
    Jun 18, 2012 at 17:07
6

Benoit's function didn't work for me, but I found something similar in the vim manual, here:

http://www.polarhome.com/vim/manual/v73/undo.html#undo-remarks

I slapped it into a function, added to my vimrc and it seems to be working fine on vim 7.3:

" A function to clear the undo history
function! <SID>ForgetUndo()
    let old_undolevels = &undolevels
    set undolevels=-1
    exe "normal a \<BS>\<Esc>"
    let &undolevels = old_undolevels
    unlet old_undolevels
endfunction
command -nargs=0 ClearUndo call <SID>ForgetUndo()

This can be used with :ClearUndo.

2
  • 1
    Working normally with Gundo plugin and undo file reloading, this thing comes really handy for me. However, I changed two things: instead of the normal edit command (which itself leaves some edit history on 7.4 it seems), I simply use an edit! (and always write before erasing the undo history). It seems that some internal lists are not properly updated, so if you want to use this with Gundo plugin, doing an additional edit! at the functions end will prevent it from erroring out later.
    – PlasmaHH
    Dec 20, 2013 at 10:39
  • @PlasmaHH Could you please post the function for clearing undo history, because I did not understand what did you change... (you could maybe post it as an answer for those of us who use gundu). Thanks
    – Ben
    Feb 25, 2014 at 12:10
5

Probably:

:let old_ul=&ul
:set ul=-1
:let &ul=old_ul
:unlet old_ul

('ul' is alias for 'undolevels').

4
  • This works! Now I'm trying to make a single command do that - preferably :edit!. As a start, I've made a function called ClearUndos() with the commands you listed, but calling it doesn't seem to do anything, whereas doing the commands individually does... Nov 24, 2010 at 20:25
  • 3
    :command -nargs=0 Reset let old_ul=&ul | set ul=-1 | e! | let &ul = old_ul | unlet old_ul
    – Benoit
    Nov 24, 2010 at 21:38
  • is that meant to be the contents of the function? It's not working for me, but maybe I misunderstood. Also - maybe move this to its own answer? Nov 29, 2010 at 13:32
  • Maybe you cannot put raw | in a command content. Then create a function that does what I told in my answer, and set the command to call thefunction().
    – Benoit
    Nov 29, 2010 at 13:36
3

" Clear undo history (:w to clear the undo file if presented)
command! -bar UndoClear exe "set ul=-1 | m-1 | let &ul=" . &ul

  • When you set 'undolevels' to -1 the undo information is not immediately cleared, this happens at the next change, i.e. m-1, which doesn't actually change your text.
  • When 'undofile' is on, :w to clear the undo file, or chain like UndoClear|w.
1

In a script:

function! <SID>ForgetUndo
     let old_ul = &ul
     set ul=-1
     let &ul = old_ul
     unlet old_ul
endfunction
command -nargs=0 Reset call <SID>ForgetUndo()

Then use :Reset to call it.

2
  • Your function definition line needs () at the end. Nov 29, 2010 at 17:13
  • This is odd - running those commands individually works fine, and echoing the values throughout the function shows that they are set and unset appropriately. But running the function doesn't reset my undo history - afterwards, I can still undo multiple times. Maybe the set ul= command only affects a local variable until the script exits, and since we change it back before the script exits, it never affect the environment? Did you test this function and have it work - meaning, is there something odd about my setup? Nov 29, 2010 at 17:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .