3

I've recently upgraded to Magit 2.10.3 and Emacs 25.2.1.

My full config is: Magit 2.10.3, Git 2.13.5 (Apple Git-94), Emacs 25.2.1, darwin.

I was previously on Magit 2.3.1 and Emacs 24.4.1.

Now, when I do a magit-status any open buffers within the project are changed to have auto-revert mode turned on.

Previously, the behaviour was only to revert buffers when Magit operations were performed (eg using Magit to checkout a different commit would revert any buffers whose files had changed). auto-revert mode was never turned on (or if it was it was only temporarily, and I didn't notice it).

Is there a way to get the old behaviour?


UPDATE #1:

Based on tarsius's answer, I've done the following:

(with-eval-after-load 'magit-autorevert
  (defalias 'magit-auto-revert-buffers 'revert-all-unmodified-buffers)
  (magit-auto-revert-mode -1))

revert-all-unmodified-buffers is something I had lying around:

(defun _revert-all-buffers (buffer-predicate)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (funcall buffer-predicate buf))
        (revert-buffer t t t) )))
  (message "Refreshed open files."))

(defun revert-all-unmodified-buffers ()
  "Refreshes all open unmodified buffers from their files."
  (interactive)
  (_revert-all-buffers (lambda (b) (not (buffer-modified-p b)))))

This kind of works. I guess I could change things so that I only revert buffers in the project directory.

One thing I noticed: whenever I refresh the Magit Status buffer, files get reverted. I don't really want that.


UPDATE #2

I believe I have restored the old behaviour, by turning off magit-auto-revert-mode and by doing a (defalias 'magit-auto-revert-buffers ...) that reverts buffers within the repo:

(defun _revert-all-buffers (buffer-predicate)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (funcall buffer-predicate buf))
        (condition-case e
            (revert-buffer t t t)
          (error
           (message "%s" e))))))
  (message "Refreshed open files."))

(defun revert-all-unmodified-buffers-in-git-repo ()
  "Refreshes all open modified buffers in current buffer's Git repo
 from their files."
  (interactive)
  (_revert-all-buffers (lambda (b)
                         (and (not (buffer-modified-p b))
                              (magit-auto-revert-repository-buffer-p b)))))

(with-eval-after-load 'magit-autorevert
  (magit-auto-revert-mode 0)
  (defalias 'magit-auto-revert-buffers
    'revert-all-unmodified-buffers-in-git-repo))

Thanks, tarsius, for pointing me in the right direction.

I wonder if something like this could be supported without having to hack things? (My concern is that my hack might break when I next update Magit.)

2
  • 1
    Have you tried customizing magit-auto-revert-mode?
    – npostavs
    Sep 23, 2017 at 16:06
  • @npostavs: I tried turning off magit-auto-revert-mode. The effect was to completely turn off reverting — even when a Magit operation changes files.
    – Simon K
    Sep 23, 2017 at 16:30

2 Answers 2

2

(Answering my own question…)

I decided to address the issue I mentioned about files being reverted when I refresh the Magit Status buffer. (BTW, the doc strings for magit-refresh and magit-refresh-all are interesting. Only the latter mentions reverting buffers. Maybe that was the original intention and things have changed over time.)

This is what I have ended up with. I'd be interested in any comments.

I'm also interested in whether this behaviour could be made part of Magit.

;;;; Don't revert buffers other than after performing a Magit operation that
;;;; changes files.
;;;; See https://emacs.stackexchange.com/questions/35701/magit-sets-auto-revert-mode-annoying

;;;; This is more heavy-handed than I would like. A change to a single file
;;;; (eg by discarding changes to the file) causes all buffers in the repo
;;;; to be reverted.

(defun _revert-all-buffers (buffer-predicate)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (funcall buffer-predicate buf))
        (condition-case e
            (revert-buffer t t t)
          (error
           (message "%s" e))))))
  (message "Refreshed open files."))

(defun revert-all-unmodified-buffers-in-git-repo ()
  "Refreshes all open unmodified buffers in current buffer's Git repo
 from their files."
  (interactive)
  (_revert-all-buffers (lambda (b)
                         (and (not (buffer-modified-p b))
                              (magit-auto-revert-repository-buffer-p b)))))

(defun -nomis/fix-magit-auto-revert/2.10.3 ()

  (with-eval-after-load 'magit-autorevert

    (magit-auto-revert-mode 0)

    (defvar *nomis/magit-revert-buffers?* t)

    (defun nomis/magit-refresh ()
      "A replacement for the \"g\" key binding in `magit-mode-map`. This does
not revert buffers."
      (interactive)
      (let* ((*nomis/magit-revert-buffers?* nil))
        (magit-refresh)))

    (define-key magit-mode-map "g" 'nomis/magit-refresh)

    (advice-add 'magit-auto-revert-buffers
                :around
                (lambda (_)
                  (when *nomis/magit-revert-buffers?*
                    (revert-all-unmodified-buffers-in-git-repo)))
                '((name . -nomis/hack-auto-refresh)))))

(defun -nomis/fix-magit-auto-revert ()
  (cond
   ((equal magit-version "2.10.3")
    (-nomis/fix-magit-auto-revert/2.10.3))
   (t
    (message-box (s-join " "
                         '("Revisit `-nomis/fix-magit-auto-revert`"
                       "for this version of Magit."))))))    

(add-hook 'magit-mode-hook '-nomis/fix-magit-auto-revert)
1

Try this:

(with-eval-after-load 'magit-autorevert
  (defalias 'magit-auto-revert-buffers 'auto-revert-buffers)
  (magit-auto-revert-mode -1))

Edit: This won't work because auto-revert-buffers assumes that auto-revert-mode is on. It was worth a shot, but this outcome isn't really surprising.

So I am afraid the answer is no. Magit cannot automatically revert without using auto-revert-mode anymore. But you haven't explained why it is annoying that auto-revert-mode is being turned on now. Maybe there's something else that can be done to make you happy.

One thing I noticed: whenever I refresh the Magit Status buffer, files get reverted. I don't really want that.

That already happened before. I am pretty sure every thing you do in Magit that now triggers a revert also did so before. So what action outside of Magit did not use to do so but now does? (Or in other words, how did you notice that something had changed?)

9
  • (EDITED for clarity.) The effect was to completely turn off reverting — even when a Magit operation changes files
    – Simon K
    Sep 23, 2017 at 18:32
  • Ah, I just tried again and noticed stuff in the Messages buffer that makes it look like something is trying to revert bufers. Not sure I can get this to format nicely... Discard unstaged changes in project.clj? (y or n) y [2 times] cancel-timer: Wrong type argument: timerp, nil So it looks like something tried to revert buffers.
    – Simon K
    Sep 23, 2017 at 20:25
  • Hmmm, that previous comment of mine doesn't make a lot of sense. But I guess the point is that there's an error with cancel-timer.
    – Simon K
    Sep 23, 2017 at 21:05
  • You are right that refreshing the Magit Status buffer used to cause reverts (I reverted my Emacs config to check). I hadn't noticed it before. I guess I've noticed it now because I've been doing lots of playing around. But note that bringing up the Magit Status buffer in the first place did not and does not cause a revert -- and I like that.
    – Simon K
    Sep 24, 2017 at 10:24
  • As to why auto-revert is annoying, I will try to explain. Without auto-revert, if files change outside of Emacs, for whatever reason, I get to know about it. (If I try to edit a file that has changed on disc, Emacs asks whether I really want to do that.) And at any time, I can use my revert-all-unmodified-buffers command, so if a lot of files have changed I can use that. I appreciate that other people have different workflows, but I know and like mine.
    – Simon K
    Sep 24, 2017 at 10:24

Your Answer

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

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