Reverting All Buffers

I have two machines on which I do most of my writing and development: a 27" iMac and a 5 year old MacBook Pro. I use both of these computers everyday so I need to keep them in sync. I do that with Git repositories that live on a separate Linux server. One of those repositories contains all my org files. That includes blog posts, todo and task lists from my org agenda, and various other files that I maintain with org-mode. Those, along with all the other archived files means that I have a lot of files to keep up to date.

The first thing I do when I begin a session is a git pull to make sure I have the latest files from the other machine. Of course that means I have to be religious about pushing any changes to Git but that's pretty much second nature now. The other thing you need to know is that when I'm finished with a session, I just put the machine in sleep mode. That means my Emacs still has all the open files from the last session when I get back to it. I also have desktop-save-mode on so this happens even if I turn the computer off or reboot it.

Here's the problem. After the Git pull, those buffers and their underlying files are no longer in sync. I could set Emacs to automatically sync them but I don't want to deal with the overhead. Thus I have to run revert-buffer by hand for each of the updated files. That's a pain, of course, and cries out for automation so I wrote a quick bit of Elisp to do it for me. Here's the code

(defun revert-all-buffers ()
  "Revert all non-modified buffers associated with a file.
This is to update existing buffers after a Git pull of their underlying files."
    (mapc (lambda (b)
            (set-buffer b)
            (unless (or (null (buffer-file-name)) (buffer-modified-p))
              (revert-buffer t t)
              (message "Reverted %s\n" (buffer-file-name))))

The code is pretty simple. It goes through the buffer list looking for buffers with an underlying file. If the buffer is not dirty, I call revert-buffer to get the changes from the Git pull into the buffer. If I've made changes to the buffer, then I have to fix things up by hand so I don't want to do the revert.

It seems to me that there's nothing special about my work flow so others may have the same problem and find revert-all-buffers useful.

This entry was posted in Programming and tagged , . Bookmark the permalink.
  • If you perform the pull with Magit, it will conservatively revert the associated buffers for you. That's how I've mostly managed the issue.

    • jcs

      Really? I didn't know that. I do use Magit so this is good news for me. Do you have a pointer to the details?

      • Chris Wellons

        It's probably in the manual somewhere. All I know is that it just works for me with Magit 1.0.0. I did a little test right now to make sure I wasn't imagining things, and yes, it's definitely working. Switch branches and such through Magit and watch the magic.

  • nhgn

    Wouldn't (global-auto-revert-mode t) do?

    • jcs

      Yes but that's what I meant when I said that I didn't want to deal with the overhead. I read somewhere that set global-auto-revert-mode on can slow things down because it has to keep checking the file status. My use case doesn't require constant checking for a changed file; I only need to revert after a Git pull.

      • Foo

        I have the same setting you have and have global-auto-revert-mode on with absolutely no slow down.

        • ded7


          (global-auto-revert-mode t) has been in my config for more than 3 yrs. It's makes an assert about the state of my files and emacs buffers that I find simplifies things. I have lost work a couple of times, but I'm happy with that cost in return for the sane work practices it enforces (stash or commit before pulling; never treat your emacs buffers as storage for valuable work, except when you are writing said work).

  • bmm
    • I was totally going to recommend this.

      It changed my world :)