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.