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.