Module: Git::Repository::RemoteOperations

Included in:
Git::Repository
Defined in:
lib/git/repository/remote_operations.rb

Overview

Mixin that adds remote operation facade methods to Git::Repository

Included by Git::Repository.

Instance Method Summary collapse

Instance Method Details

#add_remote(name, url, opts = {}) ⇒ Git::Remote

Register a new remote in the local repository

Associates name with url and optionally fetches immediately or configures which branches are tracked.

Examples:

Add a remote

repo.add_remote('upstream', 'https://github.com/user/repo.git')

Add a remote and fetch immediately

repo.add_remote('upstream', 'https://github.com/user/repo.git', fetch: true)

Add a remote tracking a specific branch

repo.add_remote('upstream', 'https://github.com/user/repo.git', track: 'main')

Parameters:

  • name (String)

    the name for the new remote

  • url (String, Git::Base)

    the URL of the remote repository

    A Base instance is accepted for local references and converted to url.repo.to_s.

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

    options for adding the remote

Options Hash (opts):

  • :fetch (Boolean, nil) — default: nil

    fetch from the remote immediately after adding it (-f)

    The deprecated alias :with_fetch is accepted and normalized automatically.

  • :track (String, nil) — default: nil

    track only the given branch during fetch (-t)

Returns:

Raises:

  • (ArgumentError)

    when unsupported option keys are provided

  • (Git::FailedError)

    when git exits with a non-zero status



417
418
419
420
421
422
423
424
# File 'lib/git/repository/remote_operations.rb', line 417

def add_remote(name, url, opts = {})
  url = url.repo.to_s if url.is_a?(Git::Base)
  opts = Private.normalize_add_remote_keys(opts)
  SharedPrivate.assert_valid_opts!(ADD_REMOTE_ALLOWED_OPTS, **opts)
  Git::Commands::Remote::Add.new(@execution_context).call(name, url, **opts)

  Git::Remote.new(self, name)
end

#config_remote(name) ⇒ Hash{String => String}

Return the git configuration entries for a named remote

Reads git config --list and returns all entries whose keys begin with remote.<name>., with the remote.<name>. prefix stripped. This typically yields at least "url" and "fetch" for a configured remote.

Examples:

Retrieve the config for the 'origin' remote

repo.config_remote('origin')
#=> {
#     'url'   => 'https://github.com/user/repo.git',
#     'fetch' => '+refs/heads/*:refs/remotes/origin/*'
#   }

Parameters:

  • name (String)

    the name of the remote (e.g. "origin")

Returns:

  • (Hash{String => String})

    configuration entries for the remote, keyed without the remote.<name>. prefix

    Returns an empty hash when no entries are found.

Raises:



532
533
534
535
536
537
# File 'lib/git/repository/remote_operations.rb', line 532

def config_remote(name)
  prefix = "remote.#{name}."
  Private.config_list(@execution_context).each_with_object({}) do |(key, value), hsh|
    hsh[key.delete_prefix(prefix)] = value if key.start_with?(prefix)
  end
end

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

Download objects and refs from a remote repository

Fetches branches and/or tags from one or more other repositories, along with the objects necessary to complete their histories. The local tracking references are updated but the working directory is not modified.

Examples:

Fetch from the default remote

repo.fetch

Fetch from a named remote

repo.fetch('upstream')

Fetch all remotes at once

repo.fetch(all: true)

Fetch and prune deleted remote branches

repo.fetch('origin', prune: true)

Fetch a specific refspec

repo.fetch('origin', ref: 'refs/heads/main:refs/remotes/origin/main')

Fetch multiple refspecs

repo.fetch('origin', ref: ['refs/heads/main', 'refs/heads/develop'])

Fetch and include all tags

repo.fetch('origin', tags: true)

Returns the merged stdout from the fetch command.

Parameters:

  • remote (String, Hash, nil) (defaults to: 'origin')

    the remote name or URL to fetch from

    When a Hash is given it is treated as opts and remote defaults to nil (which omits the remote positional argument and lets git use the configured default).

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

    options for the fetch command

Options Hash (opts):

  • :all (Boolean, nil) — default: nil

    fetch from all configured remotes (--all)

  • :tags (Boolean, nil) — default: nil

    fetch all tags from the remote (--tags)

    Alias: :t

  • :prune (Boolean, nil) — default: nil

    remove remote-tracking references that no longer exist on the remote (--prune)

    Alias: :p

  • :prune_tags (Boolean, nil) — default: nil

    remove local tags that no longer exist on the remote (--prune-tags)

    Alias: :P. The legacy dash-style key :'prune-tags' is also accepted and normalized automatically.

  • :force (Boolean, nil) — default: nil

    override the fast-forward check when using explicit refspecs (--force)

    Alias: :f

  • :update_head_ok (Boolean, nil) — default: nil

    allow git fetch to update the branch pointed to by HEAD (--update-head-ok)

    Alias: :u. The legacy dash-style key :'update-head-ok' is also accepted and normalized automatically.

  • :unshallow (Boolean, nil) — default: nil

    convert a shallow clone into a full repository (--unshallow)

  • :depth (String, Integer) — default: nil

    limit history to N commits from each branch tip (--depth=N)

  • :ref (String, Array<String>) — default: nil

    one or more refspecs to fetch; forwarded as positional arguments after the remote name. An explicit remote is required when :ref is given.

Returns:

  • (String)

    the merged stdout from the fetch command

Raises:

  • (ArgumentError)

    when unsupported option keys are provided or :ref is supplied without an explicit remote

  • (Git::FailedError)

    when git exits with a non-zero status



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/git/repository/remote_operations.rb', line 129

def fetch(remote = 'origin', opts = {})
  remote, opts = Private.resolve_fetch_target(remote, opts)

  opts = Private.normalize_fetch_keys(opts)
  SharedPrivate.assert_valid_opts!(FETCH_ALLOWED_OPTS, **opts)

  opts = opts.dup
  refspecs = Array(opts.delete(:ref)).compact
  positionals = [*([remote] if remote), *refspecs]

  Git::Commands::Fetch.new(@execution_context).call(*positionals, **opts, merge: true).stdout
end

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

Incorporate changes from a remote repository into the current branch

Fetches from the given remote and merges into the current branch. In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD. The merge editor is suppressed (--no-edit) and progress output is silenced (--no-progress) by default.

Examples:

Pull from the default remote and branch

repo.pull

Pull from a named remote

repo.pull('upstream')

Pull a specific branch from a remote

repo.pull('origin', 'main')

Pull allowing unrelated histories

repo.pull('origin', 'main', allow_unrelated_histories: true)

Returns the stdout from the pull command.

Parameters:

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

    the remote name or URL to pull from

    When nil, git uses the tracking remote for the current branch.

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

    the remote branch name to pull

    When nil, git uses the tracking branch for the current branch. A branch may not be specified without also specifying a remote.

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

    options for the pull command

Options Hash (opts):

  • :allow_unrelated_histories (Boolean, nil) — default: nil

    allow merging histories that do not share a common ancestor (--allow-unrelated-histories)

Returns:

  • (String)

    the stdout from the pull command

Raises:

  • (ArgumentError)

    when a branch is given without a remote, or when unsupported option keys are provided

  • (Git::FailedError)

    when git exits with a non-zero status

Raises:

  • (ArgumentError)


196
197
198
199
200
201
202
203
204
205
# File 'lib/git/repository/remote_operations.rb', line 196

def pull(remote = nil, branch = nil, opts = {})
  raise ArgumentError, 'You must specify a remote if a branch is specified' if remote.nil? && !branch.nil?

  SharedPrivate.assert_valid_opts!(PULL_ALLOWED_OPTS, **opts)
  positional_args = [remote, branch].compact
  Git::Commands::Pull
    .new(@execution_context)
    .call(*positional_args, no_edit: true, no_progress: true, **opts)
    .stdout
end

#push(options = {}) ⇒ String #push(remote, options = {}) ⇒ String #push(remote, branch, options = {}) ⇒ String #push(remote, branch, tags) ⇒ String

Push refs to a remote repository

Examples:

Push using the current branch's default remote and push configuration

repo.push

Push to a named remote

repo.push('origin')

Force-push the current branch to a named remote

repo.push('origin', force: true)

Push a specific branch to a named remote

repo.push('origin', 'main')

Push a branch and all tags to a named remote

repo.push('origin', 'main', tags: true)

Push all branches to a named remote

repo.push('origin', all: true)

Mirror all refs to a named remote

repo.push('origin', mirror: true)

Overloads:

  • #push(options = {}) ⇒ String

    Push using the current branch's default remote and push configuration

    Parameters:

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

      push options (see option list below)

    Options Hash (options):

    • :all (Boolean, nil) — default: nil

      push all branches (--all)

    • :mirror (Boolean, nil) — default: nil

      push all refs under refs/ to the remote (--mirror)

      When :tags is also given, the separate tags push is suppressed.

    • :tags (Boolean, nil) — default: nil

      push all refs under refs/tags/ in a second git push invocation (--tags)

      When :mirror is also given, the tags push is suppressed because --mirror already includes tags.

    • :force (Boolean, nil) — default: nil

      force updates, overriding the fast-forward check (--force)

      Alias: :f

    • :delete (Boolean, nil) — default: nil

      delete the named refs from the remote (--delete)

    • :push_option (String, Array<String>) — default: nil

      one or more server-side push option values (--push-option=<value>, repeatable)

    Returns:

    • (String)

      the stdout from the push command

  • #push(remote, options = {}) ⇒ String

    Push to the given remote using the current branch's default push configuration

    Parameters:

    • remote (String)

      the remote name or URL to push to

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

      push options (see option list below)

    Options Hash (options):

    • :all (Boolean, nil) — default: nil

      push all branches (--all)

    • :mirror (Boolean, nil) — default: nil

      push all refs under refs/ to the remote (--mirror)

      When :tags is also given, the separate tags push is suppressed.

    • :tags (Boolean, nil) — default: nil

      push all refs under refs/tags/ in a second git push invocation (--tags)

      When :mirror is also given, the tags push is suppressed because --mirror already includes tags.

    • :force (Boolean, nil) — default: nil

      force updates, overriding the fast-forward check (--force)

      Alias: :f

    • :delete (Boolean, nil) — default: nil

      delete the named refs from the remote (--delete)

    • :push_option (String, Array<String>) — default: nil

      one or more server-side push option values (--push-option=<value>, repeatable)

    Returns:

    • (String)

      the stdout from the push command

  • #push(remote, branch, options = {}) ⇒ String

    Push a branch or refspec to the given remote

    Parameters:

    • remote (String)

      the remote name or URL to push to

    • branch (String)

      the branch name or refspec to push

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

      push options (see option list below)

    Options Hash (options):

    • :all (Boolean, nil) — default: nil

      push all branches (--all)

    • :mirror (Boolean, nil) — default: nil

      push all refs under refs/ to the remote (--mirror)

      When :tags is also given, the separate tags push is suppressed.

    • :tags (Boolean, nil) — default: nil

      push all refs under refs/tags/ in a second git push invocation (--tags)

      When :mirror is also given, the tags push is suppressed because --mirror already includes tags.

    • :force (Boolean, nil) — default: nil

      force updates, overriding the fast-forward check (--force)

      Alias: :f

    • :delete (Boolean, nil) — default: nil

      delete the named refs from the remote (--delete)

    • :push_option (String, Array<String>) — default: nil

      one or more server-side push option values (--push-option=<value>, repeatable)

    Returns:

    • (String)

      the stdout from the push command

    Raises:

    • (ArgumentError)

      if remote is nil when branch is given

  • #push(remote, branch, tags) ⇒ String

    Backward-compatible shorthand for push(remote, branch, tags: tags)

    Parameters:

    • remote (String)

      the remote name or URL to push to

    • branch (String)

      the branch name or refspec to push

    • tags (Boolean)

      whether to push all tags; equivalent to tags: tags

    Returns:

    • (String)

      the stdout from the push command

    Raises:

    • (ArgumentError)

      if a branch is given and remote is nil

Raises:

  • (ArgumentError)

    when unsupported option keys are provided

  • (Git::FailedError)

    when git exits with a non-zero exit status



362
363
364
365
366
367
368
369
370
371
# File 'lib/git/repository/remote_operations.rb', line 362

def push(remote = nil, branch = nil, opts = nil)
  remote, branch, opts = Private.normalize_push_args(remote, branch, opts)
  SharedPrivate.assert_valid_opts!(PUSH_ALLOWED_OPTS, **opts)
  raise ArgumentError, 'remote is required if branch is specified' if !remote && branch

  first_result = Private.push_refs(@execution_context, remote, branch, opts)
  return first_result.stdout unless Private.push_tags_separately?(opts)

  Private.push_tags(@execution_context, remote, opts).stdout
end

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

Returns a Git::Remote object for the named remote

Examples:

Get the default 'origin' remote

repo.remote  #=> #<Git::Remote 'origin'>

Get a named remote

repo.remote('upstream')  #=> #<Git::Remote 'upstream'>

Parameters:

  • name (String) (defaults to: 'origin')

    the remote name (defaults to 'origin')

Returns:

Raises:



553
554
555
# File 'lib/git/repository/remote_operations.rb', line 553

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

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

This method returns an undefined value.

Configures which branches are fetched for a remote

Uses git remote set-branches to set or append fetch refspecs. When the add: option is false, the --add flag is not passed to the git command and the tracked branch list is replaced.

Examples:

Replace fetched branches with a single glob pattern

repo.remote_set_branches('origin', 'feature/*')

Append a glob pattern to existing fetched branches

repo.remote_set_branches('origin', 'release/*', add: true)

Configure multiple explicit branches

repo.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

Raises:

  • (ArgumentError)

    when no branches are provided

  • (Git::FailedError)

    when git exits with a non-zero status



501
502
503
504
505
506
507
508
# File 'lib/git/repository/remote_operations.rb', line 501

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

  Git::Commands::Remote::SetBranches.new(@execution_context).call(name, *branch_list, add: add)

  nil
end

#remotesArray<Git::Remote>

Returns all configured remotes as Git::Remote objects

Examples:

List all remotes

repo.remotes  #=> [#<Git::Remote 'origin'>, #<Git::Remote 'upstream'>]

Returns:

  • (Array<Git::Remote>)

    one Git::Remote for each configured remote

    Returns an empty array when no remotes are configured.

Raises:



568
569
570
571
# File 'lib/git/repository/remote_operations.rb', line 568

def remotes
  result = Git::Commands::Remote::List.new(@execution_context).call
  result.stdout.split("\n").map { |name| Git::Remote.new(self, name) }
end

#remove_remote(name) ⇒ Git::CommandLineResult

Removes a remote from this repository

Deletes the remote named name along with its associated configuration, tracking references, and remote-tracking branches.

Examples:

Remove a remote named 'upstream'

repo.remove_remote('upstream')

Parameters:

  • name (String)

    the name of the remote to remove

Returns:

Raises:



440
441
442
# File 'lib/git/repository/remote_operations.rb', line 440

def remove_remote(name)
  Git::Commands::Remote::Remove.new(@execution_context).call(name)
end

#set_remote_url(name, url) ⇒ Git::Remote

Sets the URL for an existing remote

Replaces the fetch URL configured for the remote named name.

Examples:

Set the URL for a remote

repo.set_remote_url('origin', 'https://github.com/user/repo.git')

Set the URL from a local repository reference

source = Git.open('/path/to/source')
repo.set_remote_url('origin', source)

Parameters:

  • name (String)

    the name of the remote to update

  • url (String, Git::Base)

    the new URL for the remote

    A Base instance is accepted for local references and converted to url.repo.to_s.

Returns:

Raises:



466
467
468
469
470
471
# File 'lib/git/repository/remote_operations.rb', line 466

def set_remote_url(name, url)
  url = url.repo.to_s if url.is_a?(Git::Base)
  Git::Commands::Remote::SetUrl.new(@execution_context).call(name, url)

  Git::Remote.new(self, name)
end