module Git::Git
The Git module provides the basic functions to open a git reference to work with. You can open a working directory, open a bare repository, initialize a new repo or clone an existing remote repository.
Constants
- LS_REMOTE_ALLOWED_OPTS
-
Option keys accepted by {.ls_remote}
Parser-incompatible options such as ‘:get_url` and `:symref` are intentionally excluded because {Git::Parsers::LsRemote.parse_output} cannot handle the non-standard output formats those flags produce.
@return [Array<Symbol>]
@api private
- MINIMUM_GIT_VERSION
-
Minimum git version required by this gem
Commandsand features may require newer versions, but this is the absolute minimum supported version for the gem as a whole.@return [Git::Version]
@api public
- REPOSITORY_SPECIFIC_SCOPES
-
Scopes that require an active repository and cannot be used at the
Gitmodule level@api private
Public Class Methods
Source
# File lib/git.rb, line 372 def self.cached_git_version(binary_path, &block) @git_version_cache_mutex.synchronize do @git_version_cache[binary_path] ||= block.call end end
Return the cached git version for the given binary path
If it isn’t already known, compute it using the given block.
@param binary_path [String] the path to the git binary
@return [Git::Version] the git version
@yield [] compute the git version if it is not cached
@yieldreturn [Git::Version] the computed git version
@api private
Source
# File lib/git.rb, line 383 def self.clear_git_version_cache @git_version_cache_mutex.synchronize do @git_version_cache.clear end end
Clear the cached git version for all binary paths
@return [void]
@api private
Source
# File lib/git.rb, line 166 def self.config Git::Config.instance end
Returns the process-wide {Git::Config} singleton
@example Read the configured binary path
Git.config.binary_path #=> "git"
@return [Git::Config] the singleton config object
Source
# File lib/git.rb, line 154 def self.configure yield Git::Config.instance nil end
Configures the gem by yielding {Git::Config.instance} to the block
@example Set the global git binary path
Git.configure { |c| c.binary_path = '/usr/local/bin/git' }
@return [void]
@yield [config] yields the singleton config object
@yieldparam config [Git::Config] the singleton config object
@yieldreturn [void]
Source
# File lib/git.rb, line 208 def self.default_branch(repository, options = {}) context = Git::ExecutionContext::Global.new(logger: options[:log]) output = Git::Commands::LsRemote.new(context).call(repository, 'HEAD', symref: true).stdout Git::Parsers::LsRemote.parse_default_branch(output) end
Returns the name of the default branch of the given repository
@example with a URI string
Git.default_branch('https://github.com/ruby-git/ruby-git') # => 'master' Git.default_branch('https://github.com/rspec/rspec-core') # => 'main'
@example with a URI object
repository_uri = URI('https://github.com/ruby-git/ruby-git') Git.default_branch(repository_uri) # => 'master'
@example with a local repository
Git.default_branch('.') # => 'master'
@example with a local repository Pathname
repository_path = Pathname('.') Git.default_branch(repository_path) # => 'master'
@example with the logging option
logger = Logger.new(STDOUT, level: Logger::INFO) Git.default_branch('.', log: logger) # => 'master' # Logs the executed git command to STDOUT, for example: # I, [2022-04-13T16:01:33.221596 #18415] INFO -- : git '-c' 'core.quotePath=true' # '-c' 'color.ui=false' ls-remote '--symref' '--' '.' 'HEAD' 2>&1
@param repository [URI, Pathname, String] The (possibly remote) repository to get the default branch name for
See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a) for more information.
@param options [Hash] The options for this command (see list of valid
options below)
@option options [Logger] :log A logger to use for Git operations. Git
commands are logged at the `:info` level. Additional logging is done at the `:debug` level.
@return [String] the name of the default branch
Source
# File lib/git.rb, line 244 def self.export(repository_url, directory = nil, options = {}) repo = clone(repository_url, directory, { depth: 1 }.merge(options)) git_dir = File.join(repo.dir.to_s, '.git') Git::SystemCallGuard.call( "Failed to remove '#{git_dir}'; the exported files are in place, but part of the " \ 'repository remains and has to be removed by hand' ) { FileUtils.rm_r(git_dir) } end
Clone a repository into ‘directory` then remove its `.git` directory
Exports the current HEAD (or the specific branch given in options[:branch]) into the given ‘directory`. It then removes all traces of git from the directory.
Removing ‘.git` is not atomic. If it fails, the exported files are complete and usable, but the directory keeps whatever part of `.git` could not be deleted. Nothing is cleaned up, because the exported files are the deliverable and the leftover has to be removed by hand once the cause of the failure is fixed.
Takes the same options as {Git.clone} except that ‘:depth` defaults to 1.
@param repository_url [String, URI, Pathname] the repository to export from
@param directory [String, Pathname, nil] the directory to export into; defaults to the
repository basename
@param options [Hash] options forwarded to {Git.clone} (‘:depth` defaults to 1)
@option options [String] :branch the branch or tag to export instead of HEAD.
Give the short name (`main`, `v1.0.0`); a full ref path such as `refs/tags/v1.0.0` or a commit SHA is not accepted. Use `:revision` to export a SHA.
@return [void]
@raise [Git::Error] if the ‘.git` directory cannot be removed. The exported
files are left in place, and the directory keeps whatever part of `.git` could not be deleted.
Source
# File lib/git.rb, line 408 def self.git_version(binary_path = nil) path = binary_path || Git::Config.instance.binary_path cached_git_version(path) { run_git_version(path) } end
Return the version of a git binary as a {Git::Version}
@example Default binary
Git.git_version #=> #<Git::Version 2.42.0>
@example Explicit binary path
Git.git_version('/opt/homebrew/bin/git') #=> #<Git::Version 2.42.0>
@param binary_path [String, nil] path to the git binary; defaults to
`Git::Config.instance.binary_path`
@return [Git::Version] the parsed git version
@raise [Git::UnexpectedResultError] if the version output cannot be parsed
@raise [Git::FailedError] if the git binary exits with a non-zero status
@raise [Git::Error] if the binary is not found or fails to launch
Source
# File lib/git.rb, line 342 def self.ls_remote(repository = '.', options = {}) raise ArgumentError, 'repository must not be nil' if repository.nil? options = options.dup log = options.delete(:log) unknown = options.keys - LS_REMOTE_ALLOWED_OPTS raise ArgumentError, "Unknown options: #{unknown.join(', ')}" unless unknown.empty? context = Git::ExecutionContext::Global.new(logger: log) output_lines = Git::Commands::LsRemote.new(context).call(repository, **options).stdout.split("\n") Git::Parsers::LsRemote.parse_output(output_lines) end
Displays references available in a remote repository along with the associated commit IDs
@example From a remote repository given its URL
references = Git.ls_remote('https://github.com/user/repo.git')
@example From the default remote of the current repository
references = Git.ls_remote
@example From a specific remote of the current repository
references = Git.ls_remote('origin')
@param repository [String] the target repository location or the name of a remote
Defaults to `'.'` (the current directory). Passing `nil` raises `ArgumentError`; pass `'.'` or omit the argument.
@param options [Hash] the options to pass to the git command
@option options [Boolean, nil] :branches (nil) limit output to refs under ‘refs/heads/`
Alias: `:b`
@option options [Boolean, nil] :heads (nil) limit output to refs under ‘refs/heads/`
Deprecated: use `:branches` instead. Kept for backward compatibility with older git versions where `--heads` is the only supported flag. Alias: `:h`
@option options [Boolean, nil] :tags (nil) limit output to refs under ‘refs/tags/`
Alias: `:t`
@option options [Boolean, nil] :refs (nil) exclude peeled tags and pseudorefs
like `HEAD` from the output
@option options [String] :upload_pack (nil) full path to ‘git-upload-pack` on the
remote host Useful when accessing repositories via SSH where the daemon does not use the PATH configured by the user.
@option options [Boolean, nil] :quiet (nil) do not print the remote URL to stderr
Alias: `:q`
@option options [Boolean, nil] :exit_code (nil) exit with status ‘2` when no
matching refs are found in the remote repository Without this option, the command exits `0` whenever it successfully communicates with the remote, even if no refs match.
@option options [String] :sort (nil) sort output by the given key
Prefix `-` for descending order. Supports `"version:refname"` or `"v:refname"`. See `git for-each-ref` for sort key documentation.
@option options [String, Array<String>] :server_option (nil) transmit a string to
the server when communicating using protocol version 2 The string must not contain NUL or LF characters. Repeatable by passing an Array. Alias: `:o`
@option options [Numeric] :timeout (nil) execution timeout in seconds
@option options [Logger] :log (nil) a logger to use for Git operations
Git commands are logged at the `:info` level. Additional logging is done at the `:debug` level.
@return [Hash{String => Hash}] the available references of the target repo
@raise [ArgumentError] if ‘repository` is `nil` or `options` contains an unknown key
Private Class Methods
Source
# File lib/git.rb, line 466 def self.assert_valid_scope!(**options_to_check) invalid = REPOSITORY_SPECIFIC_SCOPES.select { |s| options_to_check[s] } return if invalid.empty? raise ArgumentError, "#{invalid.join(', ')} scope requires a repository" end
Raises ArgumentError when a repository-specific scope is requested.
The :local, :worktree, and :blob scopes require an active git repository and are therefore not valid at the Git module level.
@param options_to_check [Hash{Symbol => Object}] the scope options to check
If any of the options listed in +REPOSITORY_SPECIFIC_SCOPES+ are present and truthy, an +ArgumentError+ will be raised.
@option options_to_check [Object] :local truthy value requests local scope
@option options_to_check [Object] :worktree truthy value requests worktree scope
@option options_to_check [Object] :blob truthy value requests blob scope
@raise [ArgumentError] if a repository-specific scope is requested
@api private
Source
# File lib/git.rb, line 434 def self.execution_context Git::ExecutionContext::Global.new end
@api private
Source
# File lib/git.rb, line 427 def self.run_git_version(path) output = Git::Commands::Version.new(Git::ExecutionContext::Global.new(binary_path: path)).call.stdout Git::Version.parse(output) end
Return the version of the git binary
@param path [String] the path to the git binary
@return [Git::Version] the parsed git version
@raise [Git::UnexpectedResultError] if the version output cannot be parsed
@raise [Git::FailedError] if the git binary exits with a non-zero status
@raise [Git::Error] if the binary is not found or fails to launch
@api private