7

How can I set up emacs to automatically git commit every time I save an open file or periodically?

  • 6
    Doesn't that kinda defeat the point of version control? – Phoshi May 7 '10 at 15:25
  • 2
    If you are a programmer, probably. But for those of using emacs to write rather then code, I think this is quite useful. – Brian Z Sep 8 '13 at 14:36
3

If you wanted to commit upon every save, you'd do:

(add-hook 'after-save-hook 'my-commit-on-save)
(defun my-commit-on-save ()
   "commit the buffer"
   ...your-code-goes-here...)

Likely you could just use

(defun my-commit-on-save ()
   "commit the buffer"
   (call-interactively 'vc-next-action))

But, you'll want to add some checks to make sure it's a part of the set of files you want to commit, otherwise every buffer you save will be added to a repository.

  • This is exactly what I came here looking for! – Ryan Fox Sep 15 '10 at 20:25
4

I use git-wip for that (see my answer on SO).

3

Here is a bit of lisp that I found. Does not do commit/push on every save, but schedules it for the near future so if you save a bunch of small edits you don't get a bunch of small commits.

https://gist.github.com/defunkt/449668

;; Automatically add, commit, and push when files change.

(defvar autocommit-dir-set '()
  "Set of directories for which there is a pending timer job")

(defun autocommit-schedule-commit (dn)
  "Schedule an autocommit (and push) if one is not already scheduled for the given dir."
  (if (null (member dn autocommit-dir-set))
      (progn
        (run-with-idle-timer
         10 nil
         (lambda (dn)
           (setq autocommit-dir-set (remove dn autocommit-dir-set))
           (message (concat "Committing org files in " dn))
           (shell-command (concat "cd " dn " && git commit -m 'Updated org files.'"))
           (shell-command (concat "cd " dn " && git push & /usr/bin/true")))
         dn)
        (setq autocommit-dir-set (cons dn autocommit-dir-set)))))

(defun autocommit-after-save-hook ()
  "After-save-hook to 'git add' the modified file and schedule a commit and push in the idle loop."
  (let ((fn (buffer-file-name)))
    (message "git adding %s" fn)
    (shell-command (concat "git add " fn))
    (autocommit-schedule-commit (file-name-directory fn))))

(defun autocommit-setup-save-hook ()
  "Set up the autocommit save hook for the current file."
  (interactive)
  (message "Set up autocommit save hook for this buffer.")
  (add-hook 'after-save-hook 'autocommit-after-save-hook nil t))
  • It's better to copy and paste the relevant info from the linked page rather than just linking to it in case the page content changes or moves. – Tog Jul 23 '13 at 18:02
2

You don't need emacs for that at all. You can write a shell script that uses inotify. It could look like this:

while true; do
    inotifywait -e modify FILES...
    git commit ....
done

inotifywait is part of inoftify-tools.

  • or some other periodic thing: 'cron', 'sched from zsh', whatever – akira May 7 '10 at 15:28
  • what i suggested isn't periodic – Kim May 7 '10 at 21:08
2

You can also use my git-monitor utility, if especially if you are a Haskell user.

-1

Try something like this:

(defadvice save-buffer (after commit-buffer-now activate)
  (when buffer-file-name (your commit code goes here)))

This is the emacs way to do it.

  • 1
    You shouldn't be using advice when save-buffer already provides the perfectly good variable after-save-hook. – Ryan Thompson Dec 1 '10 at 2:43

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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