Cron job checking for changes in Git repository

We have just moved our server configs to a Git repository. Therefore there should not be any changes in any of the repository folders. I was thinking about how I could set up a cron job to check for any uncommited changes.

How could a cron job be set up to check for changes in a Git repository?

Greping the output of the git status command might just do it. Grep and cron jobs are not my strong side. Here are some sample outputs from git status:

Standing the folder containing the git repository (e.g. /path/gitrepo/) with changed files:

$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   apache2/sites-enabled/000-default
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   apache2/conf.d/test
no changes added to commit (use "git add" and/or "git commit -a")

Standing in the folder when there is no changes:

$ git status
# On branch master
nothing to commit (working directory clean)

Update:

Synced up with origin is not important. There should be no local changes. Local files that must be in place go into the .gitignore file. In addition to the server configs there are also git repos for content (static web sites, web apps, wordpress, etc). None of the repositories should have local changes.

We might use Puppet in the long run since its being used for development of one of the web apps.


You should use git ls-files

The -m flag will get a list of all modified files since last commit. If no files are modified, no data is output. This makes it extremely easy to set up a cronjob using this command, since the cronjob will by default only send a mail if the command outputs something.

Deleted files are pr. definition modified, so they will also be shown in the modified view. If you do git ls-files -m -d, deleted files will be listed twice.

Note however that git ls-files -m will only show files modified, and will therefore ignore untracked files. In order to also show untracked files, you'll need to pass the the -o flag for "other files", aswell as passing the option --exclude-standard to exclude files listed in .gitignore and .git/info/exclude.

Specifying git dir and working tree

When running the command from a cronjob, you'll need to specify the path to the .git dir, and working tree using --git-dir and --work-tree respectively. See git man pages for reference.

Cronjob setup

The complete command you'll need to run in your cronjob:

$ git --git-dir "/PATH/TO/DIR/.git" --work-tree "/PATH/TO/DIR" ls-files -m -o --exclude-standard

Your crontab should look something like this:

$ crontab -l
# m h  dom mon dow   command
* * * * * git --git-dir "/PATH/TO/DIR/.git" --work-tree "/PATH/TO/DIR" ls-files -m -o --exclude-standard

This will send an e-mail every minute if there are changes. If you want a different setup, I recommend you check out the examples in the cron page on Wikipedia.

Why git-ls-files?

The reason I recommend git ls-files over git status is that git status is a so-called "porcelain" command, while git ls-files is a "plumbing" command. In short, porcelain commands are designed for outputting to the user, while plumbing commands are designed for scripts. Read more about the differences between git porcelain and git plumbing commands.


There is a lot of complexity you ignore in your question, so I'm going to ignore it in my answer:

if [ `git status | grep -c "working directory clean"` -ne 1 ]; then
    . . . you have changes . . .
else
    . . . you don't have any changes . . . 
fi

Note however that this doesn't tell you if you're sync'd up, or if the changes locally are legitimate, or really much of anything you'd want to know if there are changes.

You would probably be better off using a configuration management tool like Puppet or Chef to handle your config files - the learning curve may be a bit steeper initially, but they vastly simplify server/configuration management.