Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Git::Repository::TutorUser3Contributed Perl DocumeGit::Repository::Tutorial(3)

NAME
       Git::Repository::Tutorial - Control git from Perl using Git::Repository

SYNOPSIS
	   use Git::Repository;

	   # do	cool stuff with	Git, using the following advice

HOW-TO
       A Git::Repository object	represents an actual Git repository, against
       which you can run commands.

   Obtain a Git::Repository object from	an existing repository
       If your script is expected to run against a repository in the current
       directory (like most Git	commands), let Git::Repository handle the
       magic:

	   $r =	Git::Repository->new();

       If the repository has a working copy (work tree):

	   $r =	Git::Repository->new( work_tree	=> $dir	);

       In this case, the git dir is computed as	the output of "git rev-parse
       --git-dir", and the the work tree is normalized using "git rev-parse
       --show-cdup". To	force the use of a different work tree,	set the
       "GIT_WORK_TREE" environment variable in the option hash.

       If the repository is a bare repository, or you prefer to	provide	the
       location	of the .git directory:

	   $r =	Git::Repository->new( git_dir => $gitdir );

       If the work tree	and the	git directory are in unrelated locations, you
       can also	provide	both:

	   $r =	Git::Repository->new( work_tree	=> $dir, git_dir => $gitdir );

       The constructor also accepts an option hash. The	various	options	are
       detailed	in the manual page for Git::Repository::Command.

   Run any git command
       Git commands can	be run against an existing Git::Repository object, or
       against the class itself	(in which case,	git will try to	deduce its
       context from the	current	directory and the environment).

       The pattern for running commands	is always the same:

	   $r->run( $command =>	@arguments, \%options );

       The $command and	@arguments are identical to those you'd	pass to	the
       "git" command-line tool.	The options hash contains options, as
       described in the	manual page for	Git::Repository::Command.

   Create a new	repository
       Sometime, you'll	need to	create the Git repository from scratch:

	   # git version 1.6.5 and above
	   Git::Repository->run( init => $dir );
	   $r =	Git::Repository->new( work_tree	=> $dir	);

       Any git older than 1.6.5	requires the command to	be run in the work
       tree, so	we use the "cwd" option:

	   # git version 1.5.0.rc1 and above
	   Git::Repository->run( init => { cwd => $dir } );
	   $r =	Git::Repository->new( work_tree	=> $dir	);

	   # older git versions
	   Git::Repository->run( 'init-db' => {	cwd => $dir } );
	   $r =	Git::Repository->new( work_tree	=> $dir	);

       Note that the old "create()" method is obsolete (as of Git::Repository
       1.18, from April	16, 2011) and has been removed (as of Git::Repository
       1.301, January 21, 2013).

   Clone a repository
       Cloning works the same way:

	   Git::Repository->run( clone => $url => $dir );
	   $r =	Git::Repository->new( work_tree	=> $dir	);

   Run a simple	command
       When you	don't really care about	the output of the command, just	call
       it:

	   $r->run( add	=> '.' );
	   $r->run( commit => '-m', 'my	commit message'	);

       In case of an error or warning, Git::Repository will "croak()" or
       "carp()"	appropriately.

   Properly quote options
       It's common to work out the proper string of Git	commands needed	to
       achieve your goal in the	shell, before actually turning them into calls
       to "Git::Repository->run".

       Some options might require quoting, to properly get the arguments to
       Git through the shell:

	   # shell
	   $ git log --since='Fri Jul 26 19:34:15 2013 +0200' --grep='report ticket'

       Such quoting is of course not needed with Git::Repository:

	   $since = 'Fri Jul 26	19:34:15 2013 +0200';
	   $grep  = 'report ticket';
	   my $cmd = $r->command( log => "--since=$since", "--grep=$grep" );

   Be careful with spaces in options
       For the same reasons as above (individual arguments to "run" or
       "command" are turned into individual "argv" elements for	git,
       whitespace included), some command-line usages of git need to be
       slightly	reformatted to make them suitable for "run()".

       For example, these two commands have the	same effect when run from the
       shell:

	       shell> git checkout -b sometopic
	       shell> git checkout -bsometopic

       In the first case, git receives three arguments in "argv": "checkout",
       "-b" and	"sometopic". In	the second case, it receives two arguments:
       "checkout" and "-bsometopic", and then git recognizes the beginning of
       the -b option and splits	"sometopic" out	of the second argument.

       So, in a	call such as:

	   $command = $repo->run( checkout => "-b$branch_name",	{ quiet	=> 0 } );

       If $branch_name contains	an initial space character, the	call will be
       equivalent the following	shell command:

	       shell> git checkout -b\ sometopic

       and git will receive two	arguments: "checkout" and "-b sometopic", from
       which it	will split out " sometopic" (note the initial space).

       The space after -b must be removed, as otherwise	the code attempts to
       create a	branch called "	sometopic", which git rejects.

   Silence warnings for	some Git commands
       Some Git	porcelain commands provide additional information on "STDERR".
       One typical example is "git checkout":

	   $ git checkout mybranch
	   Switched to branch 'mybranch'

       The "run()" method of Git::Repository treats all	output on "STDERR" as
       a warning. Therefore, the following code:

	   $r->run( checkout =>	'mybranch' );

       will output a warning like this one:

	   Switched to branch 'mybranch' at myscript.pl	line 10.

       In such a case, you can use the "quiet" option to silence the warning
       for a single command:

	   $r->run( checkout =>	'mybranch', { quiet => 1 } );

       To silence all warnings,	you can	pass the "quiet" option	during the
       creation	of the original	repository object:

	   my $r = Git::Repository->new( { quiet => 1 }	);

       This is not recommended,	as it might hide important information from
       you.

   Process normal and error output
       The "run()" command doesn't capture "STDERR": it	only warns (or dies)
       if something was	printed	on it. To be able to actually capture error
       output, "command()" must	be used.

	   my $cmd = $r->command( @cmd );
	   my @errput =	$cmd->stderr->getlines();
	   $cmd->close;

       "run()" also captures all output	at once, which can lead	to unnecessary
       memory consumption when capturing the output of some really verbose
       commands.

	   my $cmd = $r->command( log => '--pretty=oneline', '--all' );
	   my $log = $cmd->stdout;
	   while (<$log>) {
	       ...;
	   }
	   $cmd->close;

       Of course, as soon as one starts	reading	and writing to an external
       process'	communication handles, a risk of blocking exists.  Caveat
       emptor.

   Provide input on standard input
       Use the "input" option:

	   my $commit =	$r->run( 'commit-tree',	$tree, '-p', $parent,
	       { input => $message } );

   Change the environment of a command
       Use the "env" option:

	   $r->run(
	       'commit', '-m', 'log message',
	       {   env => {
		       GIT_COMMITTER_NAME  => 'Git::Repository',
		       GIT_COMMITTER_EMAIL => 'book@cpan.org',
		   },
	       },
	   );

       Note that Git::Repository::Command does small changes to	the
       environment a command before running it.	Specifically, it:

       o   deletes "GIT_DIR" and "GIT_WORK_TREE", and sets them	to the
	   corresponding values	from the current Git::Repository object

       o   deletes "TERM"

       o   replaces "PATH" with	the value of the "env->{PATH}" option

       The easiest way to preserve en environment variable is to pass it with
       the "env" option, for example:

	   $r->run( qw(	config --get-colorbool githooks.color true ),
	       { env =>	{ TERM => $ENV{TERM} } } );

       See Git::Repository::Command and	System::Command	for other available
       options.

   Ignore the system and global	configuration files
       Git has three levels of configuration files that	can change the output
       of porcelain commands: system ($(prefix)/etc/gitconfig),	global
       ($HOME/.gitconfig and $XDG_CONFIG_HOME/git/config) and local
       (.git/config inside the repository).

       To ensure the system and	global configuration files will	be ignored and
       won't interfere with the	expected output	of your	Git commands, you can
       add the following keys to the "env" option:

	   GIT_CONFIG_NOSYSTEM => 1,
	   XDG_CONFIG_HOME     => undef,
	   HOME		       => undef,

   Ensure the output from Git commands is not localized
       Since version 1.7.9, Git	translates its most common interface messages
       into the	user's language	if translations	are available and the locale
       is appropriately	set.

       This means that naively parsing the output "porcelain" commands might
       fail if the program is unexpectedly run under an	unexpected locale.

       The easiest way to ensure your Git commands will	be run in a "locale-
       safe" environment, is to	set the	"LC_ALL" environment variable to "C".

       The brutal way:

	   $ENV{LC_ALL}	= 'C';

       The temporary way:

	   local $ENV{LC_ALL} =	'C';

       The subtle way (restricted to the commands run on a given
       Git::Repository instance):

	   my $r = Git::Repository->new( { env => { LC_ALL => 'C' } } );

       The stealthiest way (restricted to a single command):

	   $r->run( ..., { env => { LC_ALL => 'C' } } );

   Ensure the Git commands are run from	the current working directory
       By default, Git::Repository::Command will "chdir()" to the root of the
       work tree before	launching the requested	Git command.

       This means that no matter where your program "chdir()" to, commands on
       the Git::Repository instance will by default be run from	the root of
       the work	tree. So, commands such	as "add" need to use the "full"	path
       (relative to "GIT_WORK_TREE") of	the files to be	added.

       The "cwd" option	can be used to define where Git::Repository::Command
       will "chdir()" to. To instruct Git::Repository::Command to not
       "chdir()" (and therefore	run the	Git command from the current working
       directory), set the option to "undef":

	   # run from cwd for this command only
	   $r->run( ..., { cwd => undef	} );

	   # always run	git from cwd
	   my $r = Git::Repository->new( { cwd => undef	} );

   Finely control when "run()" dies
       By default, "Git::Repository->run( ... )" dies if the Git command
       exited with a status code of 128	(fatal error) or 129 (usage message).

       Some commands will throw	an error and exit with a status	different from
       the previous two:

	   $r->run( checkout =>	'does-not-exist' );    # exit status: 1

       The above "run()" call does not die, and	output the following warning:

	   error: pathspec 'does-not-exist' did	not match any file(s) known to git.

       The exit	status (as given by "$?	>> 8") is 1.

       To force	"run()"	to die when the	Git command exits with status 1, use
       the "fatal" option (added in version 1.304, May 25, 2013):

	   $r->run( checkout =>	'does-not-exist', { fatal => 1 } );

       By default, 128 and 129 remain in the list of fatal codes.

       Here are	a few examples:

	   # set the fatal codes for all call to run() on this object
	   $r =	Git::Repository->new( {	fatal => [ 1 ..	255 ] }	);

       As usual, setting the option to the Git::Repository object will set it
       for all commands	run for	it:

	   # "!0" is a shortcut	for 1 .. 255
	   $r =	Git::Repository->new( {	fatal => [ "!0"	] } );

       Using negative codes will make these values non-fatal:

	   # the above call to new() makes all exit codes fatal
	   # but 3 and 7 won't be fatal	for this specific run
	   $r->run( ..., { fatal => [ -3, -7 ] } );

       When the	list contains a	single item, there is no need to use an	array
       reference:

	   # same as [ "!0" ]
	   $r =	Git::Repository->new( {	fatal => "!0" }	);

	   # remove 17 from the	list of	fatal exit codes for this run only
	   $r->run( ..., { fatal => -17	} );

       See Git::Repository::Command for	other available	options.

   Process the output of git log
       When creating a tool that needs to process the output of	git log, you
       should always define precisely the expected format using	the --pretty
       option, and choose a format that	is easy	to parse.

       Assuming	git log	will output the	default	format will eventually lead to
       problems, for example when the user's git configuration defines
       "format.pretty" to be something else than the default of	"medium".

       See also	Git::Repository::Plugin::Log for adding	to your
       Git::Repository objects a "log()" method	that will parse	the log	output
       for you.

       Understanding the various options for git log can make it very simple
       to obtain a lot of information.

       For example:

	   # all tags reachable	from $committish
	   my @tags = map {
	       s/^ \((.*)\)/$1/;
	       ( map +(	split /: / )[1], grep /^tag: /,	split /, / )
	     }
	     $_->run( qw( log --simplify-by-decoration --pretty=%d ), $committish );

   Process the output of git shortlog
       git shortlog behaves differently	when it	detects	it's not attached to a
       terminal. In that case, it just tries to	read some git log output from
       its standard input.

       So this oneliner	will hang, because git shortlog	is waiting for some
       data from the program connected to its standard input (the oneliner):

	   perl	-MGit::Repository -le 'print scalar Git::Repository->run( shortlog => -5 )'

       Whereas this one	will "work" (as	in "immediately	return with no
       output"):

	   perl	-MGit::Repository -le 'print scalar Git::Repository->run( shortlog => -5, { input => ""	} )'

       So, you need to give git	shortlog some input (from git log):

	   perl	-MGit::Repository -le 'print scalar Git::Repository->run( shortlog => {	input => scalar	Git::Repository->run( log => -5	) } )'

       If the log output is large, you'll probably be better off with
       something like the following:

	   use Git::Repository;

	   # start both	git commands
	   my $log = Git::Repository->command('log')->stdout;
	   my $cmd = Git::Repository->command( shortlog	=> -ens	);

	   # feed one with the output of the other
	   my $in = $cmd->stdin;
	   print {$in} $_ while	<$log>;
	   close $in;

	   # and do something with the output
	   print $cmd->stdout->getlines;

   Wrap	git in a sudo call
       If for a	given repository you want to wrap all calls to git in a	"sudo"
       call, you can use the "git" option with an array	ref:

	   my $r = Git::Repository->new( { git => [qw( sudo -u nobody git )] } );

       In this case, every call	to git from $r will actually call "sudo	-u
       nobody git".

   Use submodules
       Because Git::Repository automatically sets the "GIT_DIR"	and
       "GIT_WORK_TREE" environment variables, some "submodule" sub-commands
       may fail. For example:

	   $r->run( submodule => add =>	$repository => 'sub' );

       will give the following error:

	   error: pathspec 'sub' did not match any file(s) known to git.

       To avoid	this error, you	should enforce the removal of the
       "GIT_WORK_TREE" variable	from the environment in	which the command is
       run:

	   $r->run(
	       submodule => add	=> $repository => 'sub',
	       { env =>	{ GIT_WORK_TREE	=> undef } }
	   );

       Note that System::Command version 1.04 is required to be	able to	remove
       variables from the environment.

   Sort	git versions
       Since version 1.318, Git::Repository lets Git::Version::Compare handle
       all version comparisons.

       Sorting version numbers is therefore as simple as:

	   use Git::Version::Compare qw( cmp_git );

	   @sort_verson	= sort cmp_git @versions;

   Add specialized methods to your Git::Repository objects
       Have a look at Git::Repository::Plugin and
       Git::Repository::Plugin::Log, to	learn how to add your own methods to
       Git::Repository.

   Run code on the output of a git command through callback
       Sometimes you need to process the output	of a command by	running	a
       callback	on each	line of	the output.

	   # code inspiration:
	   # https://github.com/dolmen/github-keygen/blob/24c501072ba7d890810de3008434c1fe1f757286/release.pl#L178

	   my %tree;
	   $r->run( 'ls-tree' => $commit, sub {
	       my ($mode, $type, $object, $file) = split;
	       $tree{$file} = [	$mode, $type, $object ];
	   } );

       Note that the value returned by the callback will be returned as	part
       of the "run()" output, instead of the original line.

   Initialize a	test repository	with a bundle
       Instead of creating a test repository using a series of file editions
       and commits, one	can simply import data into the	test repository	using
       a bundle. Bundles are created with the "git bundle create" command (see
       the Git documentation for details).

       First create a temporary	repository with	the help of Test::Git:

	   use Test::Git;
	   my $r = test_repository();

       then import the bundle data in your repository, and collect the
       references:

	   my @refs = $r->run( bundle => 'unbundle', $bundle_file );

       and finally update the references:

	   for my $line	(@refs)	{
	       my ( $sha1, $ref	) = split / /, $line;
	       $r->run(	'update-ref', $ref => $sha1 );
	   }

       Since Git version 1.6.5,	it's also possible to clone directly from a
       bundle (this creates an "origin"	remote pointing	to the bundle file):

	   my $r = test_repository( clone => [ $bundle_file ] );

       A bundle	from a recipient repository's point of view is just like a
       regular remote repository. See the documentation	of git bundle for
       details of what's possible (e.g.	incremental bundles).

AUTHOR
       Philippe	Bruhat (BooK) <book@cpan.org>

COPYRIGHT
       Copyright 2010-2016 Philippe Bruhat (BooK), all rights reserved.

LICENSE
       This program is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

perl v5.32.1			  2019-08-31	  Git::Repository::Tutorial(3)

NAME | SYNOPSIS | HOW-TO | AUTHOR | COPYRIGHT | LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Git::Repository::Tutorial&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help