tags:

views:

2175

answers:

9

I'd like to use git to record all the changes to a file.

Is there a way I can turn git 'commit' on to automatically happen every time a file is updated - so there is a new commit for every change to a file?

Ideally I'd like my users to not even know that git is running behind the scenes. A user could then potentially "undo" changes to a file - and this could be achieved by pulling a previous version out of git.

+1  A: 

I'm pretty sure you'd need to hook that into whatever editor your users are using. You could write something to poll for changes, but depending on usage patterns, the polling frequency might need to be incredibly high to make sure it was picking up individual changes instead of multiple changes.

Hank Gay
Also, polling for changes will create race conditions.
Bombe
+16  A: 

On Linux you could use inotifywait to automatically execute a command every time a file's content is changed.

Edit: the following command commits file.txt as soon as it is saved:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh
JesperE
+2  A: 

Can you imagine that when commiting every change to a file upon save might create enormous number of revisions? For example if a user is writing a text in OpenOffice Writer and has 1m autosave delay it will create a revision every minute: 60 revisions per hour.

And if user writes a text file and saves it every near keystroke?

So maybe it is just better to educate users to execute some script after job done that will compare and update repo?

Marcin Gil
Ideally, an auto-commit command/tool would be able to be have lower-priority for certain filetypes - e.g. if filetype is OpenOffice, only commit every ten saves/minutes/etc.
Peter Boughton
640k is enough for anybody
Dustin Getz
A: 

If you know the name of the file and you want to monitor only one (or a few files), you can simply call "git commit" every few minutes to achieve this. If the file hasn't changed, git will just complain and you'll have to ignore this error but other than that, there will be no corruption.

In addition to that, you'll want to mark these files as "auto commit" in order to be able to commit manually as well. This way, the user can see the automatic changes and also the bigger "logical" changes which are accompanied by commit comments to explain that has changed since the last manual commit.

For example, use "AUTOCOMMIT" as the commit message. Later, you can write a tool to purge these commits using git log (to find out the revisions to kill) or you can try to create a branch AUTOCOMMIT using a brute force collision resolve strategy to hammer in the "manual commits".

Another option is to use the git low-level commands to build your own specialized repository.

Lastly, you could copy the file to a new name ("$filename.ac") while doing auto commits to distinguish between the manual and automatic versions.

Aaron Digulla
+1  A: 

Maybe this would be a task for Dropbox. (At least if you don't insist on using git)

Hades32
+4  A: 

The earlier inotifywait answer is great, but it isn't quite a complete solution. As written, it is a one shot commit for a one time change in a file. It does not work for the common case where editing a file creates a new inode with the original name. inotifywait -m apparently follows files by inode, not by name. Also, after the file has changed, it is not staged for git commit without git add or git commit -a. Making some adjustments, here is what I am using on Debian to track all changes to my calendar file:

/etc/rc.local:


su -c /home/<username>/bin/gitwait -l <username>

/home/<username>/bin/gitwait:


#!/bin/bash
#
# gitwait - watch file and git commit all changes as they happen
#

while true; do

  inotifywait -qq -e CLOSE_WRITE ~/.calendar/calendar

  cd ~/.calendar; git commit -a -m 'autocommit on change'

done

This could be generalized to wait on a list of files and/or directories, and the corresponding inotifywait processes, and restart each inotifywait as a file is changed.

Lester Buck
Lester could you please expand on how to generalize this to a directory?
Diego
A: 

i had the same problem and on mac launchd provides you with a great solution. it will watch a file or a directory and if there are changes you can run an app or anything else...

A: 

This is a really interesting topic and I intend to do it on a linux machine syncing a git repository with dropbox. Any updates on anyone's progress would be interesting

UncleCJ
+1  A: 

git-wip is a great solution that works well for me. "WIP" stands for "work in progress". Every time you run 'git wip', the changes are commited to a separate branch. It can be run on the command line, but there are extensions for vim and emacs to automatically run git-wip each time a file is written.

rafak