Class: Git::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/git/base.rb

Overview

The main public interface for interacting with Git commands

Instead of creating a Git::Base directly, obtain a Git::Base instance by calling one of the follow Git class methods: open, init, clone, or bare.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Git::Base

Create an object that executes Git commands in the context of a working copy or a bare repository.

Parameters:

  • options (Hash) (defaults to: {}) —

    The options for this command (see list of valid options below)

Options Hash (options):

  • :working_dir (Pathname) —

    the path to the root of the working directory. Should be nil if executing commands on a bare repository.

  • :repository (Pathname) —

    used to specify a non-standard path to the repository directory. The default is "#{working_dir}/.git".

  • :index (Pathname) —

    used to specify a non-standard path to an index file. The default is "#{working_dir}/.git/index"

  • :log (Logger) —

    A logger to use for Git operations. Git commands are logged at the :info level. Additional logging is done at the :debug level.

  • :git_ssh (String, nil) —

    Path to a custom SSH executable or script. Controls how SSH is configured for this Git::Base instance:

    • If this option is not provided, the global Git::Base.config.git_ssh setting is used.
    • If this option is explicitly set to nil, SSH is disabled for this instance.
    • If this option is a non-empty String, that value is used as the SSH command for this instance, overriding the global Git::Base.config.git_ssh setting.


174
175
176
177
178
179
# File 'lib/git/base.rb', line 174

def initialize(options = {})
  options = default_paths(options)
  setup_logger(options[:log])
  @git_ssh = options.key?(:git_ssh) ? options[:git_ssh] : :use_global_config
  initialize_components(options)
end

Instance Attribute Details

#git_ssh ⇒ String, ... (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the per-instance git_ssh configuration value.

This may be:

  • a [String] path when an explicit git_ssh command has been configured
  • the Symbol :use_global_config when this instance is using the global config
  • nil when SSH has been explicitly disabled for this instance

Returns:

  • (String, Symbol, nil) —

    the git_ssh configuration value for this instance



361
362
363
# File 'lib/git/base.rb', line 361

def git_ssh
  @git_ssh
end

#index (readonly)

returns reference to the git index file



255
256
257
# File 'lib/git/base.rb', line 255

def index
  @index
end

Class Method Details

.bare(git_dir, options = {}) ⇒ Git::Base

Open a bare repository

Opens a bare repository located in the git_dir directory. Since there is no working copy, you can not checkout or commit but you can do most read operations.

Examples:

Open a bare repository and retrieve the first commit SHA

repository = Git.bare('ruby-git.git')
puts repository.log[0].sha #=> "64c6fa011d3287bab9158049c85f3e85718854a0"

Parameters:

  • git_dir (Pathname) —

    The path to the bare repository directory containing an initialized Git repository. If a relative path is given, it is converted to an absolute path using File.expand_path.

  • options (Hash) (defaults to: {}) —

    The options for this command (see list of valid options below)

Options Hash (options):

  • :git_ssh (String, nil) —

    An optional custom SSH command

    • If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
    • If nil, disables SSH for this instance.
    • If a non-empty string, uses that value for this instance.
  • :log (Logger) —

    A logger to use for Git operations. Git commands are logged at the :info level. Additional logging is done at the :debug level.

Returns:

  • (Git::Base) —

    an object that can execute git commands in the context of the bare repository.

See Also:



16
17
18
19
# File 'lib/git/base.rb', line 16

def self.bare(git_dir, options = {})
  normalize_paths(options, default_repository: git_dir, bare: true)
  new(options)
end

.binary_version(binary_path)



42
43
44
# File 'lib/git/base.rb', line 42

def self.binary_version(binary_path)
  parse_version_string(execute_git_version(binary_path))
end

.clone(repository_url, directory, options = {}) ⇒ Git::Base

Clone a repository into an empty or newly created directory

Examples:

Clone into the default directory ruby-git

git = Git.clone('https://github.com/ruby-git/ruby-git.git')

Clone and then checkout the development branch

git = Git.clone('https://github.com/ruby-git/ruby-git.git', branch: 'development')

Clone into a different directory my-ruby-git

git = Git.clone('https://github.com/ruby-git/ruby-git.git', 'my-ruby-git')
# or:
git = Git.clone('https://github.com/ruby-git/ruby-git.git', path: 'my-ruby-git')

Create a bare repository in the directory ruby-git.git

git = Git.clone('https://github.com/ruby-git/ruby-git.git', bare: true)

Clone a repository and set a single config option

git = Git.clone(
  'https://github.com/ruby-git/ruby-git.git',
  config: 'submodule.recurse=true'
)

Clone a repository and set multiple config options

git = Git.clone(
  'https://github.com/ruby-git/ruby-git.git',
  config: ['user.name=John Doe', '[email protected]']
)

Clone using a specific SSH key

git = Git.clone(
  '[email protected]:ruby-git/ruby-git.git',
  'local-dir',
  git_ssh: 'ssh -i /path/to/private_key'
)

Parameters:

  • repository_url (URI, Pathname) —

    The (possibly remote) repository url to clone from. See GIT URLS for more information.

  • directory (Pathname, nil) —

    The directory to clone into

    If directory is a relative directory it is relative to the path option if given. If path is not given, directory is relative to the current working directory.

    If nil, directory will be set to the basename of the last component of the path from the repository_url. For example, for the URL: https://github.com/org/repo.git, directory will be set to repo.

    If the last component of the path is .git, the next-to-last component of the path is used. For example, for the URL /Users/me/foo/.git, directory will be set to foo.

  • options (Hash) (defaults to: {}) —

    The options for this command (see list of valid options below)

Options Hash (options):

  • :bare (Boolean) —

    Make a bare Git repository. See what is a bare repository?.

  • :branch (String) —

    The name of a branch or tag to checkout instead of the default branch.

  • :config (Array, String) —

    A list of configuration options to set on the newly created repository.

  • :depth (Integer) —

    Create a shallow clone with a history truncated to the specified number of commits.

  • :filter (String) —

    Request that the server send a partial clone according to the given filter

  • :single_branch (Boolean, nil) —

    Control whether the clone limits fetch refspecs to a single branch.

    • If nil (default), no flag is passed and the Git default is used.
    • If true, --single-branch is passed to limit the refspec to the checkout branch.
    • If false, --no-single-branch is passed to broaden the refspec (useful for shallow clones that should include all branches).
  • :git_ssh (String, nil) —

    An optional custom SSH command

    • If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
    • If nil, disables SSH for this instance.
    • If a non-empty string, uses that value for this instance.
  • :log (Logger) —

    A logger to use for Git operations. Git commands are logged at the :info level. Additional logging is done at the :debug level.

  • :mirror (Boolean) —

    Set up a mirror of the source repository.

  • :origin (String) —

    Use the value instead origin to track the upstream repository.

  • :path (Pathname) —

    The directory to clone into. May be used as an alternative to the directory parameter. If specified, the path option is used instead of the directory parameter.

  • :recursive (Boolean) —

    After the clone is created, initialize all submodules within, using their default settings.

Returns:

  • (Git::Base) —

    an object that can execute git commands in the context of the cloned local working copy or cloned repository.

See Also:



22
23
24
25
26
27
28
# File 'lib/git/base.rb', line 22

def self.clone(repository_url, directory, options = {})
  lib_options = {}
  lib_options[:git_ssh] = options[:git_ssh] if options.key?(:git_ssh)
  new_options = LibImpl.new(lib_options, options[:log]).clone(repository_url, directory, options)
  normalize_paths(new_options, bare: options[:bare] || options[:mirror])
  new(new_options)
end

.config ⇒ Git::Config

Returns (and initialize if needed) a Git::Config instance

Returns:



38
39
40
# File 'lib/git/base.rb', line 38

def self.config
  @config ||= Config.new
end

.init(directory = '.', options = {}) ⇒ Git::Base

Create an empty Git repository or reinitialize an existing Git repository

Examples:

Initialize a repository in the current directory

git = Git.init

Initialize a repository in some other directory

git = Git.init '~/code/ruby-git'

Initialize a bare repository

git = Git.init '~/code/ruby-git.git', bare: true

Initialize a repository in a non-default location (outside of the working copy)

git = Git.init '~/code/ruby-git', repository: '~/code/ruby-git.git'

Parameters:

  • directory (Pathname) (defaults to: '.') —

    If the :bare option is NOT given or is not true, the repository will be created in "#{directory}/.git". Otherwise, the repository is created in "#{directory}".

    All directories along the path to directory are created if they do not exist.

    A relative path is referenced from the current working directory of the process and converted to an absolute path using File.expand_path.

  • options (Hash) (defaults to: {}) —

    The options for this command (see list of valid options below)

Options Hash (options):

  • :bare (Boolean) —

    Instead of creating a repository at "#{directory}/.git", create a bare repository at "#{directory}". See what is a bare repository?.

  • :initial_branch (String) —

    Use the specified name for the initial branch in the newly created repository.

  • :repository (Pathname) —

    the path to put the newly initialized Git repository. The default for non-bare repository is "#{directory}/.git".

    A relative path is referenced from the current working directory of the process and converted to an absolute path using File.expand_path.

  • :git_ssh (String, nil) —

    An optional custom SSH command

    • If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
    • If nil, disables SSH for this instance.
    • If a non-empty string, uses that value for this instance.
  • :log (Logger) —

    A logger to use for Git operations. Git commands are logged at the :info level. Additional logging is done at the :debug level.

Returns:

  • (Git::Base) —

    an object that can execute git commands in the context of the newly initialized repository

See Also:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/git/base.rb', line 63

def self.init(directory = '.', options = {})
  normalize_paths(options, default_working_directory: directory, default_repository: directory,
                           bare: options[:bare])

  init_options = {
    bare: options[:bare],
    initial_branch: options[:initial_branch]
  }

  directory = options[:bare] ? options[:repository] : options[:working_directory]
  FileUtils.mkdir_p(directory)

  # TODO: this dance seems awkward: this creates a Git::Lib so we can call
  #   init so we can create a new Git::Base which in turn (ultimately)
  #   creates another/different Git::Lib.
  #
  # TODO: maybe refactor so this Git::Bare.init does this:
  #   self.new(opts).init(init_opts) and move all/some of this code into
  #   Git::Bare#init. This way the init method can be called on any
  #   repository you have a Git::Base instance for.  This would not
  #   change the existing interface (other than adding to it).
  #
  LibImpl.new(options).init(init_options)

  new(options)
end

.open(working_dir, options = {}) ⇒ Git::Base

Open a an existing Git working directory

Git.open will most likely be the most common way to create a git reference, referring to an existing working directory.

If not provided in the options, the library will assume the repository and index are in the default places (.git/, .git/index).

Examples:

Open the Git working directory in the current directory

git = Git.open

Open a Git working directory in some other directory

git = Git.open('~/Projects/ruby-git')

Use a logger to see what is going on

logger = Logger.new(STDOUT)
git = Git.open('~/Projects/ruby-git', log: logger)

Open a working copy whose repository is in a non-standard directory

git = Git.open('~/Projects/ruby-git', repository: '~/Project/ruby-git.git')

Parameters:

  • working_dir (Pathname) —

    the path to the working directory to use for git commands.

    A relative path is referenced from the current working directory of the process and converted to an absolute path using File.expand_path.

  • options (Hash) (defaults to: {}) —

    The options for this command (see list of valid options below)

Options Hash (options):

  • :repository (Pathname) —

    used to specify a non-standard path to the repository directory. The default is "#{working_dir}/.git".

  • :index (Pathname) —

    used to specify a non-standard path to an index file. The default is "#{working_dir}/.git/index"

  • :git_ssh (String, nil) —

    An optional custom SSH command

    • If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
    • If nil, disables SSH for this instance.
    • If a non-empty string, uses that value for this instance.
  • :log (Logger) —

    A logger to use for Git operations. Git commands are logged at the :info level. Additional logging is done at the :debug level.

Returns:

  • (Git::Base) —

    an object that can execute git commands in the context of the opened working copy

Raises:

  • (ArgumentError)


135
136
137
138
139
140
141
142
143
# File 'lib/git/base.rb', line 135

def self.open(working_dir, options = {})
  raise ArgumentError, "'#{working_dir}' is not a directory" unless Dir.exist?(working_dir)

  working_dir = root_of_worktree(working_dir) unless options[:repository]

  normalize_paths(options, default_working_directory: working_dir)

  new(options)
end

.repository_default_branch(repository, options = {}) ⇒ String

Returns the name of the default branch of the given repository

Examples:

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'

with a URI object

repository_uri = URI('https://github.com/ruby-git/ruby-git')
Git.default_branch(repository_uri) # => 'master'

with a local repository

Git.default_branch('.') # => 'master'

with a local repository Pathname

repository_path = Pathname('.')
Git.default_branch(repository_path) # => 'master'

with the logging option

logger = Logger.new(STDOUT, level: Logger::INFO)
Git.default_branch('.', log: logger) # => 'master'
I, [2022-04-13T16:01:33.221596 #18415]  INFO -- : git '-c' 'core.quotePath=true'
  '-c' 'color.ui=false' ls-remote '--symref' '--' '.' 'HEAD'  2>&1

Parameters:

  • repository (URI, Pathname, String) —

    The (possibly remote) repository to get the default branch name for

    See GIT URLS for more information.

  • options (Hash) (defaults to: {}) —

    The options for this command (see list of valid options below)

Options Hash (options):

  • :log (Logger) —

    A logger to use for Git operations. Git commands are logged at the :info level. Additional logging is done at the :debug level.

Returns:

  • (String) —

    the name of the default branch



31
32
33
# File 'lib/git/base.rb', line 31

def self.repository_default_branch(repository, options = {})
  LibImpl.new(nil, options[:log]).repository_default_branch(repository)
end

.root_of_worktree(working_dir)

Raises:

  • (ArgumentError)


90
91
92
93
94
# File 'lib/git/base.rb', line 90

def self.root_of_worktree(working_dir)
  raise ArgumentError, "'#{working_dir}' does not exist" unless Dir.exist?(working_dir)

  execute_rev_parse_toplevel(working_dir)
end

Instance Method Details

#add(paths = '.', **options)

Update the index from the current worktree to prepare the for the next commit

Examples:

lib.add('path/to/file')
lib.add(['path/to/file1','path/to/file2'])
lib.add(all: true)

Parameters:

  • paths (String, Array<String>) (defaults to: '.') —

    a file or files to be added to the repository (relative to the worktree root)

  • options (Hash)

Options Hash (**options):

  • :all (Boolean) —

    Add, modify, and remove index entries to match the worktree

  • :force (Boolean) —

    Allow adding otherwise ignored files



194
195
196
# File 'lib/git/base.rb', line 194

def add(paths = '.', **options)
  lib.add(paths, options)
end

#add_remote(name, url, opts = {})

adds a new remote to this repository url can be a git url or a Git::Base object if it's a local reference

@git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git') @git.fetch('scotts_git') @git.merge('scotts_git/master')

Options:

:fetch => true
:track => <branch_name>


208
209
210
211
212
# File 'lib/git/base.rb', line 208

def add_remote(name, url, opts = {})
  url = url.repo.to_s if url.is_a?(Git::Base)
  lib.remote_add(name, url, opts)
  Git::Remote.new(self, name)
end

#add_tag(name, *options)

Create a new git tag

Examples:

repo.add_tag('tag_name', object_reference)
repo.add_tag('tag_name', object_reference, {:options => 'here'})
repo.add_tag('tag_name', {:options => 'here'})

Parameters:

  • name (String) —

    The name of the tag to add

  • options (Hash) —

    Opstions to pass to git tag. See git-tag for more details.

Options Hash (*options):

  • :annotate (boolean) —

    Make an unsigned, annotated tag object

  • :a (boolean) —

    An alias for the :annotate option

  • :d (boolean) —

    Delete existing tag with the given names.

  • :f (boolean) —

    Replace an existing tag with the given name (instead of failing)

  • :message (String) —

    Use the given tag message

  • :m (String) —

    An alias for the :message option

  • :s (boolean) —

    Make a GPG-signed tag.



644
645
646
647
# File 'lib/git/base.rb', line 644

def add_tag(name, *options)
  lib.tag(name, *options)
  tag(name)
end

#apply(file)

rubocop:enable Style/ArgumentsForwarding



719
720
721
722
723
# File 'lib/git/base.rb', line 719

def apply(file)
  return unless File.exist?(file)

  lib.apply(file)
end

#apply_mail(file)



725
726
727
# File 'lib/git/base.rb', line 725

def apply_mail(file)
  lib.apply_mail(file) if File.exist?(file)
end

#archive(treeish, file = nil, opts = {})

creates an archive file of the given tree-ish



655
656
657
# File 'lib/git/base.rb', line 655

def archive(treeish, file = nil, opts = {})
  object(treeish).archive(file, opts)
end

#branch(branch_name = current_branch) ⇒ Git::Branch

Returns an object for branch_name.

Returns:



854
855
856
# File 'lib/git/base.rb', line 854

def branch(branch_name = current_branch)
  Git::Branch.new(self, branch_name)
end

#branch?(branch) ⇒ Boolean

returns true if the branch exists

Returns:

  • (Boolean)


332
333
334
335
# File 'lib/git/base.rb', line 332

def branch?(branch)
  branch_names = branches.map(&:name)
  branch_names.include?(branch)
end

#branches ⇒ Git::Branches

Returns a collection of all the branches in the repository. Each branch is represented as a Git::Branch.

Returns:



860
861
862
# File 'lib/git/base.rb', line 860

def branches
  Git::Branches.new(self)
end

#cat_file(objectish) ⇒ String

Returns the contents of a git object

Uses git cat-file -p to pretty-print the contents of the given object.

Parameters:

  • objectish (String) —

    a SHA, branch name, tag, or other revision reference to the git object

Returns:

  • (String) —

    the contents of the object

See Also:



837
838
839
# File 'lib/git/base.rb', line 837

def cat_file(objectish)
  lib.cat_file_contents(objectish)
end

#chdir

changes current working directory for a block to the git working directory

example @git.chdir do

write files

@git.add @git.commit('message') end



223
224
225
226
227
# File 'lib/git/base.rb', line 223

def chdir # :yields: the Git::Path
  Dir.chdir(dir.to_s) do
    yield dir.to_s
  end
end

#checkout

checks out a branch as the new git working directory



485
486
487
# File 'lib/git/base.rb', line 485

def checkout(*, **)
  lib.checkout(*, **)
end

#checkout_file(version, file)

checks out an old version of a file



490
491
492
# File 'lib/git/base.rb', line 490

def checkout_file(version, file)
  lib.checkout_file(version, file)
end

#checkout_index(opts = {})



763
764
765
# File 'lib/git/base.rb', line 763

def checkout_index(opts = {})
  lib.checkout_index(opts)
end

#clean(opts = {})

cleans the working directory

options: :force :d :ff



431
432
433
# File 'lib/git/base.rb', line 431

def clean(opts = {})
  lib.clean(opts)
end

#commit(message, opts = {})

commits all pending changes in the index file to the git repository

options:

:all
:allow_empty
:amend
:author


472
473
474
# File 'lib/git/base.rb', line 472

def commit(message, opts = {})
  lib.commit(message, opts)
end

#commit_all(message, opts = {})

commits all pending changes in the index file to the git repository, but automatically adds all modified files without having to explicitly calling @git.add() on them.



479
480
481
482
# File 'lib/git/base.rb', line 479

def commit_all(message, opts = {})
  opts = { add_all: true }.merge(opts)
  lib.commit(message, opts)
end

#commit_tree(tree = nil, opts = {}) ⇒ Git::Object::Commit

Returns a commit object.

Returns:



876
877
878
# File 'lib/git/base.rb', line 876

def commit_tree(tree = nil, opts = {})
  Git::Object::Commit.new(self, lib.commit_tree(tree, opts))
end

#config(name = nil, value = nil, options = {})

g.config('user.name', 'Scott Chacon') # sets value g.config('user.email', '[email protected]') # sets value g.config('user.email', '[email protected]', file: 'path/to/custom/config) # sets value in file g.config('user.name') # returns 'Scott Chacon' g.config # returns whole config hash



234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/git/base.rb', line 234

def config(name = nil, value = nil, options = {})
  if name && value
    # set value
    lib.config_set(name, value, options)
  elsif name
    # return value
    lib.config_get(name)
  else
    # return hash
    lib.config_list
  end
end

#current_branch ⇒ String

The name of the branch HEAD refers to or 'HEAD' if detached

Returns one of the following:

* The branch name that HEAD refers to (even if it is an unborn branch)
* 'HEAD' if in a detached HEAD state

Returns:

  • (String) —

    the name of the branch HEAD refers to or 'HEAD' if detached



849
850
851
# File 'lib/git/base.rb', line 849

def current_branch
  lib.branch_current
end

#delete_tag(name)

deletes a tag



650
651
652
# File 'lib/git/base.rb', line 650

def delete_tag(name)
  lib.tag(name, { d: true })
end

#describe(committish = nil, opts = {})

returns the most recent tag that is reachable from a commit

options: :all :tags :contains :debug :exact_match :dirty :abbrev :candidates :long :always :match



450
451
452
# File 'lib/git/base.rb', line 450

def describe(committish = nil, opts = {})
  lib.describe(committish, opts)
end

#diff(objectish = 'HEAD', obj2 = nil) ⇒ Git::Diff

Returns a Git::Diff object.

Returns:



881
882
883
# File 'lib/git/base.rb', line 881

def diff(objectish = 'HEAD', obj2 = nil)
  Git::Diff.new(self, objectish, obj2)
end

#diff_path_status(objectish = 'HEAD', obj2 = nil, opts = {}) ⇒ Git::DiffPathStatus Also known as: diff_name_status

Returns a Git::Diff::PathStatus object for accessing the name-status report.

Parameters:

  • objectish (String) (defaults to: 'HEAD') —

    The first commit or object to compare. Defaults to 'HEAD'.

  • obj2 (String, nil) (defaults to: nil) —

    The second commit or object to compare.

  • opts (Hash) (defaults to: {}) —

    Options to filter the diff.

Options Hash (opts):

  • :path_limiter (String, Pathname, Array<String, Pathname>) —

    Limit status to specified path(s).

  • :path (String, Pathname, Array<String, Pathname>) — default: deprecated —

    Legacy alias for :path_limiter.

Returns:



962
963
964
965
966
967
968
969
970
971
972
973
# File 'lib/git/base.rb', line 962

def diff_path_status(objectish = 'HEAD', obj2 = nil, opts = {})
  path_limiter = if opts.key?(:path_limiter)
                   opts[:path_limiter]
                 elsif opts.key?(:path)
                   Git::Deprecation.warn(
                     'Git::Base#diff_path_status :path option is deprecated. Use :path_limiter instead.'
                   )
                   opts[:path]
                 end

  Git::DiffPathStatus.new(self, objectish, obj2, path_limiter)
end

#diff_stats(objectish = 'HEAD', obj2 = nil, opts = {}) ⇒ Git::DiffStats

Returns a Git::Diff::Stats object for accessing diff statistics.

Parameters:

  • objectish (String) (defaults to: 'HEAD') —

    The first commit or object to compare. Defaults to 'HEAD'.

  • obj2 (String, nil) (defaults to: nil) —

    The second commit or object to compare.

  • opts (Hash) (defaults to: {}) —

    Options to filter the diff.

Options Hash (opts):

  • :path_limiter (String, Pathname, Array<String, Pathname>) —

    Limit stats to specified path(s).

Returns:



950
951
952
# File 'lib/git/base.rb', line 950

def diff_stats(objectish = 'HEAD', obj2 = nil, opts = {})
  Git::DiffStats.new(self, objectish, obj2, opts[:path_limiter])
end

#dir

returns a reference to the working directory @git.dir.path @git.dir.writeable?



250
251
252
# File 'lib/git/base.rb', line 250

def dir
  @working_directory
end

#each_conflict

iterates over the files which are unmerged



534
535
536
# File 'lib/git/base.rb', line 534

def each_conflict(&) # :yields: file, your_version, their_version
  lib.conflicts(&)
end

#fetch(remote = 'origin', opts = {})

fetches changes from a remote branch - this does not modify the working directory, it just gets the changes from the remote if there are any



496
497
498
499
500
501
502
# File 'lib/git/base.rb', line 496

def fetch(remote = 'origin', opts = {})
  if remote.is_a?(Hash)
    opts = remote
    remote = nil
  end
  lib.fetch(remote, opts)
end

#fsck(objects = [], options = {}) ⇒ Git::FsckResult

Verifies the connectivity and validity of objects in the database

Runs git fsck to check repository integrity and identify dangling, missing, or unreachable objects.

rubocop:disable Style/ArgumentsForwarding

Returns categorized objects flagged by fsck.

Examples:

Check repository integrity

result = git.fsck
result.dangling.each { |obj| puts "#{obj.type}: #{obj.sha}" }

Check with strict mode and suppress dangling output

result = git.fsck(strict: true, dangling: false)

Check if repository has any issues

result = git.fsck
puts "Repository is clean" if result.empty?

List root commits

result = git.fsck(root: true)
result.root.each { |obj| puts obj.sha }

Check specific objects

result = git.fsck('abc1234', 'def5678')

Parameters:

  • objects (Array<String>) (defaults to: []) —

    specific objects to treat as heads for unreachability trace. If no objects are given, git fsck defaults to using the index file, all SHA-1 references in the refs namespace, and all reflogs.

  • options (Hash) (defaults to: {}) —

    options to pass to the underlying git fsck command

Options Hash (options):

  • :unreachable (Boolean) —

    print unreachable objects

  • :strict (Boolean) —

    enable strict checking

  • :connectivity_only (Boolean) —

    check only connectivity (faster)

  • :root (Boolean) —

    report root nodes

  • :tags (Boolean) —

    report tags

  • :cache (Boolean) —

    consider objects in the index

  • :no_reflogs (Boolean) —

    do not consider reflogs

  • :lost_found (Boolean) —

    write dangling objects to .git/lost-found (note: this modifies the repository by creating files)

  • :dangling (Boolean, nil) —

    print dangling objects (true/false/nil for default)

  • :full (Boolean, nil) —

    check objects in alternate pools (true/false/nil for default)

  • :name_objects (Boolean, nil) —

    name objects by refs (true/false/nil for default)

  • :references (Boolean, nil) —

    check refs database consistency (true/false/nil for default)

Returns:



714
715
716
# File 'lib/git/base.rb', line 714

def fsck(*objects, **opts)
  lib.fsck(*objects, **opts)
end

#gblob(objectish) ⇒ Git::Object

Returns a Git object.

Returns:



886
887
888
# File 'lib/git/base.rb', line 886

def gblob(objectish)
  Git::Object.new(self, objectish, 'blob')
end

#gc



664
665
666
# File 'lib/git/base.rb', line 664

def gc
  lib.gc
end

#gcommit(objectish) ⇒ Git::Object

Returns a Git object.

Returns:



891
892
893
# File 'lib/git/base.rb', line 891

def gcommit(objectish)
  Git::Object.new(self, objectish, 'commit')
end

#grep(string, path_limiter = nil, opts = {}) ⇒ Hash<String, Array>

Run a grep for 'string' on the HEAD of the git repository

Examples:

Limit grep's scope by calling grep() from a specific object:

git.object("v2.3").grep('TODO')

Using grep results:

git.grep("TODO").each do |sha, arr|
  puts "in blob #{sha}:"
  arr.each do |line_no, match_string|
    puts "\t line #{line_no}: '#{match_string}'"
  end
end

Parameters:

  • string (String) —

    the string to search for

  • path_limiter (String, Pathname, Array<String, Pathname>) (defaults to: nil) —

    a path or array of paths to limit the search to or nil for no limit

  • opts (Hash) (defaults to: {}) —

    options to pass to the underlying git grep command

Options Hash (opts):

  • :ignore_case (Boolean) — default: false —

    ignore case when matching

  • :invert_match (Boolean) — default: false —

    select non-matching lines

  • :extended_regexp (Boolean) — default: false —

    use extended regular expressions

  • :object (String) — default: HEAD —

    the object to search from

Returns:

  • (Hash<String, Array>) —

    a hash of arrays

    {
       'tree-ish1' => [[line_no1, match_string1], ...],
       'tree-ish2' => [[line_no1, match_string1], ...],
       ...
    }
    


395
396
397
# File 'lib/git/base.rb', line 395

def grep(string, path_limiter = nil, opts = {})
  object('HEAD').grep(string, path_limiter, opts)
end

#gtree(objectish) ⇒ Git::Object

Returns a Git object.

Returns:



896
897
898
# File 'lib/git/base.rb', line 896

def gtree(objectish)
  Git::Object.new(self, objectish, 'tree')
end

#ignored_files ⇒ Array<String>

List the files in the worktree that are ignored by git

Returns:

  • (Array<String>) —

    the list of ignored files relative to teh root of the worktree



402
403
404
# File 'lib/git/base.rb', line 402

def ignored_files
  lib.ignored_files
end

#is_branch?(branch) ⇒ Boolean

rubocop:disable Naming/PredicatePrefix

Returns:

  • (Boolean)


337
338
339
340
341
342
343
# File 'lib/git/base.rb', line 337

def is_branch?(branch) # rubocop:disable Naming/PredicatePrefix
  Git::Deprecation.warn(
    'Git::Base#is_branch? is deprecated and will be removed in a future version. ' \
    'Use Git::Base#branch? instead.'
  )
  branch?(branch)
end

#is_local_branch?(branch) ⇒ Boolean

rubocop:disable Naming/PredicatePrefix

Returns:

  • (Boolean)


309
310
311
312
313
314
315
# File 'lib/git/base.rb', line 309

def is_local_branch?(branch) # rubocop:disable Naming/PredicatePrefix
  Git::Deprecation.warn(
    'Git::Base#is_local_branch? is deprecated and will be removed in a future version. ' \
    'Use Git::Base#local_branch? instead.'
  )
  local_branch?(branch)
end

#is_remote_branch?(branch) ⇒ Boolean

rubocop:disable Naming/PredicatePrefix

Returns:

  • (Boolean)


323
324
325
326
327
328
329
# File 'lib/git/base.rb', line 323

def is_remote_branch?(branch) # rubocop:disable Naming/PredicatePrefix
  Git::Deprecation.warn(
    'Git::Base#is_remote_branch? is deprecated and will be removed in a future version. ' \
    'Use Git::Base#remote_branch? instead.'
  )
  remote_branch?(branch)
end

#lib

this is a convenience method for accessing the class that wraps all the actual 'git' forked system calls. At some point I hope to replace the Git::Lib class with one that uses native methods or libgit C bindings



348
349
350
# File 'lib/git/base.rb', line 348

def lib
  @lib ||= LibImpl.new(self, @logger)
end

#local_branch?(branch) ⇒ Boolean

returns true if the branch exists locally

Returns:

  • (Boolean)


304
305
306
307
# File 'lib/git/base.rb', line 304

def local_branch?(branch)
  branch_names = branches.local.map(&:name)
  branch_names.include?(branch)
end

#log(count = 30) ⇒ Git::Log

Returns a log with the specified number of commits.

Returns:

  • (Git::Log) —

    a log with the specified number of commits



901
902
903
# File 'lib/git/base.rb', line 901

def log(count = 30)
  Git::Log.new(self, count)
end

#ls_files(location = nil)



784
785
786
# File 'lib/git/base.rb', line 784

def ls_files(location = nil)
  lib.ls_files(location)
end

#ls_tree(objectish, opts = {})



822
823
824
# File 'lib/git/base.rb', line 822

def ls_tree(objectish, opts = {})
  lib.ls_tree(objectish, opts)
end

#merge(branch, message = 'merge', opts = {})

merges one or more branches into the current working branch

you can specify more than one branch to merge by passing an array of branches



529
530
531
# File 'lib/git/base.rb', line 529

def merge(branch, message = 'merge', opts = {})
  lib.merge(branch, message, opts)
end

#merge_base ⇒ Array<Git::Object::Commit>

Find as good common ancestors as possible for a merge example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true)

Returns:



938
939
940
941
# File 'lib/git/base.rb', line 938

def merge_base(*)
  shas = lib.merge_base(*)
  shas.map { |sha| gcommit(sha) }
end

#object(objectish) ⇒ Git::Object

returns a Git::Object of the appropriate type you can also call @git.gtree('tree'), but that's just for readability. If you call @git.gtree('HEAD') it will still return a Git::Object::Commit object.

object calls a method that will run a rev-parse on the objectish and determine the type of the object and return an appropriate object for that type

Returns:

  • (Git::Object) —

    an instance of the appropriate type of Git::Object



915
916
917
# File 'lib/git/base.rb', line 915

def object(objectish)
  Git::Object.new(self, objectish)
end

#pull(remote = nil, branch = nil, opts = {}) ⇒ Void

Pulls the given branch from the given remote into the current branch

Examples:

pulls from origin/master

@git.pull

pulls from upstream/master

@git.pull('upstream')

pulls from upstream/develop

@git.pull('upstream', 'develop')

Parameters:

  • remote (String) (defaults to: nil) —

    the remote repository to pull from

  • branch (String) (defaults to: nil) —

    the branch to pull from

  • opts (Hash) (defaults to: {}) —

    options to pass to the pull command

Options Hash (opts):

  • :allow_unrelated_histories (Boolean) — default: false —

    Merges histories of two projects that started their lives independently

Returns:

  • (Void)

Raises:

  • (Git::FailedError) —

    if the pull fails

  • (ArgumentError) —

    if a branch is given without a remote



557
558
559
# File 'lib/git/base.rb', line 557

def pull(remote = nil, branch = nil, opts = {})
  lib.pull(remote, branch, opts)
end

#push(remote = nil, branch = nil, options = {}) ⇒ Void

Push changes to a remote repository

Parameters:

  • remote (String) (defaults to: nil) —

    the remote repository to push to

  • branch (String) (defaults to: nil) —

    the branch to push

  • options (Hash) (defaults to: {}) —

    options to pass to the push command

Returns:

  • (Void)

Raises:

  • (Git::FailedError) —

    if the push fails

  • (ArgumentError) —

    if a branch is given without a remote



522
523
524
# File 'lib/git/base.rb', line 522

def push(*, **)
  lib.push(*, **)
end

#read_tree(treeish, opts = {})



767
768
769
# File 'lib/git/base.rb', line 767

def read_tree(treeish, opts = {})
  lib.read_tree(treeish, opts)
end

#remote(remote_name = 'origin') ⇒ Git::Remote

Returns a remote of the specified name.

Returns:



920
921
922
# File 'lib/git/base.rb', line 920

def remote(remote_name = 'origin')
  Git::Remote.new(self, remote_name)
end

#remote_branch?(branch) ⇒ Boolean

returns true if the branch exists remotely

Returns:

  • (Boolean)


318
319
320
321
# File 'lib/git/base.rb', line 318

def remote_branch?(branch)
  branch_names = branches.remote.map(&:name)
  branch_names.include?(branch)
end

#remote_set_branches(name, *branches, add: false) ⇒ nil

Configures which branches are fetched for a remote

Uses git remote set-branches to set or append fetch refspecs. When the add: option is not given, the --add option is not passed to the git command

the underlying git command fails

Examples:

Replace fetched branches with a single glob pattern

git = Git.open('/path/to/repo')
# Only fetch branches matching "feature/*" from origin
git.remote_set_branches('origin', 'feature/*')

Append a glob pattern to existing fetched branches

git = Git.open('/path/to/repo')
# Keep existing fetch refspecs and add all release branches
git.remote_set_branches('origin', 'release/*', add: true)

Configure multiple explicit branches

git = Git.open('/path/to/repo')
git.remote_set_branches('origin', 'main', 'development', 'hotfix')

Parameters:

  • name (String) —

    the remote name (for example, "origin")

  • branches (Array<String>) —

    branch names or globs (for example, '*')

  • add (Boolean) (defaults to: false) —

    when true, append to existing refspecs instead of replacing them

Returns:

  • (nil)

Raises:

  • (ArgumentError) —

    if no branches are provided @raise [Git::FailedError] if



605
606
607
608
609
610
611
612
# File 'lib/git/base.rb', line 605

def remote_set_branches(name, *branches, add: false)
  branch_list = branches.flatten
  raise ArgumentError, 'branches are required' if branch_list.empty?

  lib.remote_set_branches(name, branch_list, add: add)

  nil
end

#remotes

returns an array of Git:Remote objects



562
563
564
# File 'lib/git/base.rb', line 562

def remotes
  lib.remotes.map { |r| Git::Remote.new(self, r) }
end

#remove_remote(name)

removes a remote from this repository

@git.remove_remote('scott_git')



617
618
619
# File 'lib/git/base.rb', line 617

def remove_remote(name)
  lib.remote_remove(name)
end

#repack

repacks the repository



660
661
662
# File 'lib/git/base.rb', line 660

def repack
  lib.repack
end

#repo

returns reference to the git repository directory @git.dir.path



259
260
261
# File 'lib/git/base.rb', line 259

def repo
  @repository
end

#repo_size

returns the repository size in bytes



264
265
266
267
268
269
270
271
# File 'lib/git/base.rb', line 264

def repo_size
  all_files = Dir.glob(File.join(repo.path, '**', '*'), File::FNM_DOTMATCH)

  all_files.reject { |file| file.include?('..') }
           .map { |file| File.expand_path(file) }
           .uniq
           .sum { |file| File.stat(file).size.to_i }
end

#reset(commitish = nil, opts = {})

resets the working directory to the provided commitish



414
415
416
# File 'lib/git/base.rb', line 414

def reset(commitish = nil, opts = {})
  lib.reset(commitish, opts)
end

#reset_hard(commitish = nil, opts = {})

resets the working directory to the commitish with '--hard'



419
420
421
422
# File 'lib/git/base.rb', line 419

def reset_hard(commitish = nil, opts = {})
  opts = { hard: true }.merge(opts)
  lib.reset(commitish, opts)
end

#rev_parse(objectish) Also known as: revparse

runs git rev-parse to convert the objectish to a full sha

Examples:

git.rev_parse("HEAD^^")
git.rev_parse('v2.4^{tree}')
git.rev_parse('v2.4:/doc/index.html')


815
816
817
# File 'lib/git/base.rb', line 815

def rev_parse(objectish)
  lib.rev_parse(objectish)
end

#revert(commitish = nil, opts = {})

reverts the working directory to the provided commitish. Accepts a range, such as comittish..HEAD

options:

:no_edit


460
461
462
# File 'lib/git/base.rb', line 460

def revert(commitish = nil, opts = {})
  lib.revert(commitish, opts)
end

#rm(path = '.', opts = {}) Also known as: remove

removes file(s) from the git repository



407
408
409
# File 'lib/git/base.rb', line 407

def rm(path = '.', opts = {})
  lib.rm(path, opts)
end

#set_index(index_file, check = nil, must_exist: nil)



273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/git/base.rb', line 273

def set_index(index_file, check = nil, must_exist: nil)
  unless check.nil?
    Git::Deprecation.warn(
      'The "check" argument is deprecated and will be removed in a future version. ' \
      'Use "must_exist:" instead.'
    )
  end

  # default is true
  must_exist = must_exist.nil? && check.nil? ? true : must_exist | check

  @lib = nil
  @index = Git::Index.new(index_file.to_s, must_exist:)
end

#set_remote_url(name, url)

sets the url for a remote url can be a git url or a Git::Base object if it's a local reference

@git.set_remote_url('scotts_git', 'git://repo.or.cz/rubygit.git')



571
572
573
574
575
# File 'lib/git/base.rb', line 571

def set_remote_url(name, url)
  url = url.repo.to_s if url.is_a?(Git::Base)
  lib.remote_set_url(name, url)
  Git::Remote.new(self, name)
end

#set_working(work_dir, check = nil, must_exist: nil)



288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/git/base.rb', line 288

def set_working(work_dir, check = nil, must_exist: nil)
  unless check.nil?
    Git::Deprecation.warn(
      'The "check" argument is deprecated and will be removed in a future version. ' \
      'Use "must_exist:" instead.'
    )
  end

  # default is true
  must_exist = must_exist.nil? && check.nil? ? true : must_exist | check

  @lib = nil
  @working_directory = Git::WorkingDirectory.new(work_dir.to_s, must_exist:)
end

#show(objectish = nil, path = nil) ⇒ String

Shows objects

Parameters:

  • objectish (String|NilClass) (defaults to: nil) —

    the target object reference (nil == HEAD)

  • path (String|NilClass) (defaults to: nil) —

    the path of the file to be shown

Returns:

  • (String) —

    the object information



734
735
736
# File 'lib/git/base.rb', line 734

def show(objectish = nil, path = nil)
  lib.show(objectish, path)
end

#status ⇒ Git::Status

Returns a status object.

Returns:



925
926
927
# File 'lib/git/base.rb', line 925

def status
  Git::Status.new(self)
end

#tag(tag_name) ⇒ Git::Object::Tag

Returns a tag object.

Returns:



930
931
932
# File 'lib/git/base.rb', line 930

def tag(tag_name)
  Git::Object::Tag.new(self, tag_name)
end

#tags

returns an array of all Git::Tag objects for this repository



622
623
624
# File 'lib/git/base.rb', line 622

def tags
  lib.tags.map { |r| tag(r) }
end

#update_ref(branch, commit)



780
781
782
# File 'lib/git/base.rb', line 780

def update_ref(branch, commit)
  branch(branch).update_ref(commit)
end

#with_index(new_index)

LOWER LEVEL INDEX OPERATIONS ##



740
741
742
743
744
745
746
# File 'lib/git/base.rb', line 740

def with_index(new_index) # :yields: new_index
  old_index = @index
  set_index(new_index, false)
  return_value = yield @index
  set_index(old_index)
  return_value
end

#with_temp_index



748
749
750
751
752
753
754
755
756
757
758
759
760
761
# File 'lib/git/base.rb', line 748

def with_temp_index(&)
  # Workaround for JRUBY, since they handle the TempFile path different.
  # MUST be improved to be safer and OS independent.
  if RUBY_PLATFORM == 'java'
    temp_path = "/tmp/temp-index-#{(0...15).map { ('a'..'z').to_a[rand(26)] }.join}"
  else
    tempfile = Tempfile.new('temp-index')
    temp_path = tempfile.path
    tempfile.close
    tempfile.unlink
  end

  with_index(temp_path, &)
end

#with_temp_working



799
800
801
802
803
804
805
806
# File 'lib/git/base.rb', line 799

def with_temp_working(&)
  tempfile = Tempfile.new('temp-workdir')
  temp_dir = tempfile.path
  tempfile.close
  tempfile.unlink
  Dir.mkdir(temp_dir, 0o700)
  with_working(temp_dir, &)
end

#with_working(work_dir)

:yields: the Git::WorkingDirectory



788
789
790
791
792
793
794
795
796
797
# File 'lib/git/base.rb', line 788

def with_working(work_dir) # :yields: the Git::WorkingDirectory
  return_value = false
  old_working = @working_directory
  set_working(work_dir)
  Dir.chdir work_dir do
    return_value = yield @working_directory
  end
  set_working(old_working)
  return_value
end

#worktree(dir, commitish = nil)

returns a Git::Worktree object for dir, commitish



865
866
867
# File 'lib/git/base.rb', line 865

def worktree(dir, commitish = nil)
  Git::Worktree.new(self, dir, commitish)
end

#worktrees

returns a Git::worktrees object of all the Git::Worktrees objects for this repo



871
872
873
# File 'lib/git/base.rb', line 871

def worktrees
  Git::Worktrees.new(self)
end

#write_and_commit_tree(opts = {})



775
776
777
778
# File 'lib/git/base.rb', line 775

def write_and_commit_tree(opts = {})
  tree = write_tree
  commit_tree(tree, opts)
end

#write_tree



771
772
773
# File 'lib/git/base.rb', line 771

def write_tree
  lib.write_tree
end