Ruby/Git is a Ruby library that can be used to create, read and manipulate Git repositories by wrapping system calls to the git binary.
Ruby/Git is a Ruby library that can be used to create, read and manipulate Git repositories by wrapping system calls to the git binary.
This branch is unreleased v6.0.0 development. The current release series is v5.x, released from the
5.xbranch. v6.0.0 removes the APIs deprecated during v5.x. See Upgrading to v6.x for what changes.
The git gem provides a Ruby interface to the git
command line.
Get a repository object by:
Git::Repository documents the methods you can call on a repository object.
This gem is a wrapper around the git command line, so a git executable (version
2.43.0 or greater) must be installed and on your PATH. See the Git version support
policy for details.
Install the gem and add to the application's Gemfile by executing:
bundle add git
If you are not using bundler to manage dependencies, install the gem by executing:
gem install git
All functionality for this gem starts with the top-level
Git module. Use this module to run non-repo
scoped git commands such as config.
The Git module also has factory methods such as open, clone, and init which
return a Git::Repository object. Use
the Git::Repository object to run repo-specific git commands such as add,
commit, push, and log.
Clone, read status, and log:
require 'git'
repo = Git.clone('https://github.com/ruby-git/ruby-git.git', 'ruby-git')
repo.status_info.changed.each_key { |path| puts "changed: #{path}" }
repo.log(5).execute.each { |c| puts c.message }
Open an existing repo and commit:
require 'git'
repo = Git.open('/path/to/repo')
repo.add(all: true)
repo.commit('chore: update files')
repo.push
Initialize a new repo and make the first commit:
require 'git'
repo = Git.init('my_project')
repo.add(all: true)
repo.commit('initial commit')
These examples cover configuring the gem and git itself. For the full set of repository operations, see Full API below.
Configure the git gem:
Git.configure do |config|
config.binary_path = '/usr/local/bin/git'
config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
end
# or
Git.config.binary_path = '/usr/local/bin/git'
Git.config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
How SSH configuration is determined:
git_ssh, the gem uses the global config
(Git.configure { |c| c.git_ssh = ... }).git_ssh: nil, the gem disables SSH for that instance and
uses no SSH key or script.git_ssh is a non-empty string, the gem uses it for that instance instead of
the global config.You can also specify a custom SSH script on a per-repository basis:
# Use a specific SSH key for a single repository
git = Git.open('/path/to/repo', git_ssh: 'ssh -i /path/to/private_key')
# Or when cloning
git = Git.clone('[email protected]:user/repo.git', 'local-dir',
git_ssh: 'ssh -i /path/to/private_key')
# Or when initializing
git = Git.init('new-repo', git_ssh: 'ssh -i /path/to/private_key')
This matters in multi-threaded applications where different repositories need different SSH credentials.
Read and set git configuration values (via git config):
…
The quick start and the configuration sections above cover the most common setup.
The Git::Repository reference
covers everything else: reading history, diffs, branches, remotes, worktrees,
staging, and low-level index and tree work. It documents every method and the object
type each one returns (such as Git::Log, Git::Object::Commit, Git::Diff,
Git::BranchInfo, and Git::WorktreeInfo), so you can follow the links from a method
to the full API of its result.
The git gem raises only ArgumentError or errors that subclass Git::Error.
Rescue Git::Error to catch any runtime error raised by this gem, unless you need
more specific error handling.
begin
# some git operation
rescue Git::Error => e
puts "An error occurred: #{e.message}"
end
Operating system errors from the gem's own filesystem operations, such as reading
a .git pointer file or creating a temporary file, are raised as Git::Error.
The original SystemCallError is available through cause:
begin
repo = Git.open('/path/to/repo')
rescue Git::Error => e
puts e.cause.class if e.cause.is_a?(SystemCallError) #=> Errno::EACCES
end
The promise covers errors the gem raises from its own operations. Two things pass
through unchanged. An error raised by a block your code passes to a method such as
chdir or with_temp_working is your error, and the gem does not relabel it. And
with the raise behavior described under Deprecation policy, a
deprecated call raises ActiveSupport::DeprecationException, which is intentionally
not a Git::Error so a broad rescue cannot hide a deprecation your code opted to
treat as fatal.
See Git::Error for more information.
Set a timeout for git command line operations either globally or per method call for
methods that accept a :timeout parameter.
The timeout is the number of seconds a git command may run before the gem sends
it SIGKILL. It must be a real, non-negative Numeric. When a command times out,
the gem kills it and raises Git::TimeoutError, which derives from
Git::SignaledError and Git::Error. The gem may hang if the git command does
not terminate after receiving SIGKILL.
If the timeout value is 0 or nil, no timeout is enforced.
If a method accepts a :timeout parameter and receives a non-nil value, that value
overrides the global timeout. In this context, a value of nil, which is usually
the default, uses the global timeout value, and a value of 0 turns off timeout
enforcement for that method call no matter what the global value is.
To set a global timeout, use the Git.config object:
Git.config.timeout = nil # a value of nil or 0 means no timeout is enforced
Git.config.timeout = 1.5 # can be any real, non-negative Numeric interpreted as number of seconds
The global timeout can be overridden for a specific method if the method accepts a
:timeout parameter:
repo_url = 'https://github.com/ruby-git/ruby-git.git'
Git.clone(repo_url) # Use the global timeout value
Git.clone(repo_url, timeout: nil) # Also uses the global timeout value
Git.clone(repo_url, timeout: 0) # Do not enforce a timeout
Git.clone(repo_url, timeout: 10.5) # Timeout after 10.5 seconds raising Git::TimeoutError
If the command takes too long, the gem raises Git::TimeoutError:
begin
Git.clone(repo_url, timeout: 10)
rescue Git::TimeoutError => e
e.result.tap do |r|
r.class #=> Git::CommandLine::Result
r.status #=> #<Process::Status: pid 62173 SIGKILL (signal 9)>
r.status.timeout? #=> true
r.git_cmd # The git command ran as an array of strings
r.stdout # The command's output to stdout until it was terminated
r.stderr # The command's output to stderr until it was terminated
end
end
This gem uses ActiveSupport's deprecation mechanism to report deprecation warnings.
You can silence deprecation warnings by adding this line to your source code:
Git::Deprecation.behavior = :silence
Or by setting this environment variable before loading the gem:
GIT_DEPRECATION_BEHAVIOR=silence
Accepted environment variable values are the behavior names supported by your installed ActiveSupport version.
If GIT_DEPRECATION_BEHAVIOR is set to an unsupported value, loading the gem
raises ArgumentError with the accepted behavior names.
See the Active Support Deprecation documentation for more details.
Before upgrading the git gem to the next major version, follow the upgrade procedure in UPGRADING.md. It turns the warnings into errors so that you cannot miss one.
For the full list of deprecated methods and their replacements, see UPGRADING.md.
On Git for Windows, git's regex engine matches bytes rather than characters. A
metacharacter such as ., or a POSIX character class such as [[:alpha:]], therefore
never matches a whole multi-byte character. The same call matches on Linux and macOS.
The failure is silent. Nothing raises, and the result is indistinguishable from a pattern that genuinely does not occur:
# File content, commit message, and config value are all 'ÄPFEL sind gut'.
# 'Ä' is two bytes in UTF-8 (C3 84), so '.' has to match both to match the character.
repo.grep('^.PFEL') # => {} on Windows, matches elsewhere
repo.log.grep('^.PFEL').execute.size # => 0 on Windows, 1 elsewhere
repo.config_get_all('test.desc', '^.PFEL') # => [] on Windows, matches elsewhere
This is a property of the regex engine git bundles on that platform, not something the
gem sets. It is unaffected by the locale: the behavior is identical under en_US.UTF-8,
C.UTF-8, C, and with no LC_ALL set at all. Literal (metacharacter-free) patterns
and case-insensitive matching are unaffected on every platform.
Workaround. Perl-compatible regular expressions do match characters on Git for Windows, so the methods that can reach a PCRE engine accept an opt-in selector:
repo.grep('^.PFEL', nil, perl_regexp: true) # matches on every platform
repo.log.perl_regexp.grep('^.PFEL').execute # matches on every platform
repo.full_log_commits(grep: '^.PFEL', perl_regexp: true)
Two caveats:
No open issues yet, or sync has not completed.