If you work with git, eventually you will want to script something that git doesn’t do already and can’t be accomplished with an alias. If you use Perl, the Git::Wrapper module makes scripting git easy.
The big advantage of Git::Wrapper is that it wraps the binary version of git, which keeps your perl and git independent. Upgrade perl and not git? Add Git::Wrapper and you’re done. Upgrade git while keeping your existing perl? No problem. If you get your git from an OS distribution package, but roll your own perl, then Git::Wrapper is for you!
Git::Wrapper just makes it really easy to pass git commands and get back useful data. It really shines on “git log” commands, as it parses each commit message into Git::Wrapper::Log objects with accessors for id, author, date, and message. For everything else, it’s not much more than a wrapper around qx(), but it returns arrays of lines and throws exceptions when things go wrong, which just saves a little time and code.
Here is a short example that I whipped up recently to automate the process of adding a github repository remote for someone when they send me a pull request. (It also uses my Getopt::Lucid module, but as the name suggests, it should be clear what that does.)
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use autodie;
use Git::Wrapper;
use Getopt::Lucid qw/:all/;
# USAGE: github-remote [-r REPO] [NAME]
# NAME -- a github user name (or defaults to 'dagolden')
# REPO -- a github repository path (or is parsed out of my private origin repo)
my $opts = Getopt::Lucid->getopt([
Param('repo|r'),
]);
my $who = shift @ARGV;
# Get a wrapper for the current directory
my $git = Git::Wrapper->new(".");
# Locate the origin repository URL
my ($origin) = grep { /origin/ } $git->remote("-v");
die "Couldn't determine origin\n" unless $origin;
$origin =~ s/^origin\s+//;
$origin =~ s/\s+\(.*$//;
# Parse out the repository path
my $repo = $opts->get_repo;
unless ( $repo ) {
# me@git.example.com:my-repo-name.git
($repo) = $origin =~ m/^[^:]+:(.+)$/;
}
# Set up someone else's github repo
if ( $who ) {
$git->remote("add", $who, "git://github.com/${who}/${repo}");
}
# Or set up my own github mirror
else {
$git->remote("add", "github", "git\@github.com:dagolden/${repo}");
}
That’s it. I admit the program is a little crufty because of how I manage my repositories with a private origin that I mirror to a github repository, but there’s almost no cruft around interactions with git. Consider this:
$git->remote("add", $who, "git://github.com/${who}/${repo}");
If the command fails (if there’s already $who as a remote name), an exception will be thrown. That means I don’t have to write any error handling myself, which is perfect for a simple automation program like this one.