7

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

2
  • 7
    Doesn't that kinda defeat the point of version control?
    – Phoshi
    May 7, 2010 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, 2013 at 14:36

6 Answers 6

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.

1
  • This is exactly what I came here looking for!
    – Ryan Fox
    Sep 15, 2010 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))
1
  • 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, 2013 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.

2
  • or some other periodic thing: 'cron', 'sched from zsh', whatever
    – akira
    May 7, 2010 at 15:28
  • what i suggested isn't periodic
    – Kim
    May 7, 2010 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
  • 1
    You shouldn't be using advice when save-buffer already provides the perfectly good variable after-save-hook. Dec 1, 2010 at 2:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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