Module: Git

Extended by:
Configuring
Defined in:
lib/git.rb,
lib/git.rb,
lib/git/log.rb,
lib/git/url.rb,
lib/git/diff.rb,
lib/git/stash.rb,
lib/git/author.rb,
lib/git/branch.rb,
lib/git/config.rb,
lib/git/errors.rb,
lib/git/object.rb,
lib/git/remote.rb,
lib/git/status.rb,
lib/git/status.rb,
lib/git/status.rb,
lib/git/stashes.rb,
lib/git/version.rb,
lib/git/branches.rb,
lib/git/commands.rb,
lib/git/file_ref.rb,
lib/git/tag_info.rb,
lib/git/worktree.rb,
lib/git/diff_info.rb,
lib/git/worktrees.rb,
lib/git/diff_stats.rb,
lib/git/repository.rb,
lib/git/stash_info.rb,
lib/git/branch_info.rb,
lib/git/commands/am.rb,
lib/git/commands/gc.rb,
lib/git/commands/mv.rb,
lib/git/commands/rm.rb,
lib/git/configuring.rb,
lib/git/deprecation.rb,
lib/git/diff_result.rb,
lib/git/fsck_object.rb,
lib/git/fsck_result.rb,
lib/git/parsers/tag.rb,
lib/git/args_builder.rb,
lib/git/command_line.rb,
lib/git/commands/add.rb,
lib/git/commands/log.rb,
lib/git/commands/tag.rb,
lib/git/dirstat_info.rb,
lib/git/escaped_path.rb,
lib/git/parsers/diff.rb,
lib/git/parsers/fsck.rb,
lib/git/parsers/grep.rb,
lib/git/commands/base.rb,
lib/git/commands/diff.rb,
lib/git/commands/fsck.rb,
lib/git/commands/grep.rb,
lib/git/commands/init.rb,
lib/git/commands/pull.rb,
lib/git/commands/push.rb,
lib/git/commands/show.rb,
lib/git/parsers/stash.rb,
lib/git/commands/apply.rb,
lib/git/commands/clean.rb,
lib/git/commands/clone.rb,
lib/git/commands/fetch.rb,
lib/git/commands/merge.rb,
lib/git/commands/reset.rb,
lib/git/commands/stash.rb,
lib/git/encoding_utils.rb,
lib/git/parsers/branch.rb,
lib/git/commands/branch.rb,
lib/git/commands/commit.rb,
lib/git/commands/remote.rb,
lib/git/commands/repack.rb,
lib/git/commands/revert.rb,
lib/git/commands/status.rb,
lib/git/parsers/ls_tree.rb,
lib/git/commands/am/quit.rb,
lib/git/commands/am/skip.rb,
lib/git/commands/archive.rb,
lib/git/commands/ls_tree.rb,
lib/git/commands/version.rb,
lib/git/diff_path_status.rb,
lib/git/parsers/cat_file.rb,
lib/git/command_line/base.rb,
lib/git/commands/am/abort.rb,
lib/git/commands/am/apply.rb,
lib/git/commands/am/retry.rb,
lib/git/commands/cat_file.rb,
lib/git/commands/checkout.rb,
lib/git/commands/describe.rb,
lib/git/commands/ls_files.rb,
lib/git/commands/name_rev.rb,
lib/git/commands/show_ref.rb,
lib/git/commands/tag/list.rb,
lib/git/commands/worktree.rb,
lib/git/config_entry_info.rb,
lib/git/execution_context.rb,
lib/git/parsers/ls_remote.rb,
lib/git/tag_delete_result.rb,
lib/git/commands/arguments.rb,
lib/git/commands/ls_remote.rb,
lib/git/commands/read_tree.rb,
lib/git/commands/rev_parse.rb,
lib/git/commands/stash/pop.rb,
lib/git/detached_head_info.rb,
lib/git/diff_file_raw_info.rb,
lib/git/repository/diffing.rb,
lib/git/repository/logging.rb,
lib/git/repository/merging.rb,
lib/git/repository/staging.rb,
lib/git/tag_delete_failure.rb,
lib/git/version_constraint.rb,
lib/git/command_line/result.rb,
lib/git/command_line_result.rb,
lib/git/commands/diff_files.rb,
lib/git/commands/diff_index.rb,
lib/git/commands/merge/quit.rb,
lib/git/commands/merge_base.rb,
lib/git/commands/remote/add.rb,
lib/git/commands/stash/drop.rb,
lib/git/commands/stash/list.rb,
lib/git/commands/stash/push.rb,
lib/git/commands/stash/show.rb,
lib/git/commands/tag/create.rb,
lib/git/commands/tag/delete.rb,
lib/git/commands/tag/verify.rb,
lib/git/commands/update_ref.rb,
lib/git/commands/write_tree.rb,
lib/git/repository/stashing.rb,
lib/git/branch_delete_result.rb,
lib/git/commands/am/continue.rb,
lib/git/commands/branch/copy.rb,
lib/git/commands/branch/list.rb,
lib/git/commands/branch/move.rb,
lib/git/commands/commit_tree.rb,
lib/git/commands/maintenance.rb,
lib/git/commands/merge/abort.rb,
lib/git/commands/merge/start.rb,
lib/git/commands/remote/list.rb,
lib/git/commands/remote/show.rb,
lib/git/commands/revert/quit.rb,
lib/git/commands/revert/skip.rb,
lib/git/commands/stash/apply.rb,
lib/git/commands/stash/clear.rb,
lib/git/commands/stash/store.rb,
lib/git/diff_file_patch_info.rb,
lib/git/parsers/config_entry.rb,
lib/git/repository/branching.rb,
lib/git/repository/factories.rb,
lib/git/branch_delete_failure.rb,
lib/git/commands/cat_file/raw.rb,
lib/git/commands/remote/prune.rb,
lib/git/commands/revert/abort.rb,
lib/git/commands/revert/start.rb,
lib/git/commands/stash/branch.rb,
lib/git/commands/stash/create.rb,
lib/git/commands/symbolic_ref.rb,
lib/git/commands/worktree/add.rb,
lib/git/repository/committing.rb,
lib/git/repository/inspecting.rb,
lib/git/command_line/capturing.rb,
lib/git/command_line/streaming.rb,
lib/git/commands/branch/create.rb,
lib/git/commands/branch/delete.rb,
lib/git/commands/remote/remove.rb,
lib/git/commands/remote/rename.rb,
lib/git/commands/remote/update.rb,
lib/git/commands/show_ref/list.rb,
lib/git/commands/worktree/list.rb,
lib/git/commands/worktree/lock.rb,
lib/git/commands/worktree/move.rb,
lib/git/diff_file_numstat_info.rb,
lib/git/repository/configuring.rb,
lib/git/repository/maintenance.rb,
lib/git/commands/cat_file/batch.rb,
lib/git/commands/checkout/files.rb,
lib/git/commands/checkout_index.rb,
lib/git/commands/merge/continue.rb,
lib/git/commands/remote/get_url.rb,
lib/git/commands/remote/set_url.rb,
lib/git/commands/worktree/prune.rb,
lib/git/commands/checkout/branch.rb,
lib/git/commands/maintenance/run.rb,
lib/git/commands/remote/set_head.rb,
lib/git/commands/revert/continue.rb,
lib/git/commands/show_ref/exists.rb,
lib/git/commands/show_ref/verify.rb,
lib/git/commands/worktree/remove.rb,
lib/git/commands/worktree/repair.rb,
lib/git/commands/worktree/unlock.rb,
lib/git/execution_context/global.rb,
lib/git/repository/path_resolver.rb,
lib/git/commands/maintenance/stop.rb,
lib/git/commands/update_ref/batch.rb,
lib/git/repository/shared_private.rb,
lib/git/commands/cat_file/filtered.rb,
lib/git/commands/maintenance/start.rb,
lib/git/commands/symbolic_ref/read.rb,
lib/git/commands/update_ref/delete.rb,
lib/git/commands/update_ref/update.rb,
lib/git/repository/context_helpers.rb,
lib/git/commands/remote/set_url_add.rb,
lib/git/commands/branch/set_upstream.rb,
lib/git/commands/branch/show_current.rb,
lib/git/commands/remote/set_branches.rb,
lib/git/commands/symbolic_ref/delete.rb,
lib/git/commands/symbolic_ref/update.rb,
lib/git/execution_context/repository.rb,
lib/git/repository/object_operations.rb,
lib/git/repository/remote_operations.rb,
lib/git/repository/status_operations.rb,
lib/git/commands/archive/list_formats.rb,
lib/git/commands/config_option_syntax.rb,
lib/git/commands/maintenance/register.rb,
lib/git/commands/am/show_current_patch.rb,
lib/git/commands/branch/unset_upstream.rb,
lib/git/commands/remote/set_url_delete.rb,
lib/git/repository/worktree_operations.rb,
lib/git/commands/maintenance/unregister.rb,
lib/git/commands/config_option_syntax/add.rb,
lib/git/commands/config_option_syntax/get.rb,
lib/git/commands/config_option_syntax/set.rb,
lib/git/commands/worktree/management_base.rb,
lib/git/commands/config_option_syntax/list.rb,
lib/git/commands/show_ref/exclude_existing.rb,
lib/git/commands/config_option_syntax/unset.rb,
lib/git/commands/config_option_syntax/get_all.rb,
lib/git/commands/config_option_syntax/get_color.rb,
lib/git/commands/config_option_syntax/unset_all.rb,
lib/git/commands/config_option_syntax/get_regexp.rb,
lib/git/commands/config_option_syntax/replace_all.rb,
lib/git/commands/config_option_syntax/get_urlmatch.rb,
lib/git/commands/config_option_syntax/get_color_bool.rb,
lib/git/commands/config_option_syntax/remove_section.rb,
lib/git/commands/config_option_syntax/rename_section.rb

Overview

The Git module provides a Ruby interface to Git version control.

Defined Under Namespace

Modules: CommandLine, Commands, Configuring, EncodingUtils, Parsers Classes: ArgsBuilder, Author, Branch, BranchDeleteFailure, BranchDeleteResult, BranchInfo, Branches, CommandLineError, Config, ConfigEntryInfo, DetachedHeadInfo, Diff, DiffFileNumstatInfo, DiffFilePatchInfo, DiffFileRawInfo, DiffInfo, DiffPathStatus, DiffResult, DiffStats, DirstatEntry, DirstatInfo, Error, EscapedPath, ExecutionContext, FailedError, FileDiffInfo, FileRef, FsckObject, FsckResult, GitAltURI, Log, Object, ProcessIOError, Remote, Repository, SignaledError, Stash, StashInfo, Stashes, Status, TagDeleteFailure, TagDeleteResult, TagInfo, TimeoutError, URL, UnexpectedResultError, Version, VersionConstraint, VersionError, Worktree, Worktrees

Constant Summary collapse

MINIMUM_GIT_VERSION =

Minimum git version required by this gem

Commands and features may require newer versions, but this is the absolute minimum supported version for the gem as a whole.

Returns:

Version.parse('2.28.0')
GitExecuteError =
Deprecated.

Use Git::Error instead

An alias for Git::Error

Git::GitExecuteError error class is an alias for Git::Error for backwards compatibility. It is recommended to use Git::Error directly.

ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Git::GitExecuteError', 'Git::Error', Git::Deprecation)
VERSION =

The current gem version

Returns:

  • (String)

    the current gem version

'5.0.0.beta.2'
BRANCH_REFNAME_REGEXP =

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

Note:

This regex is similar to Git::Branch::BRANCH_NAME_REGEXP but uses \A/\z anchors instead of ^/$ for stricter matching. As part of the architectural redesign, Git::Branch will eventually be refactored to use BranchInfo internally, at which point this will become the single source of truth for branch name parsing.

Note:

This regex assumes remote names do not contain '/'. If a remote name contains '/', parsing will be incorrect. For example, 'remotes/team/upstream/main' would parse as remote_name='team' instead of 'team/upstream'. This is an inherent ambiguity in git refnames that can only be resolved with knowledge of configured remotes. See: https://github.com/ruby-git/ruby-git/issues/919

Regular expression for parsing branch refnames

Captures:

  • remote_name: the remote name (e.g., 'origin') for remote branches, nil for local
  • branch_name: the branch name without the remote prefix

Examples:

'main' => { remote_name: nil, branch_name: 'main' }
'remotes/origin/main' => { remote_name: 'origin', branch_name: 'main' }
'feature/foo' => { remote_name: nil, branch_name: 'feature/foo' }
'remotes/origin/feature/bar' => { remote_name: 'origin', branch_name: 'feature/bar' }
%r{
  \A                              # start of string
  (?:(?:refs/)?remotes/(?<remote_name>[^/]+)/)? # optional 'refs?/remotes/<remote_name>/'
  (?<branch_name>.+)                   # branch name (everything else)
  \z                              # end of string
}x
Deprecation =

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

ActiveSupport::Deprecation.new('5.0.0', 'Git')
CommandLineResult =

Backward-compatible alias for Git::CommandLine::Result

Git::CommandLine::Result

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Configuring

config_add, config_get, config_get_all, config_get_colorbool, config_get_regexp, config_get_urlmatch, config_list, config_remove_section, config_rename_section, config_replace_all, config_set, config_unset, config_unset_all

Instance Attribute Details

#author_dateString (readonly)

Returns the author date in ISO 8601 format.

Returns:

  • (String)

    the author date in ISO 8601 format



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#author_emailString (readonly)

Returns the email of the stash author.

Returns:

  • (String)

    the email of the stash author



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#author_nameString (readonly)

Returns the name of the stash author.

Returns:

  • (String)

    the name of the stash author



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#binaryBoolean (readonly)

Returns whether this is a binary file.

Returns:

  • (Boolean)

    whether this is a binary file



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/git/diff_info.rb', line 45

FileDiffInfo = Data.define(
  :path,
  :patch,
  :mode,
  :src,
  :dst,
  :type,
  :binary
) do
  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end
end

#branchString? (readonly)

Returns the branch name where the stash was created, or nil for custom stash messages.

Returns:

  • (String, nil)

    the branch name where the stash was created, or nil for custom stash messages



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#committer_dateString (readonly)

Returns the committer date in ISO 8601 format.

Returns:

  • (String)

    the committer date in ISO 8601 format



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#committer_emailString (readonly)

Returns the email of the stash committer.

Returns:

  • (String)

    the email of the stash committer



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#committer_nameString (readonly)

Returns the name of the stash committer.

Returns:

  • (String)

    the name of the stash committer



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#currentBoolean (readonly)

Whether this branch is currently checked out in the current worktree

Returns:

  • (Boolean)

    true if this is the current branch



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/git/branch_info.rb', line 133

BranchInfo = Data.define(:refname, :target_oid, :current, :worktree, :symref, :upstream) do
  # @return [Boolean] always false for BranchInfo (see DetachedHeadInfo for detached state)
  def detached? = false

  # @return [Boolean] true if this is an unborn branch (no commits yet)
  def unborn? = target_oid.nil?

  # @return [Boolean] true if this is the currently checked out branch
  def current? = current

  # @return [Boolean] true if this branch is checked out in another worktree
  def worktree? = worktree

  # @return [Boolean] true if this is a symbolic reference
  def symref? = !symref.nil?

  # @return [Boolean] true if this is a remote-tracking branch
  def remote? = !remote_name.nil?

  # @return [String, nil] the name of the remote (e.g., 'origin'), or nil for local branches
  def remote_name
    parse_refname[:remote_name]
  end

  # @return [String] the branch name without remote prefix (e.g., 'main' or 'feature/foo')
  def short_name
    parse_refname[:branch_name]
  end

  # @return [String] string representation (the full refname)
  def to_s = refname

  private

  # Parse the refname and return match data
  #
  # The regex is guaranteed to match any non-empty string due to the `.+` pattern,
  # so we don't need nil checking. If refname is empty/nil, this would fail at
  # object creation time since refname is a required attribute.
  #
  # @return [MatchData] the match result
  def parse_refname
    refname.match(Git::BRANCH_REFNAME_REGEXP)
  end
end

#deletedArray<Git::BranchInfo> (readonly)

Branches that were successfully deleted

Returns:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/git/tag_delete_result.rb', line 45

TagDeleteResult = Data.define(:deleted, :not_deleted) do
  # Returns true if all requested tags were successfully deleted
  #
  # @return [Boolean] true if no tags failed to delete, false otherwise
  #
  # @example
  #   result = tag_delete.call('v1.0.0')
  #   if result.success?
  #     puts "All tags deleted successfully"
  #   else
  #     puts "Some tags could not be deleted:"
  #     result.not_deleted.each { |f| puts "  #{f.name}: #{f.error_message}" }
  #   end
  #
  def success?
    not_deleted.empty?
  end
end

#deletionsInteger (readonly)

Returns number of lines deleted.

Returns:

  • (Integer)

    number of lines deleted



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/git/diff_file_raw_info.rb', line 67

DiffFileRawInfo = Data.define(:src, :dst, :status, :similarity, :insertions, :deletions, :binary) do
  # Get the primary file path
  #
  # Returns the destination path if it exists, otherwise the source path.
  # This is the "current" or "canonical" path for the file.
  #
  # @return [String] the file path
  #
  def path
    dst&.path || src&.path
  end

  # Get the source path (for renames/copies)
  #
  # @return [String, nil] the source path, or nil if file was added
  #
  def src_path
    src&.path
  end

  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end

  # Check if this file was renamed
  #
  # @return [Boolean]
  #
  def renamed?
    status == :renamed
  end

  # Check if this file was copied
  #
  # @return [Boolean]
  #
  def copied?
    status == :copied
  end

  # Check if this file was added
  #
  # @return [Boolean]
  #
  def added?
    status == :added
  end

  # Check if this file was deleted
  #
  # @return [Boolean]
  #
  def deleted?
    status == :deleted
  end
end

#directoryString (readonly)

Returns the directory path (always ends with '/').

Returns:

  • (String)

    the directory path (always ends with '/')



19
# File 'lib/git/dirstat_info.rb', line 19

DirstatEntry = Data.define(:directory, :percentage)

#dirstatDirstatInfo? (readonly)

Returns directory statistics if requested, nil otherwise.

Returns:

  • (DirstatInfo, nil)

    directory statistics if requested, nil otherwise



31
# File 'lib/git/diff_result.rb', line 31

DiffResult = Data.define(:files_changed, :total_insertions, :total_deletions, :files, :dirstat)

#dstFileRef? (readonly)

Returns the destination file reference, or nil for deleted files.

Returns:

  • (FileRef, nil)

    the destination file reference, or nil for deleted files



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/git/diff_info.rb', line 45

FileDiffInfo = Data.define(
  :path,
  :patch,
  :mode,
  :src,
  :dst,
  :type,
  :binary
) do
  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end
end

#entriesArray<DirstatEntry> (readonly)

Returns directory statistics in order from git output.

Returns:

  • (Array<DirstatEntry>)

    directory statistics in order from git output



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/git/dirstat_info.rb', line 41

DirstatInfo = Data.define(:entries) do
  # Look up percentage by directory path
  #
  # @param directory [String] the directory path
  # @return [Float, nil] the percentage or nil if not found
  #
  def [](directory)
    entries.find { |e| e.directory == directory }&.percentage
  end

  # Convert to a Hash mapping directory to percentage
  #
  # @return [Hash<String, Float>]
  #
  def to_h
    entries.to_h { |e| [e.directory, e.percentage] }
  end

  # Number of directories in the dirstat
  #
  # @return [Integer]
  #
  def size
    entries.size
  end

  # Check if dirstat is empty
  #
  # @return [Boolean]
  #
  def empty?
    entries.empty?
  end

  # Iterate over entries
  #
  # @yield [DirstatEntry] each entry
  # @return [Enumerator] if no block given
  #
  def each(&block)
    entries.each(&block)
  end

  include Enumerable
end

#error_messageString (readonly)

The error message from git explaining why the branch could not be deleted

Returns:

  • (String)


30
# File 'lib/git/tag_delete_failure.rb', line 30

TagDeleteFailure = Data.define(:name, :error_message)

#file_patchesArray<FileDiffInfo> (readonly)

Returns array of file diff info objects (empty if patch not requested).

Returns:

  • (Array<FileDiffInfo>)

    array of file diff info objects (empty if patch not requested)



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/git/diff_info.rb', line 99

DiffInfo = Data.define(:stats, :file_patches) do
  # @!method insertions
  #   @return [Integer] total number of lines inserted

  # @!method deletions
  #   @return [Integer] total number of lines deleted

  # @!method lines
  #   @return [Integer] total number of lines changed (insertions + deletions)

  # @!method file_count
  #   @return [Integer] number of files changed

  # Total number of lines inserted
  #
  # @return [Integer]
  #
  def insertions
    stats[:total][:insertions]
  end

  # Total number of lines deleted
  #
  # @return [Integer]
  #
  def deletions
    stats[:total][:deletions]
  end

  # Total number of lines changed (insertions + deletions)
  #
  # @return [Integer]
  #
  def lines
    stats[:total][:lines]
  end

  # Number of files changed
  #
  # @return [Integer]
  #
  def file_count
    stats[:total][:files]
  end

  # Per-file statistics hash
  #
  # @return [Hash<String, Hash>] mapping file paths to `{ insertions:, deletions: }` hashes
  #
  def file_stats
    stats[:files]
  end

  # Check if patch information is available
  #
  # @return [Boolean] true if file_patches were loaded
  #
  def patches?
    !file_patches.empty?
  end

  # Get patch info for a specific file
  #
  # @param path [String] the file path
  # @return [FileDiffInfo, nil] the diff info or nil if not found
  #
  def patch_for(path)
    file_patches.find { |p| p.path == path }
  end
end

#filesArray<DiffFileNumstatInfo, DiffFileRawInfo, DiffFilePatchInfo> (readonly)

Returns per-file information.

Returns:



31
# File 'lib/git/diff_result.rb', line 31

DiffResult = Data.define(:files_changed, :total_insertions, :total_deletions, :files, :dirstat)

#files_changedInteger (readonly)

Returns number of files changed (from --shortstat).

Returns:

  • (Integer)

    number of files changed (from --shortstat)



31
# File 'lib/git/diff_result.rb', line 31

DiffResult = Data.define(:files_changed, :total_insertions, :total_deletions, :files, :dirstat)

#indexInteger (readonly)

Returns the stash index (0, 1, 2, ...).

Returns:

  • (Integer)

    the stash index (0, 1, 2, ...)



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#insertionsInteger (readonly)

Returns number of lines inserted.

Returns:

  • (Integer)

    number of lines inserted



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/git/diff_file_raw_info.rb', line 67

DiffFileRawInfo = Data.define(:src, :dst, :status, :similarity, :insertions, :deletions, :binary) do
  # Get the primary file path
  #
  # Returns the destination path if it exists, otherwise the source path.
  # This is the "current" or "canonical" path for the file.
  #
  # @return [String] the file path
  #
  def path
    dst&.path || src&.path
  end

  # Get the source path (for renames/copies)
  #
  # @return [String, nil] the source path, or nil if file was added
  #
  def src_path
    src&.path
  end

  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end

  # Check if this file was renamed
  #
  # @return [Boolean]
  #
  def renamed?
    status == :renamed
  end

  # Check if this file was copied
  #
  # @return [Boolean]
  #
  def copied?
    status == :copied
  end

  # Check if this file was added
  #
  # @return [Boolean]
  #
  def added?
    status == :added
  end

  # Check if this file was deleted
  #
  # @return [Boolean]
  #
  def deleted?
    status == :deleted
  end
end

#keyString (readonly)

The full dotted key name of the configuration entry (e.g., remote.origin.url)

Returns:

  • (String)

    the full dotted key name (e.g. remote.origin.url)



58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/git/config_entry_info.rb', line 58

ConfigEntryInfo = Data.define(:scope, :origin, :key, :value) do
  # Returns the section component of the key (everything before the first dot)
  #
  # Returns an empty string when the key contains no dot.
  #
  # @example Section component of a dotted key
  #   entry.section # => "remote"
  #
  # @return [String] the section name, or an empty string when the key has no dot
  #
  def section = first_dot ? key[0...first_dot] : ''

  # Returns the subsection component of the key (everything between the first and last dot)
  #
  # Returns an empty string when the key has zero or one dot (no subsection).
  #
  # @example Subsection component of a dotted key
  #   entry.subsection # => "origin"
  #
  # @return [String] the subsection name, or an empty string when there is no subsection
  #
  def subsection = first_dot && first_dot != last_dot ? key[(first_dot + 1)...last_dot] : ''

  # Returns the variable component of the key (everything after the last dot)
  #
  # Returns the full key when the key contains no dot.
  #
  # @example Variable component of a dotted key
  #   entry.variable # => "url"
  #
  # @return [String] the variable name (everything after the last dot)
  #
  def variable = last_dot ? key[(last_dot + 1)..] : key

  private

  # Returns the index of the first dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the first dot, or `nil`
  #
  def first_dot = key.index('.')

  # Returns the index of the last dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the last dot, or `nil`
  #
  def last_dot = key.rindex('.')
end

#majorInteger (readonly)

The major version number

Returns:

  • (Integer)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/git/version.rb', line 43

Version = Data.define(:major, :minor, :patch) do
  include Comparable

  # Parse a version string into a Version object
  #
  # Handles git's version output format, stripping platform suffixes
  # (like `.windows.1` or `.vfs.0`) and padding two-segment versions
  # to three segments.
  #
  # @example Parse various version string formats
  #   Git::Version.parse('2.42.1')  #=> Git::Version.new(2, 42, 1)
  #   Git::Version.parse('git version 2.42.1')  #=> Git::Version.new(2, 42, 1)
  #   Git::Version.parse('2.42.0.windows.1')  #=> Git::Version.new(2, 42, 0)
  #
  # @param string [String] version string to parse
  #
  # @return [Git::Version] the parsed version
  #
  # @raise [Git::UnexpectedResultError] if the string cannot be parsed as a version
  #
  def self.parse(string)
    version_match = string&.match(/(\d+)\.(\d+)(?:\.(\d+))?/)
    raise Git::UnexpectedResultError, "Invalid version: #{string.inspect}" unless version_match

    major = version_match[1].to_i
    minor = version_match[2].to_i
    patch = (version_match[3] || '0').to_i

    new(major, minor, patch)
  end

  # Compare this version to another
  #
  # @param other [Git::Version] the version to compare to
  #
  # @return [Integer] -1, 0, or 1
  #
  def <=>(other)
    [major, minor, patch] <=> [other.major, other.minor, other.patch]
  end

  # Return the version as a dotted string
  #
  # @return [String] the version in "major.minor.patch" format
  #
  def to_s
    "#{major}.#{minor}.#{patch}"
  end

  # Return a readable representation
  #
  # @return [String] inspect string
  #
  def inspect
    "#<Git::Version #{self}>"
  end

  # Return the version as an array of integers
  #
  # Useful when legacy code expects the array shape returned by the
  # deprecated `Git::Lib#current_command_version` method.
  #
  # @return [Array<Integer>] [major, minor, patch]
  #
  # @example
  #   Git.git_version.to_a  #=> [2, 42, 0]
  #
  def to_a
    deconstruct
  end
end

#messageString (readonly)

Returns the stash message (e.g., 'WIP on main: abc123 commit msg').

Returns:

  • (String)

    the stash message (e.g., 'WIP on main: abc123 commit msg')



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#minorInteger (readonly)

The minor version number

Returns:

  • (Integer)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/git/version.rb', line 43

Version = Data.define(:major, :minor, :patch) do
  include Comparable

  # Parse a version string into a Version object
  #
  # Handles git's version output format, stripping platform suffixes
  # (like `.windows.1` or `.vfs.0`) and padding two-segment versions
  # to three segments.
  #
  # @example Parse various version string formats
  #   Git::Version.parse('2.42.1')  #=> Git::Version.new(2, 42, 1)
  #   Git::Version.parse('git version 2.42.1')  #=> Git::Version.new(2, 42, 1)
  #   Git::Version.parse('2.42.0.windows.1')  #=> Git::Version.new(2, 42, 0)
  #
  # @param string [String] version string to parse
  #
  # @return [Git::Version] the parsed version
  #
  # @raise [Git::UnexpectedResultError] if the string cannot be parsed as a version
  #
  def self.parse(string)
    version_match = string&.match(/(\d+)\.(\d+)(?:\.(\d+))?/)
    raise Git::UnexpectedResultError, "Invalid version: #{string.inspect}" unless version_match

    major = version_match[1].to_i
    minor = version_match[2].to_i
    patch = (version_match[3] || '0').to_i

    new(major, minor, patch)
  end

  # Compare this version to another
  #
  # @param other [Git::Version] the version to compare to
  #
  # @return [Integer] -1, 0, or 1
  #
  def <=>(other)
    [major, minor, patch] <=> [other.major, other.minor, other.patch]
  end

  # Return the version as a dotted string
  #
  # @return [String] the version in "major.minor.patch" format
  #
  def to_s
    "#{major}.#{minor}.#{patch}"
  end

  # Return a readable representation
  #
  # @return [String] inspect string
  #
  def inspect
    "#<Git::Version #{self}>"
  end

  # Return the version as an array of integers
  #
  # Useful when legacy code expects the array shape returned by the
  # deprecated `Git::Lib#current_command_version` method.
  #
  # @return [Array<Integer>] [major, minor, patch]
  #
  # @example
  #   Git.git_version.to_a  #=> [2, 42, 0]
  #
  def to_a
    deconstruct
  end
end

#modeString (readonly)

Returns the file mode (e.g., '100644' for regular files).

Returns:

  • (String)

    the file mode (e.g., '100644' for regular files)



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/git/file_ref.rb', line 33

FileRef = Data.define(:mode, :sha, :path) do
  # Check if this is a regular file (not executable, symlink, etc.)
  #
  # @return [Boolean] true if mode is 100644
  #
  def regular_file?
    mode == '100644'
  end

  # Check if this is an executable file
  #
  # @return [Boolean] true if mode is 100755
  #
  def executable?
    mode == '100755'
  end

  # Check if this is a symbolic link
  #
  # @return [Boolean] true if mode is 120000
  #
  def symlink?
    mode == '120000'
  end

  # Return the mode as an integer (parsed as octal)
  #
  # Useful for bit operations on file permissions.
  #
  # @return [Integer] the mode as an integer
  #
  # @example Check file permissions
  #   ref.mode_bits & 0o777  # => 0o644 (420 decimal)
  #
  # @example Check if group writable
  #   (ref.mode_bits & 0o020) != 0
  #
  def mode_bits
    mode.to_i(8)
  end
end

#nameString (readonly)

The name of the branch that failed to be deleted

Returns:

  • (String)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#not_deletedArray<Git::BranchDeleteFailure> (readonly)

Branches that could not be deleted, with the reason for each failure

Returns:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/git/tag_delete_result.rb', line 45

TagDeleteResult = Data.define(:deleted, :not_deleted) do
  # Returns true if all requested tags were successfully deleted
  #
  # @return [Boolean] true if no tags failed to delete, false otherwise
  #
  # @example
  #   result = tag_delete.call('v1.0.0')
  #   if result.success?
  #     puts "All tags deleted successfully"
  #   else
  #     puts "Some tags could not be deleted:"
  #     result.not_deleted.each { |f| puts "  #{f.name}: #{f.error_message}" }
  #   end
  #
  def success?
    not_deleted.empty?
  end
end

#objecttypeString (readonly)

Returns 'tag' for annotated tags, 'commit' for lightweight tags.

Returns:

  • (String)

    'tag' for annotated tags, 'commit' for lightweight tags



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#oidString (readonly)

Returns the full 40-character object identifier of the stash.

Returns:

  • (String)

    the full 40-character object identifier of the stash



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#originString? (readonly)

Where the configuration entry originates

The origin is in the format <origin-type>:<actual-origin> and is never blank. The origin type prefix is one of file:, blob:, command line:, or standard input:.

nil when the git command used to retrieve this entry does not support --show-origin (currently only --get-urlmatch).

Returns:

  • (String, nil)

    the origin path in the format <type>:<path>, or nil



58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/git/config_entry_info.rb', line 58

ConfigEntryInfo = Data.define(:scope, :origin, :key, :value) do
  # Returns the section component of the key (everything before the first dot)
  #
  # Returns an empty string when the key contains no dot.
  #
  # @example Section component of a dotted key
  #   entry.section # => "remote"
  #
  # @return [String] the section name, or an empty string when the key has no dot
  #
  def section = first_dot ? key[0...first_dot] : ''

  # Returns the subsection component of the key (everything between the first and last dot)
  #
  # Returns an empty string when the key has zero or one dot (no subsection).
  #
  # @example Subsection component of a dotted key
  #   entry.subsection # => "origin"
  #
  # @return [String] the subsection name, or an empty string when there is no subsection
  #
  def subsection = first_dot && first_dot != last_dot ? key[(first_dot + 1)...last_dot] : ''

  # Returns the variable component of the key (everything after the last dot)
  #
  # Returns the full key when the key contains no dot.
  #
  # @example Variable component of a dotted key
  #   entry.variable # => "url"
  #
  # @return [String] the variable name (everything after the last dot)
  #
  def variable = last_dot ? key[(last_dot + 1)..] : key

  private

  # Returns the index of the first dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the first dot, or `nil`
  #
  def first_dot = key.index('.')

  # Returns the index of the last dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the last dot, or `nil`
  #
  def last_dot = key.rindex('.')
end

#patchString (readonly)

Returns the full unified diff patch text for this file.

Returns:

  • (String)

    the full unified diff patch text for this file



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/git/version.rb', line 43

Version = Data.define(:major, :minor, :patch) do
  include Comparable

  # Parse a version string into a Version object
  #
  # Handles git's version output format, stripping platform suffixes
  # (like `.windows.1` or `.vfs.0`) and padding two-segment versions
  # to three segments.
  #
  # @example Parse various version string formats
  #   Git::Version.parse('2.42.1')  #=> Git::Version.new(2, 42, 1)
  #   Git::Version.parse('git version 2.42.1')  #=> Git::Version.new(2, 42, 1)
  #   Git::Version.parse('2.42.0.windows.1')  #=> Git::Version.new(2, 42, 0)
  #
  # @param string [String] version string to parse
  #
  # @return [Git::Version] the parsed version
  #
  # @raise [Git::UnexpectedResultError] if the string cannot be parsed as a version
  #
  def self.parse(string)
    version_match = string&.match(/(\d+)\.(\d+)(?:\.(\d+))?/)
    raise Git::UnexpectedResultError, "Invalid version: #{string.inspect}" unless version_match

    major = version_match[1].to_i
    minor = version_match[2].to_i
    patch = (version_match[3] || '0').to_i

    new(major, minor, patch)
  end

  # Compare this version to another
  #
  # @param other [Git::Version] the version to compare to
  #
  # @return [Integer] -1, 0, or 1
  #
  def <=>(other)
    [major, minor, patch] <=> [other.major, other.minor, other.patch]
  end

  # Return the version as a dotted string
  #
  # @return [String] the version in "major.minor.patch" format
  #
  def to_s
    "#{major}.#{minor}.#{patch}"
  end

  # Return a readable representation
  #
  # @return [String] inspect string
  #
  def inspect
    "#<Git::Version #{self}>"
  end

  # Return the version as an array of integers
  #
  # Useful when legacy code expects the array shape returned by the
  # deprecated `Git::Lib#current_command_version` method.
  #
  # @return [Array<Integer>] [major, minor, patch]
  #
  # @example
  #   Git.git_version.to_a  #=> [2, 42, 0]
  #
  def to_a
    deconstruct
  end
end

#pathString (readonly)

Returns the file path (destination path for renames).

Returns:

  • (String)

    the file path (destination path for renames)



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/git/file_ref.rb', line 33

FileRef = Data.define(:mode, :sha, :path) do
  # Check if this is a regular file (not executable, symlink, etc.)
  #
  # @return [Boolean] true if mode is 100644
  #
  def regular_file?
    mode == '100644'
  end

  # Check if this is an executable file
  #
  # @return [Boolean] true if mode is 100755
  #
  def executable?
    mode == '100755'
  end

  # Check if this is a symbolic link
  #
  # @return [Boolean] true if mode is 120000
  #
  def symlink?
    mode == '120000'
  end

  # Return the mode as an integer (parsed as octal)
  #
  # Useful for bit operations on file permissions.
  #
  # @return [Integer] the mode as an integer
  #
  # @example Check file permissions
  #   ref.mode_bits & 0o777  # => 0o644 (420 decimal)
  #
  # @example Check if group writable
  #   (ref.mode_bits & 0o020) != 0
  #
  def mode_bits
    mode.to_i(8)
  end
end

#percentageFloat (readonly)

Returns the percentage of changes in this directory (0.0-100.0).

Returns:

  • (Float)

    the percentage of changes in this directory (0.0-100.0)



19
# File 'lib/git/dirstat_info.rb', line 19

DirstatEntry = Data.define(:directory, :percentage)

#refnameString (readonly)

The full reference name of the branch

Returns:

  • (String)

    the branch refname (e.g., 'main', 'remotes/origin/main')



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/git/branch_info.rb', line 133

BranchInfo = Data.define(:refname, :target_oid, :current, :worktree, :symref, :upstream) do
  # @return [Boolean] always false for BranchInfo (see DetachedHeadInfo for detached state)
  def detached? = false

  # @return [Boolean] true if this is an unborn branch (no commits yet)
  def unborn? = target_oid.nil?

  # @return [Boolean] true if this is the currently checked out branch
  def current? = current

  # @return [Boolean] true if this branch is checked out in another worktree
  def worktree? = worktree

  # @return [Boolean] true if this is a symbolic reference
  def symref? = !symref.nil?

  # @return [Boolean] true if this is a remote-tracking branch
  def remote? = !remote_name.nil?

  # @return [String, nil] the name of the remote (e.g., 'origin'), or nil for local branches
  def remote_name
    parse_refname[:remote_name]
  end

  # @return [String] the branch name without remote prefix (e.g., 'main' or 'feature/foo')
  def short_name
    parse_refname[:branch_name]
  end

  # @return [String] string representation (the full refname)
  def to_s = refname

  private

  # Parse the refname and return match data
  #
  # The regex is guaranteed to match any non-empty string due to the `.+` pattern,
  # so we don't need nil checking. If refname is empty/nil, this would fail at
  # object creation time since refname is a required attribute.
  #
  # @return [MatchData] the match result
  def parse_refname
    refname.match(Git::BRANCH_REFNAME_REGEXP)
  end
end

#scopeString (readonly)

The scope of the configuration entry

May be one of "system", "global", "local", "worktree", "command", "file", or "blob". The "command" scope is used for values supplied via the command line (including default values from --default).

Returns:

  • (String)

    the config scope string (e.g. "local", "global")



58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/git/config_entry_info.rb', line 58

ConfigEntryInfo = Data.define(:scope, :origin, :key, :value) do
  # Returns the section component of the key (everything before the first dot)
  #
  # Returns an empty string when the key contains no dot.
  #
  # @example Section component of a dotted key
  #   entry.section # => "remote"
  #
  # @return [String] the section name, or an empty string when the key has no dot
  #
  def section = first_dot ? key[0...first_dot] : ''

  # Returns the subsection component of the key (everything between the first and last dot)
  #
  # Returns an empty string when the key has zero or one dot (no subsection).
  #
  # @example Subsection component of a dotted key
  #   entry.subsection # => "origin"
  #
  # @return [String] the subsection name, or an empty string when there is no subsection
  #
  def subsection = first_dot && first_dot != last_dot ? key[(first_dot + 1)...last_dot] : ''

  # Returns the variable component of the key (everything after the last dot)
  #
  # Returns the full key when the key contains no dot.
  #
  # @example Variable component of a dotted key
  #   entry.variable # => "url"
  #
  # @return [String] the variable name (everything after the last dot)
  #
  def variable = last_dot ? key[(last_dot + 1)..] : key

  private

  # Returns the index of the first dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the first dot, or `nil`
  #
  def first_dot = key.index('.')

  # Returns the index of the last dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the last dot, or `nil`
  #
  def last_dot = key.rindex('.')
end

#shaString (readonly)

Returns the blob SHA (object identifier).

Returns:

  • (String)

    the blob SHA (object identifier)



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/git/file_ref.rb', line 33

FileRef = Data.define(:mode, :sha, :path) do
  # Check if this is a regular file (not executable, symlink, etc.)
  #
  # @return [Boolean] true if mode is 100644
  #
  def regular_file?
    mode == '100644'
  end

  # Check if this is an executable file
  #
  # @return [Boolean] true if mode is 100755
  #
  def executable?
    mode == '100755'
  end

  # Check if this is a symbolic link
  #
  # @return [Boolean] true if mode is 120000
  #
  def symlink?
    mode == '120000'
  end

  # Return the mode as an integer (parsed as octal)
  #
  # Useful for bit operations on file permissions.
  #
  # @return [Integer] the mode as an integer
  #
  # @example Check file permissions
  #   ref.mode_bits & 0o777  # => 0o644 (420 decimal)
  #
  # @example Check if group writable
  #   (ref.mode_bits & 0o020) != 0
  #
  def mode_bits
    mode.to_i(8)
  end
end

#short_oidString (readonly)

Returns the abbreviated object identifier (typically 7 characters).

Returns:

  • (String)

    the abbreviated object identifier (typically 7 characters)



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/git/stash_info.rb', line 79

StashInfo = Data.define(
  :index,
  :name,
  :oid,
  :short_oid,
  :branch,
  :message,
  :author_name,
  :author_email,
  :author_date,
  :committer_name,
  :committer_email,
  :committer_date
) do
  # Returns the stash reference name
  #
  # @return [String] the stash name (e.g., 'stash@\\{0}')
  #
  # @example
  #   info.to_s # => 'stash@{0}'
  #
  def to_s
    name
  end
end

#similarityInteger? (readonly)

Returns similarity percentage for renames/copies (0-100), nil otherwise.

Returns:

  • (Integer, nil)

    similarity percentage for renames/copies (0-100), nil otherwise



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/git/diff_file_raw_info.rb', line 67

DiffFileRawInfo = Data.define(:src, :dst, :status, :similarity, :insertions, :deletions, :binary) do
  # Get the primary file path
  #
  # Returns the destination path if it exists, otherwise the source path.
  # This is the "current" or "canonical" path for the file.
  #
  # @return [String] the file path
  #
  def path
    dst&.path || src&.path
  end

  # Get the source path (for renames/copies)
  #
  # @return [String, nil] the source path, or nil if file was added
  #
  def src_path
    src&.path
  end

  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end

  # Check if this file was renamed
  #
  # @return [Boolean]
  #
  def renamed?
    status == :renamed
  end

  # Check if this file was copied
  #
  # @return [Boolean]
  #
  def copied?
    status == :copied
  end

  # Check if this file was added
  #
  # @return [Boolean]
  #
  def added?
    status == :added
  end

  # Check if this file was deleted
  #
  # @return [Boolean]
  #
  def deleted?
    status == :deleted
  end
end

#srcFileRef? (readonly)

Returns the source file reference, or nil for new/added files.

Returns:

  • (FileRef, nil)

    the source file reference, or nil for new/added files



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/git/diff_info.rb', line 45

FileDiffInfo = Data.define(
  :path,
  :patch,
  :mode,
  :src,
  :dst,
  :type,
  :binary
) do
  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end
end

#src_pathString? (readonly)

Returns the source path for renamed files, nil otherwise.

Returns:

  • (String, nil)

    the source path for renamed files, nil otherwise



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

DiffFileNumstatInfo = Data.define(:path, :src_path, :insertions, :deletions) do
  # Check if this file was renamed
  #
  # @return [Boolean] true if the file was renamed
  #
  def renamed?
    !src_path.nil?
  end
end

#statsHash (readonly)

Returns the statistics hash with :total and :files keys.

Returns:

  • (Hash)

    the statistics hash with :total and :files keys



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/git/diff_info.rb', line 99

DiffInfo = Data.define(:stats, :file_patches) do
  # @!method insertions
  #   @return [Integer] total number of lines inserted

  # @!method deletions
  #   @return [Integer] total number of lines deleted

  # @!method lines
  #   @return [Integer] total number of lines changed (insertions + deletions)

  # @!method file_count
  #   @return [Integer] number of files changed

  # Total number of lines inserted
  #
  # @return [Integer]
  #
  def insertions
    stats[:total][:insertions]
  end

  # Total number of lines deleted
  #
  # @return [Integer]
  #
  def deletions
    stats[:total][:deletions]
  end

  # Total number of lines changed (insertions + deletions)
  #
  # @return [Integer]
  #
  def lines
    stats[:total][:lines]
  end

  # Number of files changed
  #
  # @return [Integer]
  #
  def file_count
    stats[:total][:files]
  end

  # Per-file statistics hash
  #
  # @return [Hash<String, Hash>] mapping file paths to `{ insertions:, deletions: }` hashes
  #
  def file_stats
    stats[:files]
  end

  # Check if patch information is available
  #
  # @return [Boolean] true if file_patches were loaded
  #
  def patches?
    !file_patches.empty?
  end

  # Get patch info for a specific file
  #
  # @param path [String] the file path
  # @return [FileDiffInfo, nil] the diff info or nil if not found
  #
  def patch_for(path)
    file_patches.find { |p| p.path == path }
  end
end

#statusSymbol (readonly)

Returns the change status (:added, :modified, :deleted, :renamed, :copied, :type_changed).

Returns:

  • (Symbol)

    the change status (:added, :modified, :deleted, :renamed, :copied, :type_changed)



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/git/diff_file_raw_info.rb', line 67

DiffFileRawInfo = Data.define(:src, :dst, :status, :similarity, :insertions, :deletions, :binary) do
  # Get the primary file path
  #
  # Returns the destination path if it exists, otherwise the source path.
  # This is the "current" or "canonical" path for the file.
  #
  # @return [String] the file path
  #
  def path
    dst&.path || src&.path
  end

  # Get the source path (for renames/copies)
  #
  # @return [String, nil] the source path, or nil if file was added
  #
  def src_path
    src&.path
  end

  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end

  # Check if this file was renamed
  #
  # @return [Boolean]
  #
  def renamed?
    status == :renamed
  end

  # Check if this file was copied
  #
  # @return [Boolean]
  #
  def copied?
    status == :copied
  end

  # Check if this file was added
  #
  # @return [Boolean]
  #
  def added?
    status == :added
  end

  # Check if this file was deleted
  #
  # @return [Boolean]
  #
  def deleted?
    status == :deleted
  end
end

#symrefString? (readonly)

The target reference if this is a symbolic reference

Returns:

  • (String, nil)

    the target ref (e.g., 'refs/heads/main'), or nil if not a symref



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/git/branch_info.rb', line 133

BranchInfo = Data.define(:refname, :target_oid, :current, :worktree, :symref, :upstream) do
  # @return [Boolean] always false for BranchInfo (see DetachedHeadInfo for detached state)
  def detached? = false

  # @return [Boolean] true if this is an unborn branch (no commits yet)
  def unborn? = target_oid.nil?

  # @return [Boolean] true if this is the currently checked out branch
  def current? = current

  # @return [Boolean] true if this branch is checked out in another worktree
  def worktree? = worktree

  # @return [Boolean] true if this is a symbolic reference
  def symref? = !symref.nil?

  # @return [Boolean] true if this is a remote-tracking branch
  def remote? = !remote_name.nil?

  # @return [String, nil] the name of the remote (e.g., 'origin'), or nil for local branches
  def remote_name
    parse_refname[:remote_name]
  end

  # @return [String] the branch name without remote prefix (e.g., 'main' or 'feature/foo')
  def short_name
    parse_refname[:branch_name]
  end

  # @return [String] string representation (the full refname)
  def to_s = refname

  private

  # Parse the refname and return match data
  #
  # The regex is guaranteed to match any non-empty string due to the `.+` pattern,
  # so we don't need nil checking. If refname is empty/nil, this would fail at
  # object creation time since refname is a required attribute.
  #
  # @return [MatchData] the match result
  def parse_refname
    refname.match(Git::BRANCH_REFNAME_REGEXP)
  end
end

#tagger_dateString? (readonly)

Returns the tag date in ISO 8601 format, or nil for lightweight tags.

Returns:

  • (String, nil)

    the tag date in ISO 8601 format, or nil for lightweight tags



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#tagger_emailString? (readonly)

Returns the tagger's email, or nil for lightweight tags.

Returns:

  • (String, nil)

    the tagger's email, or nil for lightweight tags



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#tagger_nameString? (readonly)

Returns the tagger's name, or nil for lightweight tags.

Returns:

  • (String, nil)

    the tagger's name, or nil for lightweight tags



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#target_oidString (readonly)

The commit object ID (SHA) that HEAD points to

Returns:

  • (String)

    the full 40-character object ID



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/git/tag_info.rb', line 79

TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
  # @return [Boolean] true if this is an annotated tag (oid is present)
  def annotated?
    !oid.nil?
  end

  # @return [Boolean] true if this is a lightweight tag (oid is nil)
  def lightweight?
    oid.nil?
  end

  # Return the tagger as an Author object
  #
  # @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
  def tagger
    return nil unless annotated? && tagger_name && tagger_email

    # Git::Author expects format "Name <email> timestamp timezone"
    # We construct a minimal format that will parse correctly
    author = Git::Author.new('')
    author.name = tagger_name
    # Remove angle brackets if present
    author.email = tagger_email.gsub(/\A<|>\z/, '')
    author
  end
end

#total_deletionsInteger (readonly)

Returns total lines deleted across all files (from --shortstat).

Returns:

  • (Integer)

    total lines deleted across all files (from --shortstat)



31
# File 'lib/git/diff_result.rb', line 31

DiffResult = Data.define(:files_changed, :total_insertions, :total_deletions, :files, :dirstat)

#total_insertionsInteger (readonly)

Returns total lines inserted across all files (from --shortstat).

Returns:

  • (Integer)

    total lines inserted across all files (from --shortstat)



31
# File 'lib/git/diff_result.rb', line 31

DiffResult = Data.define(:files_changed, :total_insertions, :total_deletions, :files, :dirstat)

#typeString (readonly)

Returns the type of change: 'modified', 'new', 'deleted', 'renamed'.

Returns:

  • (String)

    the type of change: 'modified', 'new', 'deleted', 'renamed'



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/git/diff_info.rb', line 45

FileDiffInfo = Data.define(
  :path,
  :patch,
  :mode,
  :src,
  :dst,
  :type,
  :binary
) do
  # Check if this is a binary file
  #
  # @return [Boolean] true if the file is binary
  #
  def binary?
    binary
  end
end

#upstreamGit::BranchInfo? (readonly)

Note:

Remote-tracking branches (e.g., 'origin/main') have upstream: nil

Note:

When upstream exists but the remote-tracking branch hasn't been fetched, the upstream's target_oid may be nil

The configured upstream/tracking branch

Returns:

  • (Git::BranchInfo, nil)

    the upstream branch info, or nil if no upstream is configured



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/git/branch_info.rb', line 133

BranchInfo = Data.define(:refname, :target_oid, :current, :worktree, :symref, :upstream) do
  # @return [Boolean] always false for BranchInfo (see DetachedHeadInfo for detached state)
  def detached? = false

  # @return [Boolean] true if this is an unborn branch (no commits yet)
  def unborn? = target_oid.nil?

  # @return [Boolean] true if this is the currently checked out branch
  def current? = current

  # @return [Boolean] true if this branch is checked out in another worktree
  def worktree? = worktree

  # @return [Boolean] true if this is a symbolic reference
  def symref? = !symref.nil?

  # @return [Boolean] true if this is a remote-tracking branch
  def remote? = !remote_name.nil?

  # @return [String, nil] the name of the remote (e.g., 'origin'), or nil for local branches
  def remote_name
    parse_refname[:remote_name]
  end

  # @return [String] the branch name without remote prefix (e.g., 'main' or 'feature/foo')
  def short_name
    parse_refname[:branch_name]
  end

  # @return [String] string representation (the full refname)
  def to_s = refname

  private

  # Parse the refname and return match data
  #
  # The regex is guaranteed to match any non-empty string due to the `.+` pattern,
  # so we don't need nil checking. If refname is empty/nil, this would fail at
  # object creation time since refname is a required attribute.
  #
  # @return [MatchData] the match result
  def parse_refname
    refname.match(Git::BRANCH_REFNAME_REGEXP)
  end
end

#valueString (readonly)

The value of the configuration entry

Returns:

  • (String)

    the string value of this entry



58
59
60
61
62
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/git/config_entry_info.rb', line 58

ConfigEntryInfo = Data.define(:scope, :origin, :key, :value) do
  # Returns the section component of the key (everything before the first dot)
  #
  # Returns an empty string when the key contains no dot.
  #
  # @example Section component of a dotted key
  #   entry.section # => "remote"
  #
  # @return [String] the section name, or an empty string when the key has no dot
  #
  def section = first_dot ? key[0...first_dot] : ''

  # Returns the subsection component of the key (everything between the first and last dot)
  #
  # Returns an empty string when the key has zero or one dot (no subsection).
  #
  # @example Subsection component of a dotted key
  #   entry.subsection # => "origin"
  #
  # @return [String] the subsection name, or an empty string when there is no subsection
  #
  def subsection = first_dot && first_dot != last_dot ? key[(first_dot + 1)...last_dot] : ''

  # Returns the variable component of the key (everything after the last dot)
  #
  # Returns the full key when the key contains no dot.
  #
  # @example Variable component of a dotted key
  #   entry.variable # => "url"
  #
  # @return [String] the variable name (everything after the last dot)
  #
  def variable = last_dot ? key[(last_dot + 1)..] : key

  private

  # Returns the index of the first dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the first dot, or `nil`
  #
  def first_dot = key.index('.')

  # Returns the index of the last dot in the key, or nil if none exists
  #
  # @return [Integer, nil] the zero-based index of the last dot, or `nil`
  #
  def last_dot = key.rindex('.')
end

#worktreeBoolean (readonly)

Whether this branch is checked out in another linked worktree

Returns:

  • (Boolean)

    true if checked out in a different worktree



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/git/branch_info.rb', line 133

BranchInfo = Data.define(:refname, :target_oid, :current, :worktree, :symref, :upstream) do
  # @return [Boolean] always false for BranchInfo (see DetachedHeadInfo for detached state)
  def detached? = false

  # @return [Boolean] true if this is an unborn branch (no commits yet)
  def unborn? = target_oid.nil?

  # @return [Boolean] true if this is the currently checked out branch
  def current? = current

  # @return [Boolean] true if this branch is checked out in another worktree
  def worktree? = worktree

  # @return [Boolean] true if this is a symbolic reference
  def symref? = !symref.nil?

  # @return [Boolean] true if this is a remote-tracking branch
  def remote? = !remote_name.nil?

  # @return [String, nil] the name of the remote (e.g., 'origin'), or nil for local branches
  def remote_name
    parse_refname[:remote_name]
  end

  # @return [String] the branch name without remote prefix (e.g., 'main' or 'feature/foo')
  def short_name
    parse_refname[:branch_name]
  end

  # @return [String] string representation (the full refname)
  def to_s = refname

  private

  # Parse the refname and return match data
  #
  # The regex is guaranteed to match any non-empty string due to the `.+` pattern,
  # so we don't need nil checking. If refname is empty/nil, this would fail at
  # object creation time since refname is a required attribute.
  #
  # @return [MatchData] the match result
  def parse_refname
    refname.match(Git::BRANCH_REFNAME_REGEXP)
  end
end

Class Method Details

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

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::Repository)

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

See Also:



160
161
162
# File 'lib/git.rb', line 160

def self.bare(git_dir, options = {})
  Git::Repository.bare(git_dir, options)
end

.binary_version(binary_path = nil) ⇒ Array<Integer>

Deprecated.

Use git_version instead, which returns a Version (not an Array)

For the legacy array shape, call: Git.git_version.to_a. The optional binary_path argument is preserved: Git.git_version(binary_path).

Return the version of the git binary

Examples:

Basic usage

Git.binary_version  # => [2, 46, 0]

Parameters:

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

    path to the git binary; defaults to Git::Config.instance.binary_path

Returns:

  • (Array<Integer>)

    the version of the git binary



628
629
630
631
632
633
634
635
636
637
# File 'lib/git.rb', line 628

def self.binary_version(binary_path = nil)
  binary_path ||= Git::Config.instance.binary_path
  Git::Deprecation.warn(
    'Git.binary_version is deprecated and will be removed in 6.0. ' \
    'Use Git.git_version instead, which returns a Git::Version ' \
    '(not an Array). For the legacy array shape, call: Git.git_version.to_a. ' \
    'The optional binary_path argument is preserved: Git.git_version(binary_path).'
  )
  git_version(binary_path).to_a
end

.cached_git_version(binary_path, &block)

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.



509
510
511
512
513
# File 'lib/git.rb', line 509

def self.cached_git_version(binary_path, &block)
  @git_version_cache_mutex.synchronize do
    @git_version_cache[binary_path] ||= block.call
  end
end

.clear_git_version_cache

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.



516
517
518
519
520
# File 'lib/git.rb', line 516

def self.clear_git_version_cache
  @git_version_cache_mutex.synchronize do
    @git_version_cache.clear
  end
end

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

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')

Clone into a specific parent directory

git = Git.clone('https://github.com/ruby-git/ruby-git.git', chdir: '/path/to/projects')
# clones into /path/to/projects/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', 'user.email=john@doe.com']
)

Clone using a specific SSH key

git = Git.clone(
  'git@github.com: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) (defaults to: nil)

    The directory to clone into

    If directory is a relative path it is relative to the :chdir option if given. If :chdir 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.

  • :chdir (Pathname)

    Run git clone from within this directory.

    The directory parameter (or the repository basename when directory is nil) is resolved relative to :chdir, just as if you had cd'd into it before running git clone. The returned path is the join of :chdir and the cloned directory path.

  • :path (Pathname)

    Deprecated — use :chdir instead.

  • :recursive (Boolean)

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

Returns:

  • (Git::Repository)

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

See Also:



278
279
280
# File 'lib/git.rb', line 278

def self.clone(repository_url, directory = nil, options = {})
  Git::Repository.clone(repository_url, directory, options)
end

.configGit::Config

Returns the process-wide Config singleton

Examples:

Read the configured binary path

Git.config.binary_path  #=> "git"

Returns:



112
113
114
# File 'lib/git.rb', line 112

def self.config
  Git::Config.instance
end

.configure {|config| ... }

This method returns an undefined value.

Configures the gem by yielding Git::Config.instance to the block

Examples:

Set the global git binary path

Git.configure { |c| c.binary_path = '/usr/local/bin/git' }

Yields:

  • (config)

    yields the singleton config object

Yield Parameters:

Yield Returns:

  • (void)


100
101
102
103
# File 'lib/git.rb', line 100

def self.configure
  yield Git::Config.instance
  nil
end

.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



319
320
321
322
323
# File 'lib/git.rb', line 319

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

.export(repository, name, options = {})

Export the current HEAD (or a branch, if options[:branch] is specified) into the +name+ directory, then remove all traces of git from the directory.

See +clone+ for options. Does not obey the :remote option, since the .git info will be deleted anyway; always uses the default remote, 'origin.'



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

def self.export(repository, name, options = {})
  options.delete(:remote)
  repo = clone(repository, name, { depth: 1 }.merge(options))
  repo.checkout("origin/#{options[:branch]}") if options[:branch]
  FileUtils.rm_r File.join(repo.dir.to_s, '.git')
end

.git_version(binary_path = nil) ⇒ Git::Version

Return the version of a git binary as a Version

Examples:

Default binary

Git.git_version #=> #<Git::Version 2.42.0>

Explicit binary path

Git.git_version('/opt/homebrew/bin/git') #=> #<Git::Version 2.42.0>

Parameters:

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

    path to the git binary; defaults to Git::Config.instance.binary_path

Returns:

Raises:



541
542
543
544
# File 'lib/git.rb', line 541

def self.git_version(binary_path = nil)
  path = binary_path || Git::Config.instance.binary_path
  cached_git_version(path) { run_git_version(path) }
end

.global_config(name = nil, value = nil)

Same as g.config, but forces it to be at the global level

g.config('user.name', 'Scott Chacon') # sets value g.config('user.email', 'email@email.com') # sets value g.config('user.name') # returns 'Scott Chacon' g.config # returns whole config hash



345
346
347
# File 'lib/git.rb', line 345

def self.global_config(name = nil, value = nil)
  run_config_utility(name, value, global: true)
end

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

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.

  • :separate_git_dir (Pathname)

    Alias for :repository.

  • :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.
  • :binary_path (String, :use_global_config)

    path to the git binary; defaults to Git::Config.instance.binary_path when not specified. Raises ArgumentError if set to nil.

  • :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::Repository)

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

See Also:



411
412
413
# File 'lib/git.rb', line 411

def self.init(directory = '.', options = {})
  Git::Repository.init(directory, options)
end

.ls_remote(location = nil, options = {}) ⇒ {String=>Hash}

returns a Hash containing information about the references of the target repository

options :refs

Parameters:

  • location (String|NilClass) (defaults to: nil)

    the target repository location or nil for '.'

Returns:

  • ({String=>Hash})

    the available references of the target repo.

Raises:

  • (ArgumentError)


438
439
440
441
442
443
444
445
446
447
448
# File 'lib/git.rb', line 438

def self.ls_remote(location = nil, options = {})
  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)
  repository = location || '.'
  output_lines = Git::Commands::LsRemote.new(context).call(repository, **options).stdout.split("\n")
  Git::Parsers::LsRemote.parse_output(output_lines)
end

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

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::Repository)

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



500
501
502
# File 'lib/git.rb', line 500

def self.open(working_dir, options = {})
  Git::Repository.open(working_dir, options)
end

Instance Method Details

#config(name = nil, value = nil)

Deprecated.

Mixing in the Git module is deprecated and will be removed in v6.0.0. Use Git.open(Dir.pwd).config(...) instead.



79
80
81
82
83
84
85
# File 'lib/git.rb', line 79

def config(name = nil, value = nil)
  Git::Deprecation.warn(
    'Git#config is deprecated and will be removed in v6.0.0. ' \
    'Use Git.open(Dir.pwd).config(...) instead.'
  )
  Git.__send__(:run_config_utility, name, value, global: false)
end

#global_config(name = nil, value = nil)

Deprecated.

Mixing in the Git module is deprecated and will be removed in v6.0.0. Use Git.global_config(...) instead.



118
119
120
121
122
123
124
# File 'lib/git.rb', line 118

def global_config(name = nil, value = nil)
  Git::Deprecation.warn(
    'Git#global_config is deprecated and will be removed in v6.0.0. ' \
    'Use Git.global_config(...) instead.'
  )
  Git.global_config(name, value)
end