Making git auto-commit

Git

Git Problem Overview


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.

Git Solutions


Solution 1 - Git

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

Solution 2 - Git

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

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.

Solution 3 - Git

The previous answers recommending inotifywait for this job tipped me off in the right direction when I had this problem myself, so I wrote a little script. First this could only watch whole folders recursively (the opposite of Lester Buck's example), but then I also wanted to watch a file somewhere else, so I expanded it.

The result is a script currently called gitwatch, as that is what it does: it watches a file or folder for changes (using inotifywait), and commits them to a git repository.

You can find the script, more info and instructions over on github: https://github.com/nevik/gitwatch

Solution 4 - Git

[git-wip][1] 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.

[1]: http://github.com/bartman/git-wip "git-wip"

Solution 5 - Git

I wanted to do this in windows, and found the best way was to use Directory Monitor to check for changes then when it detected a change have it run:

Program: cmd.exe

Params: /C C:\pathToBatchFile.bat

That batch file contained:

c:
cd c:\gitRepoDirectory\
(if exist "%PROGRAMFILES(X86)%" (
"%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git commit -am AutoCommitMessage"
) else (
"%PROGRAMFILES%\git\bin\sh.exe" --login -i -c "git commit -am AutoCommitMessage"
))

I also tried having another command in there to add files ("%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"), but I don't think I got that working properly.

I also made a post-commit hook containing:

#!/bin/sh
git.exe pull -v --progress  "origin"
git.exe push    --progress  "origin" master:master
curl.exe -s https://webserverdomain.com/updateFromGitHook.x?r=repoName

(If there were any conflicts then it would abort the pull and abort the push, but there wasn't any clear way to tell that had happened - in the end we abandoned the whole idea because of this one flaw.)

That curl command told my server that it needed to do a pull on the code. All that was needed to handle it in php was:

<?
$r = $_GET['r'];
if (!empty($c)) {
    //use system instead of exec if you want the output to go back to the git client
    exec("cd /path/to/repo/parent/$r; sudo git reset --hard HEAD; sudo git pull;");
    echo "\n\nServer: Updated\n\n";
} else {
    echo "\n\nServer: UPDATE FAILED\n\n";
}
?>

The only problem with that was it needed to be run by the root user instead of the apache user, so I also had to make a file in /etc/sudoers.d/ containing:

www-data ALL = NOPASSWD: /usr/bin/git

For me, I think that worked pretty solidly. Directory Monitor can be configured to run on startup and start minimized, and it can watch several different folders

Solution 6 - Git

Inotify really sounds like the right tool for the job.

There is a tool called incron which could be exactly what you are looking for. You can specify files or folders (and event types, like "change", "create", "unlink") in something like a crontab, and a command to run when such an event occurs.

In contrast to inotifywait (which would be the analog of the poor man's cron sleep 10;do stuff), this will catch every event, not just the first.

I haven't used it myself, but from the documentation it doesn't look too complex to setup.

Solution 7 - Git

#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

autopushing with current date and time.

Solution 8 - Git

I wrote a program, GitPrime, to provide autosave for your local Git repositories. Now easy to roll back to before you busted it! Bitbucket repository.

This should work on any platform that supports a bash shell including Windows+Cygwin.

Solution 9 - Git

In case anyone tries to do this from Powershell I had success using the following:

& "C:\Program Files (x86)\Git\bin\sh.exe" -c "cd D:\PATH\TO\REPO && git add --all  &&  git commit -m 'Automatic Commit Message Goes Here' && git push origin master"

Solution 10 - Git

Two solutions that I like are etckeeper -- which can be adapted to a custom directory other than /etc:

mkdir /foo
etckeeper -d /foo init`
etckeeper -d /foo commit 'message'

And gitwatch -- specially the instructions of how to use it with supervisord.

Solution 11 - Git

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.

Solution 12 - Git

It sounds like you're looking for something similar to etckeeper, which is designed to automatically check all your changest to /etc/* into git (or whatever VCS you want), but I see no reason it couldn't be used with files other than those in /etc.

If you only want to deal with one single file, maybe that wouldn't be perfect, but if you want to keep track of everything in a given directory, I think it's worth checking into.

Solution 13 - Git

This script doesn't run when a user changes the file, but it could be run as a cron job (by dropping it into an /etc/cron.* directory), which is also a reasonable solution.

This script will iterate through your /srv/www directory (change it to wherever all of your sites are stored), add, commit, and push all files, and log everything to /var/log/gitlog.txt

now=$(date +"%m.%d.%Y_%T")
logfile='/var/log/gitlog.txt'

for dir in /srv/www/*/
do
echo -e '\n' >> $logfile
echo "autocommit $dir $now" >> $logfile
echo "--------------------------" >> $logfile

cd $dir
git add . >> $logfile
git commit -am "autocommit $now" >> $logfile
git push origin master >> $logfile
done

Solution 14 - Git

For Windows

According to this article about autocommit, you shou create .bat file with content:

git add -u
git commit -m "your commit message"
git push origin master 

and execute with Task Scheduler. If you don't know how to do step-by-step, refer that article.

Solution 15 - Git

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.

Solution 16 - Git

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...

Solution 17 - Git

I made this tiny shell script to monitor files status and trigger commands such as git commit on build success.

Feel free to download and try it.

https://github.com/nzvincent/nzvincent-github/blob/master/inotify-tools/inotify.sh

Solution 18 - Git

This does not satisfy the "Ideally" part of the question, but this was the closest question I saw to the answer I wanted, so I figured it could go here. My first stackoverflow post though, so apologies if I'm mistaken.

The following script ensures automatic commits on saved changes, but does prompt the user for commit input. (I realise my scenario is a little different to git-noob's).


# While running, monitors the specified directory, and when a file therein 
# is created or edited and saved, this prompts the user for a commit message.
# The --exclude is to avoid extra prompts for the changes made to 
# version control directories.

# requires inotify-tools

inotifywait --exclude '/\..+' -m  path/to/directory -e modify -e create |
        while read path action file; do
                gnome-terminal -e 'bash -c "cd path/to/directory; 
                                            git add *; 
                                            echo What did you just do??; 
                                            read varname; 
                                            git commit -m \"$varname\""'
        done

Solution 19 - Git

There are several alternatives:

  • There is git-etc for committing changes automatically on predefined interval of time.
  • Also there is a watchman
  • And gitwatch

Solution 20 - Git

  • git file (autocommit.sh)

    • `git add .
       git commit -am "auto commit"
       git push`
      
  • batch file (*.bat)

    • %windir%\system32\CMD.exe /k git-bash.exe c:/yourapp/autocommit.sh
  • windows Task Scheduler

    • create task

for me it works hope it will help some

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiongit-noobView Question on Stackoverflow
Solution 1 - GitJesperEView Answer on Stackoverflow
Solution 2 - GitLester BuckView Answer on Stackoverflow
Solution 3 - GitNevik RehnelView Answer on Stackoverflow
Solution 4 - GitrafakView Answer on Stackoverflow
Solution 5 - GitRedzarfView Answer on Stackoverflow
Solution 6 - GitpixelbreiView Answer on Stackoverflow
Solution 7 - Gitweb-riderView Answer on Stackoverflow
Solution 8 - GitBrendanView Answer on Stackoverflow
Solution 9 - GitmekulsView Answer on Stackoverflow
Solution 10 - GitvmassuchettoView Answer on Stackoverflow
Solution 11 - GitAaron DigullaView Answer on Stackoverflow
Solution 12 - GiticonoclastView Answer on Stackoverflow
Solution 13 - GitrunningonplantsView Answer on Stackoverflow
Solution 14 - GitT.ToduaView Answer on Stackoverflow
Solution 15 - GitHank GayView Answer on Stackoverflow
Solution 16 - GitmartinView Answer on Stackoverflow
Solution 17 - GitVincent PView Answer on Stackoverflow
Solution 18 - GitFintanView Answer on Stackoverflow
Solution 19 - GitsomenxavierView Answer on Stackoverflow
Solution 20 - GitM.AView Answer on Stackoverflow