Module: Git::Repository::Stashing Private

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

Overview

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

Facade methods for stash operations

Each method maps onto a git stash subcommand. Methods that identify or create a stash entry (#stash_infos, #stash_push, #stash_store) return StashInfo values; methods that only change or display the stash return git's stdout. Every method that takes a stash (#stash_apply, #stash_pop, #stash_drop, #stash_show, #stash_branch) accepts a StashInfo, a stash@{N} name, an Integer index (0 is the most recent entry), or nil for the most recent entry. Methods that take options accept them as a trailing positional Hash, so repo.stash_apply(index: true) and repo.stash_apply(nil, opts) with a stored opts Hash both work.

#stashes_all, #stash_save, and #stash_list are the legacy surface. They are deprecated and will be removed in v6.0.0.

Included by Git::Repository.

API:

  • private

Instance Method Summary collapse

Instance Method Details

#stash_apply(stash = nil, opts = {}) ⇒ String

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.

Apply a stash entry to the working tree, keeping it in the stash list

Examples:

Apply the most recent entry

repo.stash_apply #=> "On branch main\nChanges not staged for commit:..."

Apply an entry from #stash_infos

repo.stash_apply(repo.stash_infos.last)

Apply an entry by name and restore the index too

repo.stash_apply('stash@{1}', index: true)

Parameters:

  • (defaults to: nil)

    the entry to apply: a StashInfo, a stash@{N} name, an Integer N (0 is the most recent entry), or nil for the most recent entry

  • (defaults to: {})

    options for the apply

Options Hash (opts):

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

    restore the index state as well as the working tree

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

    suppress informational messages (alias: :q)

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

    alias for :quiet

Returns:

  • git's stdout from the apply

Raises:

  • if unsupported options are provided

  • if git exits with a non-zero exit status

See Also:

API:

  • private



184
185
186
187
188
# File 'lib/git/repository/stashing.rb', line 184

def stash_apply(stash = nil, opts = {})
  stash, opts = Private.split_stash_and_opts(stash, opts)
  SharedPrivate.assert_valid_opts!(STASH_APPLY_ALLOWED_OPTS, **opts)
  Git::Commands::Stash::Apply.new(@execution_context).call(stash, **opts).stdout
end

#stash_branch(branch_name, stash = nil) ⇒ String

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.

Create and check out a branch from the commit a stash entry was based on

Applies the entry on the new branch and, when that succeeds, drops the entry from the stash list.

Examples:

Branch from the most recent entry

repo.stash_branch('feature') #=> "Switched to a new branch 'feature'\n..."

Branch from an entry from #stash_infos

repo.stash_branch('feature', repo.stash_infos.last)

Parameters:

  • the name of the branch to create

  • (defaults to: nil)

    the entry to branch from: a StashInfo, a stash@{N} name, an Integer N (0 is the most recent entry), or nil for the most recent entry

Returns:

  • git's stdout from the branch command

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



374
375
376
# File 'lib/git/repository/stashing.rb', line 374

def stash_branch(branch_name, stash = nil)
  Git::Commands::Stash::Branch.new(@execution_context).call(branch_name, stash).stdout
end

#stash_clearString

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.

Remove all stash entries

Removes all entries from the stash list. Use with caution as this operation cannot be undone.

Examples:

Clear all stashes

repo.stash_clear #=> ""

Returns:

  • the output from the git stash clear command (typically empty)

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



461
462
463
# File 'lib/git/repository/stashing.rb', line 461

def stash_clear
  Git::Commands::Stash::Clear.new(@execution_context).call.stdout
end

#stash_create(message = nil) ⇒ String?

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.

Create a stash commit without adding it to the stash list

The working tree and index are left unchanged. Pass the returned object id to #stash_store to add it to the stash list later.

Examples:

Create a stash commit

repo.stash_create('WIP') #=> "3f8b2d9c..." (the full object id)

Nothing to stash

repo.stash_create #=> nil

Parameters:

  • (defaults to: nil)

    the message for the stash commit; nil for git's default message

Returns:

  • the object id of the stash commit, or nil when there were no local changes

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



399
400
401
402
# File 'lib/git/repository/stashing.rb', line 399

def stash_create(message = nil)
  oid = Git::Commands::Stash::Create.new(@execution_context).call(message).stdout.strip
  oid.empty? ? nil : oid
end

#stash_drop(stash = nil, opts = {}) ⇒ String

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.

Remove a single stash entry from the stash list

Examples:

Drop the most recent entry

repo.stash_drop #=> "Dropped refs/stash@{0} (abc1234...)"

Drop an entry from #stash_infos

repo.stash_drop(repo.stash_infos.last)

Parameters:

  • (defaults to: nil)

    the entry to drop: a StashInfo, a stash@{N} name, an Integer N (0 is the most recent entry), or nil for the most recent entry

  • (defaults to: {})

    options for the drop

Options Hash (opts):

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

    suppress informational messages (alias: :q)

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

    alias for :quiet

Returns:

  • git's stdout from the drop

Raises:

  • if unsupported options are provided

  • if git exits with a non-zero exit status

See Also:

API:

  • private



261
262
263
264
265
# File 'lib/git/repository/stashing.rb', line 261

def stash_drop(stash = nil, opts = {})
  stash, opts = Private.split_stash_and_opts(stash, opts)
  SharedPrivate.assert_valid_opts!(STASH_DROP_ALLOWED_OPTS, **opts)
  Git::Commands::Stash::Drop.new(@execution_context).call(stash, **opts).stdout
end

#stash_infosArray<Git::StashInfo>

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 every stash entry as a StashInfo, newest first

The order and indices match git stash list: the first element is stash@{0}, the most recent entry.

Examples:

List stash entries (newest first)

repo.stash_infos.map(&:name) #=> ["stash@{0}", "stash@{1}"]

Apply the oldest entry

repo.stash_apply(repo.stash_infos.last)

Returns:

  • the stash entries, newest first; empty when there are none

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



48
49
50
51
# File 'lib/git/repository/stashing.rb', line 48

def stash_infos
  result = Git::Commands::Stash::List.new(@execution_context).call
  Git::Parsers::Stash.parse_list(result.stdout)
end

#stash_listString

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.

Deprecated.

Use #stash_infos instead and format the entries yourself: repo.stash_infos.map { |s| "#{s.name}: #{s.message}" }.join("\n"). This method will be removed in v6.0.0, and a later release will reuse the name for a method returning Array<Git::StashInfo>.

Returns stash entries as a formatted string matching git stash list output

Examples:

List stashes as a formatted string

repo.stash_list #=> "stash@{0}: On main: WIP\nstash@{1}: On feature: Fix bug"

Returns:

  • newline-joined "stash@{n}: <full message>" entries, or an empty string when there are no stashes; the format matches git stash list output

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



527
528
529
530
531
532
533
# File 'lib/git/repository/stashing.rb', line 527

def stash_list
  Git::Deprecation.warn(
    'Git::Repository#stash_list is deprecated and will be removed in v6.0.0. ' \
    'Use Git::Repository#stash_infos instead.'
  )
  stash_infos.map { |info| "#{info.name}: #{info.message}" }.join("\n")
end

#stash_pop(stash = nil, opts = {}) ⇒ String

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.

Apply a stash entry to the working tree and remove it from the stash list

Examples:

Pop the most recent entry

repo.stash_pop #=> "On branch main\n...Dropped refs/stash@{0} (abc1234...)"

Pop an entry from #stash_infos

repo.stash_pop(repo.stash_infos.last)

Parameters:

  • (defaults to: nil)

    the entry to pop: a StashInfo, a stash@{N} name, an Integer N (0 is the most recent entry), or nil for the most recent entry

  • (defaults to: {})

    options for the pop

Options Hash (opts):

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

    restore the index state as well as the working tree

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

    suppress informational messages (alias: :q)

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

    alias for :quiet

Returns:

  • git's stdout from the pop

Raises:

  • if unsupported options are provided

  • if git exits with a non-zero exit status

See Also:

API:

  • private



224
225
226
227
228
# File 'lib/git/repository/stashing.rb', line 224

def stash_pop(stash = nil, opts = {})
  stash, opts = Private.split_stash_and_opts(stash, opts)
  SharedPrivate.assert_valid_opts!(STASH_POP_ALLOWED_OPTS, **opts)
  Git::Commands::Stash::Pop.new(@execution_context).call(stash, **opts).stdout
end

#stash_push(*pathspec, options = {}) ⇒ Git::StashInfo?

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.

Save the working tree and index state to a new stash entry

The stash list is read before and after the push and the entry counts are compared, so the return value is nil whenever git created no entry. This holds with quiet: true, which suppresses git's "No local changes to save" message.

Returns the new entry, or nil when there were no local changes to save.

Examples:

Stash all changes with a message

info = repo.stash_push(message: 'WIP: feature work')
info.name    #=> "stash@{0}"
info.message #=> "On main: WIP: feature work"

Stash only specific paths

repo.stash_push('src/a.rb', 'src/b.rb', message: 'partial work')

Nothing to stash

repo.stash_push #=> nil

Parameters:

  • paths that limit what gets stashed; when empty, all changes are stashed

  • (defaults to: {})

    options for the push

Options Hash (options):

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

    interactively select hunks to stash (alias: :p)

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

    alias for :patch

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

    stash only the staged changes (alias: :S; requires git 2.35+)

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

    alias for :staged (requires git 2.35+)

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

    keep the staged changes in the index (alias: :k)

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

    alias for :keep_index

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

    do not keep the staged changes in the index

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

    suppress informational messages (alias: :q)

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

    alias for :quiet

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

    include untracked files in the stash (alias: :u)

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

    alias for :include_untracked

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

    include untracked and ignored files in the stash (alias: :a)

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

    alias for :all

  • :message (String) — default: nil

    the stash message (alias: :m)

  • :m (String) — default: nil

    alias for :message

  • :pathspec_from_file (String) — default: nil

    read pathspecs from the given file; pass - to read from standard input

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

    when used with :pathspec_from_file, pathspecs are NUL-separated

Returns:

  • the new entry, or nil when there were no local changes to save

Raises:

  • if unsupported options are provided

  • if git exits with a non-zero exit status

See Also:

API:

  • private



138
139
140
141
142
143
144
145
# File 'lib/git/repository/stashing.rb', line 138

def stash_push(*pathspec)
  pathspec, opts = Private.split_pathspec_and_opts(pathspec)
  SharedPrivate.assert_valid_opts!(STASH_PUSH_ALLOWED_OPTS, **opts)
  previous_count = stash_infos.size
  Git::Commands::Stash::Push.new(@execution_context).call(*pathspec, **opts)
  entries = stash_infos
  entries.first if entries.size > previous_count
end

#stash_save(message) ⇒ Boolean

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.

Deprecated.

Use #stash_push with the :message option instead. It returns the new StashInfo, or nil when there were no local changes to save. This method will be removed in v6.0.0.

Save the current working directory and index state to a new stash

Examples:

Save current changes

repo.stash_save('WIP: feature work') #=> true

Parameters:

  • the stash message

Returns:

  • true if changes were stashed, false if there were no local changes to save

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



555
556
557
558
559
560
561
562
# File 'lib/git/repository/stashing.rb', line 555

def stash_save(message) # rubocop:disable Naming/PredicateMethod
  Git::Deprecation.warn(
    'Git::Repository#stash_save is deprecated and will be removed in v6.0.0. ' \
    'Use Git::Repository#stash_push(message: ...) instead.'
  )
  result = Git::Commands::Stash::Push.new(@execution_context).call(message: message)
  !result.stdout.include?('No local changes to save')
end

#stash_show(stash = nil, opts = {}) ⇒ String

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.

Show the changes recorded in a stash entry as a diff

Without options, git prints a diffstat. The output is returned as git prints it.

Examples:

Show the diffstat of the most recent entry

repo.stash_show #=> " file.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)"

Show the full patch of an entry from #stash_infos

repo.stash_show(repo.stash_infos.last, patch: true)

Parameters:

  • (defaults to: nil)

    the entry to show: a StashInfo, a stash@{N} name, an Integer N (0 is the most recent entry), or nil for the most recent entry

  • (defaults to: {})

    options for the show

Options Hash (opts):

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

    show the diff as a patch

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

    show per-file insertion and deletion counts

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

    show per-file mode, object id, and status metadata

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

    show only the summary line

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

    number of context lines in the patch (alias: :U)

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

    alias for :unified

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

    include the untracked files recorded in the entry (alias: :u; requires git 2.30+)

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

    alias for :include_untracked (requires git 2.30+)

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

    exclude the untracked files recorded in the entry (requires git 2.30+)

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

    show only the untracked files recorded in the entry (requires git 2.30+)

  • :find_renames (Boolean, Integer, nil) — default: nil

    detect renames, optionally with a similarity threshold (alias: :M)

  • :M (Boolean, Integer, nil) — default: nil

    alias for :find_renames

  • :find_copies (Boolean, Integer, nil) — default: nil

    detect copies as well as renames, optionally with a similarity threshold (alias: :C)

  • :C (Boolean, Integer, nil) — default: nil

    alias for :find_copies

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

    inspect unmodified files as copy sources

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

    number of context lines between hunks before they are merged

  • :dirstat (Boolean, String, nil) — default: nil

    include directory statistics, optionally with parameters

Returns:

  • git's stdout from the show

Raises:

  • if unsupported options are provided

  • if git exits with a non-zero exit status

See Also:

API:

  • private



345
346
347
348
349
# File 'lib/git/repository/stashing.rb', line 345

def stash_show(stash = nil, opts = {})
  stash, opts = Private.split_stash_and_opts(stash, opts)
  SharedPrivate.assert_valid_opts!(STASH_SHOW_ALLOWED_OPTS, **opts)
  Git::Commands::Stash::Show.new(@execution_context).call(stash, **opts).stdout
end

#stash_store(commit, opts = {}) ⇒ Git::StashInfo

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.

Add a stash commit created by #stash_create to the stash list

The stash list is read after the store to return the new top entry.

Examples:

Store a stash commit

oid = repo.stash_create
info = repo.stash_store(oid, message: 'saved for later')
info.name    #=> "stash@{0}"
info.message #=> "saved for later"

Parameters:

  • the object id of the stash commit to store

  • (defaults to: {})

    options for the store

Options Hash (opts):

  • :message (String) — default: nil

    the message for the stash entry (alias: :m)

  • :m (String) — default: nil

    alias for :message

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

    suppress informational messages (alias: :q)

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

    alias for :quiet

Returns:

  • the stored entry, now at the top of the stash list

Raises:

  • if unsupported options are provided

  • if git exits with a non-zero exit status

See Also:

API:

  • private



440
441
442
443
444
# File 'lib/git/repository/stashing.rb', line 440

def stash_store(commit, opts = {})
  SharedPrivate.assert_valid_opts!(STASH_STORE_ALLOWED_OPTS, **opts)
  Git::Commands::Stash::Store.new(@execution_context).call(commit, **opts)
  stash_infos.first
end

#stashes_allArray<Array(Integer, String)>

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.

Deprecated.

Use #stash_infos instead. It returns StashInfo entries newest first with git's own stash@{N} indices and the full message. This method will be removed in v6.0.0.

Note:

The sequential index returned here is not the same as git's stash@{N} reference used by #stash_apply. In git, stash@{0} is the most recent stash, while index 0 here is the oldest. To apply a specific stash from this list, convert the entry's position to a git reference: 'stash@{%d}' % (total - 1 - index), or pass the string reference directly to #stash_apply.

Returns all stash entries as an array of index and message pairs

Lists all stash entries in the repository ordered from oldest to newest. The index is a sequential number starting from 0 for the oldest stash. The message is the stash description with the leading branch prefix (e.g. "On main:" or "WIP on main:") stripped.

Examples:

List all stashes (oldest first)

repo.stashes_all #=> [[0, "Fix bug"], [1, "Add feature"]]

Returns:

  • array of [index, message] pairs where index is the sequential position (0 is oldest) and message is the stash description with the branch prefix stripped

Raises:

  • if git exits with a non-zero exit status

See Also:

API:

  • private



496
497
498
499
500
501
502
503
504
505
# File 'lib/git/repository/stashing.rb', line 496

def stashes_all
  Git::Deprecation.warn(
    'Git::Repository#stashes_all is deprecated and will be removed in v6.0.0. ' \
    'Use Git::Repository#stash_infos instead.'
  )
  stash_infos.reverse.each_with_index.map do |info, i|
    message = info.message.sub(/^(?:WIP on|On)\s+[^:]+:\s*/, '')
    [i, message]
  end
end