git 4.1.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +12 -3
- data/.release-please-manifest.json +1 -1
- data/.yardopts +4 -0
- data/AI_POLICY.md +24 -0
- data/CHANGELOG.md +11 -0
- data/CODE_OF_CONDUCT.md +25 -0
- data/CONTRIBUTING.md +13 -0
- data/GOVERNANCE.md +63 -0
- data/MAINTAINERS.md +16 -4
- data/README.md +388 -333
- data/lib/git/log.rb +6 -1
- data/lib/git/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e74c843d872d01532fd6938f338d16cfa84a25a4c47287347edbea39e580488
|
|
4
|
+
data.tar.gz: d7db0f868a554c60fc39d5716096dbc7967d974afad249b7625266f00cb4c305
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41504a21ea74ab571a0db205b3654a69fd6e6a5af7917e9612c4dab8cbfc321c5babc44bdf62287e890146282fe64343c97fc5af49d0f9520b340db5f4f8f4a6
|
|
7
|
+
data.tar.gz: bccb9b41fd526b5b6c92870e05fcf967d9a235898988efd41aa4f2e3ed7a2e10a4d9e3fda1e8ee7a25d4870cea132d2ae7b50dbb72252e8bb9e292a98ccebf7e
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
Review our [guidelines for contributing](https://github.com/ruby-git/ruby-git/blob/main/CONTRIBUTING.md) to this repository. A good start is to:
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
- Write tests for your changes
|
|
4
|
+
- Run `rake` before pushing
|
|
5
|
+
- Include / update docs in the README.md and in YARD documentation
|
|
6
6
|
|
|
7
7
|
# Description
|
|
8
8
|
|
|
9
|
+
\<your description here\>
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
|
|
13
|
+
- [ ] I reviewed and applied the project's [AI Policy](../AI_POLICY.md). I understand
|
|
14
|
+
and verify any AI-assisted changes included in this PR and ensured they meet
|
|
15
|
+
quality, security, and licensing standards.
|
|
16
|
+
- [ ] Tests added/updated as needed and `rake` passes locally.
|
|
17
|
+
- [ ] Documentation updated where applicable (README and/or YARD).
|
data/.yardopts
CHANGED
data/AI_POLICY.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
# @markup markdown
|
|
3
|
+
# @title AI Policy
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# AI Policy
|
|
7
|
+
|
|
8
|
+
AI assisted contributions are welcome in this project.
|
|
9
|
+
|
|
10
|
+
Reviewing and maintaining code requires human insight. While AI tools can be helpful
|
|
11
|
+
assistants, they are no substitute for human judgment and creativity.
|
|
12
|
+
|
|
13
|
+
We value the unique perspectives and critical thinking that our contributors bring.
|
|
14
|
+
If you use AI tools to assist your work:
|
|
15
|
+
|
|
16
|
+
1. **You are responsible**: You must review and understand every line of code or text
|
|
17
|
+
you submit.
|
|
18
|
+
2. **Focus on quality**: Ensure that AI-generated content meets our standards for
|
|
19
|
+
correctness, readability, and security, and respects all licensing requirements.
|
|
20
|
+
3. **Be transparent**: We encourage you to disclose if significant portions of your
|
|
21
|
+
contribution were AI-generated.
|
|
22
|
+
|
|
23
|
+
Ultimately, the quality of this project depends on *your* expertise. Use tools
|
|
24
|
+
wisely, but lead with your own intelligence.
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
# Change Log
|
|
7
7
|
|
|
8
|
+
## [4.1.1](https://github.com/ruby-git/ruby-git/compare/v4.1.0...v4.1.1) (2026-01-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Other Changes
|
|
12
|
+
|
|
13
|
+
* Add AI Policy and update documentation ([8616cdf](https://github.com/ruby-git/ruby-git/commit/8616cdf7c6cfd1a3f2ccb931f59367b0fdfa36d1))
|
|
14
|
+
* Add code of conduct links ([0769c8e](https://github.com/ruby-git/ruby-git/commit/0769c8ede791a2578291fa301d74144bc7fb2bfb))
|
|
15
|
+
* Add governance policy and update project policies ([8d8263c](https://github.com/ruby-git/ruby-git/commit/8d8263c8395ff4e127b7dc6eb25b0371c272593a))
|
|
16
|
+
* Add Quick Start section and reorganize README for new users ([1811a75](https://github.com/ruby-git/ruby-git/commit/1811a75e4b0b8b8233988d38a411ba585f35c044))
|
|
17
|
+
* Clarify JRuby on Windows support policy ([c37b3d6](https://github.com/ruby-git/ruby-git/commit/c37b3d6c256cdc925578c7ff198f6b351dcb5844))
|
|
18
|
+
|
|
8
19
|
## [4.1.0](https://github.com/ruby-git/ruby-git/compare/v4.0.7...v4.1.0) (2026-01-02)
|
|
9
20
|
|
|
10
21
|
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
# @markup markdown
|
|
3
|
+
# @title Code of Conduct
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Code of Conduct
|
|
7
|
+
|
|
8
|
+
ℹ️ We have adopted the [Ruby code of conduct](https://www.ruby-lang.org/en/conduct/).
|
|
9
|
+
|
|
10
|
+
This document provides community guidelines for a safe, respectful, productive, and
|
|
11
|
+
collaborative place for any person who is willing to contribute to the Ruby
|
|
12
|
+
community. It applies to all “collaborative space”, which is defined as community
|
|
13
|
+
communications channels (such as mailing lists, submitted patches, commit comments,
|
|
14
|
+
etc.).
|
|
15
|
+
|
|
16
|
+
- Participants will be tolerant of opposing views.
|
|
17
|
+
- Participants must ensure that their language and actions are free of personal
|
|
18
|
+
attacks and disparaging personal remarks.
|
|
19
|
+
- When interpreting the words and actions of others, participants should always
|
|
20
|
+
assume good intentions.
|
|
21
|
+
- Behavior which can be reasonably considered harassment will not be tolerated.
|
|
22
|
+
|
|
23
|
+
Report violations to the maintainers by [opening an
|
|
24
|
+
issue](https://github.com/ruby-git/ruby-git/issues/new) or contacting a
|
|
25
|
+
[maintainer](MAINTAINERS.md) privately.
|
data/CONTRIBUTING.md
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
- [Commit your changes to a fork of `ruby-git`](#commit-your-changes-to-a-fork-of-ruby-git)
|
|
13
13
|
- [Create a pull request](#create-a-pull-request)
|
|
14
14
|
- [Get your pull request reviewed](#get-your-pull-request-reviewed)
|
|
15
|
+
- [AI-assisted contributions](#ai-assisted-contributions)
|
|
15
16
|
- [Design philosophy](#design-philosophy)
|
|
16
17
|
- [Direct mapping to git commands](#direct-mapping-to-git-commands)
|
|
17
18
|
- [Parameter naming](#parameter-naming)
|
|
@@ -41,6 +42,11 @@ judgment when contributing.
|
|
|
41
42
|
If you have suggestions for improving these guidelines, please propose changes via a
|
|
42
43
|
pull request.
|
|
43
44
|
|
|
45
|
+
Please also review and adhere to our [Code of Conduct](CODE_OF_CONDUCT.md) when
|
|
46
|
+
participating in the project.
|
|
47
|
+
Governance and maintainer expectations are described in
|
|
48
|
+
[GOVERNANCE.md](GOVERNANCE.md).
|
|
49
|
+
|
|
44
50
|
## How to contribute
|
|
45
51
|
|
|
46
52
|
You can contribute in the following ways:
|
|
@@ -98,6 +104,13 @@ At least one approval from a project maintainer is required before your pull req
|
|
|
98
104
|
can be merged. The maintainer is responsible for ensuring that the pull request meets
|
|
99
105
|
[the project's coding standards](#coding-standards).
|
|
100
106
|
|
|
107
|
+
## AI-assisted contributions
|
|
108
|
+
|
|
109
|
+
AI-assisted contributions are welcome. Please review and apply our [AI Policy](AI_POLICY.md)
|
|
110
|
+
before submitting changes. You are responsible for understanding and verifying any
|
|
111
|
+
AI-assisted work included in PRs and ensuring it meets our standards for quality,
|
|
112
|
+
security, and licensing.
|
|
113
|
+
|
|
101
114
|
## Design philosophy
|
|
102
115
|
|
|
103
116
|
*Note: As of v2.x of the `git` gem, this design philosophy is aspirational. Future
|
data/GOVERNANCE.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
# @markup markdown
|
|
3
|
+
# @title Governance
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Governance
|
|
7
|
+
|
|
8
|
+
This document explains how we steward the project with a light, principles-first
|
|
9
|
+
approach: enable trusted people, minimize dormant access, and keep decisions
|
|
10
|
+
transparent.
|
|
11
|
+
|
|
12
|
+
## Roles
|
|
13
|
+
|
|
14
|
+
A **Maintainer** is a trusted leader with write access who stewards the project's
|
|
15
|
+
health and direction. Responsibilities center on triage, review, merge, and
|
|
16
|
+
helping the community stay unblocked.
|
|
17
|
+
|
|
18
|
+
A **Project Lead** is a maintainer with additional administrative scope (repo
|
|
19
|
+
Admin, org Owner). They handle settings, secrets, access, and tie-breaks when
|
|
20
|
+
needed.
|
|
21
|
+
|
|
22
|
+
## Becoming a Maintainer
|
|
23
|
+
|
|
24
|
+
Maintainers invite contributors who consistently ship, review, and model our
|
|
25
|
+
values to become maintainers. Anyone can nominate themselves or others in an
|
|
26
|
+
issue or via a private note. Current maintainers discuss nominations (see
|
|
27
|
+
[Decision Making](#decision-making)) with a focus on contribution quality,
|
|
28
|
+
alignment with project goals, and communication style.
|
|
29
|
+
|
|
30
|
+
## Access Principles
|
|
31
|
+
|
|
32
|
+
- Stewardship: Maintainer access exists to keep the project healthy and responsive.
|
|
33
|
+
- Least privilege: Elevated access is temporary and kept only while it’s needed.
|
|
34
|
+
- Continuity: Dormant access is paused to protect the project and unblock
|
|
35
|
+
contributors.
|
|
36
|
+
- Respect: Status changes are transparent, reversible, and acknowledge past
|
|
37
|
+
contributions.
|
|
38
|
+
|
|
39
|
+
## How We Apply Them
|
|
40
|
+
|
|
41
|
+
- Staying active: Maintainers keep elevated access while participating (shipping,
|
|
42
|
+
reviewing, triaging, or governance).
|
|
43
|
+
- When access is paused: If there’s no project activity for about a year, we’ll
|
|
44
|
+
check in. If we don’t hear back after a short window, we move the maintainer to
|
|
45
|
+
Emeritus and pause Owner/Admin/Write/package access (including CODEOWNERS
|
|
46
|
+
entries).
|
|
47
|
+
- Coming back: Emeritus maintainers can be re-added quickly after a brief period of
|
|
48
|
+
renewed participation to refresh context.
|
|
49
|
+
- Recognition: Emeritus maintainers remain listed to honor prior contributions.
|
|
50
|
+
|
|
51
|
+
Access changes are communicated openly (e.g., PRs or issues) and reflected in the
|
|
52
|
+
Maintainers list.
|
|
53
|
+
|
|
54
|
+
## Decision Making
|
|
55
|
+
|
|
56
|
+
Decisions are usually made by consensus among the active maintainers. If consensus
|
|
57
|
+
cannot be reached, the decision is made by a majority vote. If a vote results in a
|
|
58
|
+
tie, the Project Lead has the final say.
|
|
59
|
+
|
|
60
|
+
## Code of Conduct
|
|
61
|
+
|
|
62
|
+
All maintainers and contributors must adhere to the project's [Code of
|
|
63
|
+
Conduct](./CODE_OF_CONDUCT.md).
|
data/MAINTAINERS.md
CHANGED
|
@@ -5,8 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
# Maintainers
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
See [GOVERNANCE.md](GOVERNANCE.md) for a definition of the Maintainer role.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
## Active Maintainers
|
|
11
|
+
|
|
12
|
+
- [James Couball](https://github.com/jcouball) (Project Lead)
|
|
13
|
+
- [Frank Throckmorton](https://github.com/frankthrock)
|
|
14
|
+
- [Per Lundberg](https://github.com/perlun)
|
|
15
|
+
|
|
16
|
+
## Maintainers Emeritus (Alumni)
|
|
17
|
+
|
|
18
|
+
**Maintainers Emeritus** are former maintainers who are no longer active. We honor
|
|
19
|
+
their past contributions.
|
|
20
|
+
|
|
21
|
+
- [Vern Burton](https://github.com/tarcinil)
|
|
22
|
+
- [Daniel Perez](https://github.com/dpmex4527)
|
|
23
|
+
- [Richard Vodden](https://github.com/rvodden)
|
|
24
|
+
- [Scott Chacon](https://github.com/schacon)
|
data/README.md
CHANGED
|
@@ -7,21 +7,30 @@
|
|
|
7
7
|
|
|
8
8
|
[](https://badge.fury.io/rb/git)
|
|
9
9
|
[](https://rubydoc.info/gems/git/)
|
|
10
|
-
[](https://rubydoc.info/gems/git/file/CHANGELOG.md)
|
|
12
|
+
[](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI)
|
|
14
|
+
[](https://conventionalcommits.org)
|
|
16
|
+
[](AI_POLICY.md)
|
|
13
17
|
|
|
14
18
|
- [Summary](#summary)
|
|
15
19
|
- [Install](#install)
|
|
16
|
-
- [
|
|
20
|
+
- [Quick Start](#quick-start)
|
|
21
|
+
- [Examples](#examples)
|
|
22
|
+
- [Configuration](#configuration)
|
|
23
|
+
- [Read Operations](#read-operations)
|
|
24
|
+
- [Write Operations](#write-operations)
|
|
25
|
+
- [Index and Tree Operations](#index-and-tree-operations)
|
|
17
26
|
- [Errors Raised By This Gem](#errors-raised-by-this-gem)
|
|
18
27
|
- [Specifying And Handling Timeouts](#specifying-and-handling-timeouts)
|
|
19
28
|
- [Deprecations](#deprecations)
|
|
20
|
-
- [
|
|
21
|
-
- [Ruby
|
|
22
|
-
- [Git
|
|
23
|
-
- [License](#license)
|
|
29
|
+
- [Project Policies](#project-policies)
|
|
30
|
+
- [Ruby Version Support Policy](#ruby-version-support-policy)
|
|
31
|
+
- [Git Version Support Policy](#git-version-support-policy)
|
|
24
32
|
- [📢 Project Announcements 📢](#-project-announcements-)
|
|
33
|
+
- [2026-01-07: AI Policy Introduced](#2026-01-07-ai-policy-introduced)
|
|
25
34
|
- [2025-07-09: Architectural Redesign](#2025-07-09-architectural-redesign)
|
|
26
35
|
- [2025-07-07: We Now Use RuboCop](#2025-07-07-we-now-use-rubocop)
|
|
27
36
|
- [2025-06-06: Default Branch Rename](#2025-06-06-default-branch-rename)
|
|
@@ -34,11 +43,15 @@ command line.
|
|
|
34
43
|
|
|
35
44
|
Get started by obtaining a repository object by:
|
|
36
45
|
|
|
37
|
-
- opening an existing working copy with
|
|
38
|
-
|
|
39
|
-
-
|
|
46
|
+
- opening an existing working copy with
|
|
47
|
+
[Git.open](https://rubydoc.info/gems/git/Git#open-class_method)
|
|
48
|
+
- initializing a new repository with
|
|
49
|
+
[Git.init](https://rubydoc.info/gems/git/Git#init-class_method)
|
|
50
|
+
- cloning a repository with
|
|
51
|
+
[Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method)
|
|
40
52
|
|
|
41
|
-
Methods that can be called on a repository object are documented in
|
|
53
|
+
Methods that can be called on a repository object are documented in
|
|
54
|
+
[Git::Base](https://rubydoc.info/gems/git/Git/Base)
|
|
42
55
|
|
|
43
56
|
## Install
|
|
44
57
|
|
|
@@ -66,169 +79,92 @@ to install version 1.x:
|
|
|
66
79
|
gem install git --version "~> 1.19"
|
|
67
80
|
```
|
|
68
81
|
|
|
69
|
-
##
|
|
70
|
-
|
|
71
|
-
**Git::Base** - The object returned from a `Git.open` or `Git.clone`. Most major actions are called from this object.
|
|
72
|
-
|
|
73
|
-
**Git::Object** - The base object for your tree, blob and commit objects, returned from `@git.gtree` or `@git.object` calls. the `Git::AbstractObject` will have most of the calls in common for all those objects.
|
|
82
|
+
## Quick Start
|
|
74
83
|
|
|
75
|
-
|
|
84
|
+
All functionality for this gem starts with the top-level
|
|
85
|
+
[`Git`](https://rubydoc.info/gems/git/Git) module. This module can be used to run
|
|
86
|
+
non-repo scoped `git` commands such as `config`.
|
|
76
87
|
|
|
77
|
-
|
|
78
|
-
`Git
|
|
79
|
-
|
|
88
|
+
The `Git` module also has factory methods such as `open`, `clone`, and `init` which
|
|
89
|
+
return a [`Git::Base`](https://rubydoc.info/gems/git/Git/Base) object. The
|
|
90
|
+
`Git::Base` object is used to run repo-specific `git` commands such as `add`,
|
|
91
|
+
`commit`, `push`, and `log`.
|
|
80
92
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
**Git::Remote**- A reference to a remote repository that is tracked by this repository.
|
|
84
|
-
|
|
85
|
-
**Git::Log** - An Enumerable object that references all the `Git::Object::Commit`
|
|
86
|
-
objects that encompass your log query, which can be constructed through methods on
|
|
87
|
-
the `Git::Log object`, like:
|
|
93
|
+
Clone, read status, and log:
|
|
88
94
|
|
|
89
95
|
```ruby
|
|
90
|
-
git
|
|
91
|
-
.max_count(:all)
|
|
92
|
-
.object('README.md')
|
|
93
|
-
.since('10 years ago')
|
|
94
|
-
.between('v1.0.7', 'HEAD')
|
|
95
|
-
.map { |commit| commit.sha }
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
A maximum of 30 commits are returned if `max_count` is not called. To get all commits
|
|
99
|
-
that match the log query, call `max_count(:all)`.
|
|
100
|
-
|
|
101
|
-
Note that `git.log.all` adds the `--all` option to the underlying `git log` command.
|
|
102
|
-
This asks for the logs of all refs (basically all commits reachable by HEAD,
|
|
103
|
-
branches, and tags). This does not control the maximum number of commits returned. To
|
|
104
|
-
control how many commits are returned, you should call `max_count`.
|
|
105
|
-
|
|
106
|
-
**Git::Worktrees** - Enumerable object that holds `Git::Worktree objects`.
|
|
107
|
-
|
|
108
|
-
## Errors Raised By This Gem
|
|
109
|
-
|
|
110
|
-
The git gem will only raise an `ArgumentError` or an error that is a subclass of
|
|
111
|
-
`Git::Error`. It does not explicitly raise any other types of errors.
|
|
112
|
-
|
|
113
|
-
It is recommended to rescue `Git::Error` to catch any runtime error raised by
|
|
114
|
-
this gem unless you need more specific error handling.
|
|
96
|
+
require 'git'
|
|
115
97
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
rescue Git::Error => e
|
|
120
|
-
puts "An error occurred: #{e.message}"
|
|
121
|
-
end
|
|
98
|
+
repo = Git.clone('https://github.com/ruby-git/ruby-git.git', 'ruby-git')
|
|
99
|
+
repo.status.changed.each { |f| puts "changed: #{f.path}" }
|
|
100
|
+
repo.log(5).each { |c| puts c.message }
|
|
122
101
|
```
|
|
123
102
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
## Specifying And Handling Timeouts
|
|
127
|
-
|
|
128
|
-
The timeout feature was added in git gem version `2.0.0`.
|
|
129
|
-
|
|
130
|
-
A timeout for git command line operations can be set either globally or for specific
|
|
131
|
-
method calls that accept a `:timeout` parameter.
|
|
132
|
-
|
|
133
|
-
The timeout value must be a real, non-negative `Numeric` value that specifies a
|
|
134
|
-
number of seconds a `git` command will be given to complete before being sent a KILL
|
|
135
|
-
signal. This library may hang if the `git` command does not terminate after receiving
|
|
136
|
-
the KILL signal.
|
|
137
|
-
|
|
138
|
-
When a command times out, it is killed by sending it the `SIGKILL` signal and a
|
|
139
|
-
`Git::TimeoutError` is raised. This error derives from the `Git::SignaledError` and
|
|
140
|
-
`Git::Error`.
|
|
141
|
-
|
|
142
|
-
If the timeout value is `0` or `nil`, no timeout will be enforced.
|
|
143
|
-
|
|
144
|
-
If a method accepts a `:timeout` parameter and a receives a non-nil value, the value
|
|
145
|
-
of this parameter will override the global timeout value. In this context, a value of
|
|
146
|
-
`nil` (which is usually the default) will use the global timeout value and a value of
|
|
147
|
-
`0` will turn off timeout enforcement for that method call no matter what the global
|
|
148
|
-
value is.
|
|
149
|
-
|
|
150
|
-
To set a global timeout, use the `Git.config` object:
|
|
103
|
+
Open an existing repo and commit:
|
|
151
104
|
|
|
152
105
|
```ruby
|
|
153
|
-
|
|
154
|
-
Git.config.timeout = 1.5 # can be any real, non-negative Numeric interpreted as number of seconds
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
The global timeout can be overridden for a specific method if the method accepts a
|
|
158
|
-
`:timeout` parameter:
|
|
106
|
+
require 'git'
|
|
159
107
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
Git.clone(repo_url, timeout: 0) # Do not enforce a timeout
|
|
165
|
-
Git.clone(repo_url, timeout: 10.5) # Timeout after 10.5 seconds raising Git::SignaledError
|
|
108
|
+
repo = Git.open('/path/to/repo')
|
|
109
|
+
repo.add(all: true)
|
|
110
|
+
repo.commit('chore: update files')
|
|
111
|
+
repo.push
|
|
166
112
|
```
|
|
167
113
|
|
|
168
|
-
|
|
114
|
+
Initialize a new repo and make the first commit:
|
|
169
115
|
|
|
170
116
|
```ruby
|
|
171
|
-
|
|
172
|
-
Git.clone(repo_url, timeout: 10)
|
|
173
|
-
rescue Git::TimeoutError => e
|
|
174
|
-
e.result.tap do |r|
|
|
175
|
-
r.class #=> Git::CommandLineResult
|
|
176
|
-
r.status #=> #<Process::Status: pid 62173 SIGKILL (signal 9)>
|
|
177
|
-
r.status.timeout? #=> true
|
|
178
|
-
r.git_cmd # The git command ran as an array of strings
|
|
179
|
-
r.stdout # The command's output to stdout until it was terminated
|
|
180
|
-
r.stderr # The command's output to stderr until it was terminated
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
## Deprecations
|
|
186
|
-
|
|
187
|
-
This gem uses ActiveSupport's deprecation mechanism to report deprecation warnings.
|
|
188
|
-
|
|
189
|
-
You can silence deprecation warnings by adding this line to your source code:
|
|
117
|
+
require 'git'
|
|
190
118
|
|
|
191
|
-
|
|
192
|
-
|
|
119
|
+
repo = Git.init('my_project')
|
|
120
|
+
repo.add(all: true)
|
|
121
|
+
repo.commit('initial commit')
|
|
193
122
|
```
|
|
194
123
|
|
|
195
|
-
See [the Active Support Deprecation
|
|
196
|
-
documentation](https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.html)
|
|
197
|
-
for more details.
|
|
198
|
-
|
|
199
|
-
If deprecation warnings are silenced, you should reenable them before upgrading the
|
|
200
|
-
git gem to the next major version. This will make it easier to identify changes
|
|
201
|
-
needed for the upgrade.
|
|
202
|
-
|
|
203
124
|
## Examples
|
|
204
125
|
|
|
205
|
-
|
|
126
|
+
Beyond the basics covered in Quick Start, these examples show the full range of
|
|
127
|
+
options and variations for each operation.
|
|
206
128
|
|
|
207
|
-
|
|
129
|
+
### Configuration
|
|
130
|
+
|
|
131
|
+
Configure the `git` command line:
|
|
208
132
|
|
|
209
133
|
```ruby
|
|
210
|
-
|
|
134
|
+
# Global config (in ~/.gitconfig)
|
|
135
|
+
settings = Git.global_config # returns a Hash
|
|
136
|
+
username = Git.global_config('user.email')
|
|
137
|
+
Git.global_config('user.email', 'user@example.com')
|
|
138
|
+
|
|
139
|
+
# Repository config
|
|
140
|
+
repo = Git.open('path/to/repo')
|
|
141
|
+
settings = repo.config # returns a Hash
|
|
142
|
+
username = repo.config('user.email')
|
|
143
|
+
repo.config('user.email', 'anotheruser@example.com')
|
|
211
144
|
```
|
|
212
145
|
|
|
213
|
-
|
|
146
|
+
Configure the git gem:
|
|
214
147
|
|
|
215
148
|
```ruby
|
|
216
149
|
Git.configure do |config|
|
|
217
|
-
|
|
218
|
-
config.
|
|
219
|
-
|
|
220
|
-
# If you need to use a custom SSH script
|
|
221
|
-
config.git_ssh = '/path/to/ssh/script'
|
|
150
|
+
config.binary_path = '/usr/local/bin/git'
|
|
151
|
+
config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
|
|
222
152
|
end
|
|
223
|
-
```
|
|
224
153
|
|
|
225
|
-
|
|
154
|
+
# or
|
|
155
|
+
|
|
156
|
+
Git.config.binary_path = '/usr/local/bin/git'
|
|
157
|
+
Git.config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
|
|
158
|
+
```
|
|
226
159
|
|
|
227
160
|
**How SSH configuration is determined:**
|
|
228
161
|
|
|
229
|
-
- If `git_ssh` is not specified in the API call, the global config (`Git.configure {
|
|
230
|
-
|
|
231
|
-
- If `git_ssh` is
|
|
162
|
+
- If `git_ssh` is not specified in the API call, the global config (`Git.configure {
|
|
163
|
+
|c| c.git_ssh = ... }`) is used.
|
|
164
|
+
- If `git_ssh: nil` is specified, SSH is disabled for that instance (no SSH key or
|
|
165
|
+
script will be used).
|
|
166
|
+
- If `git_ssh` is a non-empty string, it is used for that instance (overriding the
|
|
167
|
+
global config).
|
|
232
168
|
|
|
233
169
|
You can also specify a custom SSH script on a per-repository basis:
|
|
234
170
|
|
|
@@ -244,43 +180,46 @@ git = Git.clone('git@github.com:user/repo.git', 'local-dir',
|
|
|
244
180
|
git = Git.init('new-repo', git_ssh: 'ssh -i /path/to/private_key')
|
|
245
181
|
```
|
|
246
182
|
|
|
247
|
-
This is especially useful in multi-threaded applications where different repositories
|
|
183
|
+
This is especially useful in multi-threaded applications where different repositories
|
|
184
|
+
require different SSH credentials.
|
|
248
185
|
|
|
249
|
-
|
|
186
|
+
### Read Operations
|
|
187
|
+
|
|
188
|
+
Here are the operations that need read permission only:
|
|
250
189
|
|
|
251
190
|
```ruby
|
|
252
|
-
|
|
191
|
+
repo = Git.open(working_dir, :log => Logger.new(STDOUT))
|
|
253
192
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
193
|
+
repo.index
|
|
194
|
+
repo.index.readable?
|
|
195
|
+
repo.index.writable?
|
|
196
|
+
repo.repo
|
|
197
|
+
repo.dir
|
|
259
198
|
|
|
260
199
|
# ls-tree with recursion into subtrees (list files)
|
|
261
|
-
|
|
200
|
+
repo.ls_tree("HEAD", recursive: true)
|
|
262
201
|
|
|
263
202
|
# log - returns a Git::Log object, which is an Enumerator of Git::Commit objects
|
|
264
203
|
# default configuration returns a max of 30 commits
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
204
|
+
repo.log
|
|
205
|
+
repo.log(200) # 200 most recent commits
|
|
206
|
+
repo.log.since('2 weeks ago') # default count of commits since 2 weeks ago.
|
|
207
|
+
repo.log(200).since('2 weeks ago') # commits since 2 weeks ago, limited to 200.
|
|
208
|
+
repo.log.between('v2.5', 'v2.6')
|
|
209
|
+
repo.log.each {|l| puts l.sha }
|
|
210
|
+
repo.gblob('v2.5:Makefile').log.since('2 weeks ago')
|
|
272
211
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
212
|
+
repo.object('HEAD^').to_s # git show / git rev-parse
|
|
213
|
+
repo.object('HEAD^').contents
|
|
214
|
+
repo.object('v2.5:Makefile').size
|
|
215
|
+
repo.object('v2.5:Makefile').sha
|
|
277
216
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
217
|
+
repo.gtree(treeish)
|
|
218
|
+
repo.gblob(treeish)
|
|
219
|
+
repo.gcommit(treeish)
|
|
281
220
|
|
|
282
221
|
|
|
283
|
-
commit =
|
|
222
|
+
commit = repo.gcommit('1cc8667014381')
|
|
284
223
|
|
|
285
224
|
commit.gtree
|
|
286
225
|
commit.parent.sha
|
|
@@ -292,60 +231,60 @@ commit.committer.name
|
|
|
292
231
|
commit.date.strftime("%m-%d-%y")
|
|
293
232
|
commit.message
|
|
294
233
|
|
|
295
|
-
tree =
|
|
234
|
+
tree = repo.gtree("HEAD^{tree}")
|
|
296
235
|
|
|
297
236
|
tree.blobs
|
|
298
237
|
tree.subtrees
|
|
299
238
|
tree.children # blobs and subtrees
|
|
300
239
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
240
|
+
repo.rev_parse('v2.0.0:README.md')
|
|
241
|
+
|
|
242
|
+
repo.branches # returns Git::Branch objects
|
|
243
|
+
repo.branches.local
|
|
244
|
+
repo.current_branch
|
|
245
|
+
repo.branches.remote
|
|
246
|
+
repo.branches[:main].gcommit
|
|
247
|
+
repo.branches['origin/main'].gcommit
|
|
248
|
+
|
|
249
|
+
repo.grep('hello') # implies HEAD
|
|
250
|
+
repo.blob('v2.5:Makefile').grep('hello')
|
|
251
|
+
repo.tag('v2.5').grep('hello', 'docs/')
|
|
252
|
+
repo.describe()
|
|
253
|
+
repo.describe('0djf2aa')
|
|
254
|
+
repo.describe('HEAD', {:all => true, :tags => true})
|
|
255
|
+
|
|
256
|
+
repo.diff(commit1, commit2).size
|
|
257
|
+
repo.diff(commit1, commit2).stats
|
|
258
|
+
repo.diff(commit1, commit2).name_status
|
|
259
|
+
repo.gtree('v2.5').diff('v2.6').insertions
|
|
260
|
+
repo.diff('gitsearch1', 'v2.5').path('lib/')
|
|
261
|
+
repo.diff('gitsearch1', 'v2.5').path('lib/', 'docs/', 'README.md') # multiple paths
|
|
262
|
+
repo.diff('gitsearch1', repo.gtree('v2.5'))
|
|
263
|
+
repo.diff('gitsearch1', 'v2.5').path('docs/').patch
|
|
264
|
+
repo.gtree('v2.5').diff('v2.6').patch
|
|
265
|
+
|
|
266
|
+
repo.gtree('v2.5').diff('v2.6').each do |file_diff|
|
|
328
267
|
puts file_diff.path
|
|
329
268
|
puts file_diff.patch
|
|
330
269
|
puts file_diff.blob(:src).contents
|
|
331
270
|
end
|
|
332
271
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
272
|
+
repo.worktrees # returns Git::Worktree objects
|
|
273
|
+
repo.worktrees.count
|
|
274
|
+
repo.worktrees.each do |worktree|
|
|
336
275
|
worktree.dir
|
|
337
276
|
worktree.gcommit
|
|
338
277
|
worktree.to_s
|
|
339
278
|
end
|
|
340
279
|
|
|
341
|
-
|
|
342
|
-
|
|
280
|
+
repo.config('user.name') # returns 'Scott Chacon'
|
|
281
|
+
repo.config # returns whole config hash
|
|
343
282
|
|
|
344
283
|
# Configuration can be set when cloning using the :config option.
|
|
345
284
|
# This option can be an single configuration String or an Array
|
|
346
285
|
# if multiple config items need to be set.
|
|
347
286
|
#
|
|
348
|
-
|
|
287
|
+
repo = Git.clone(
|
|
349
288
|
git_uri, destination_path,
|
|
350
289
|
:config => [
|
|
351
290
|
'core.sshCommand=ssh -i /home/user/.ssh/id_rsa',
|
|
@@ -353,11 +292,11 @@ g = Git.clone(
|
|
|
353
292
|
]
|
|
354
293
|
)
|
|
355
294
|
|
|
356
|
-
|
|
295
|
+
repo.tags # returns array of Git::Tag objects
|
|
357
296
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
297
|
+
repo.show()
|
|
298
|
+
repo.show('HEAD')
|
|
299
|
+
repo.show('v2.8', 'README.md')
|
|
361
300
|
|
|
362
301
|
Git.ls_remote('https://github.com/ruby-git/ruby-git.git') # returns a hash containing the available references of the repo.
|
|
363
302
|
Git.ls_remote('/path/to/local/repo')
|
|
@@ -366,207 +305,316 @@ Git.ls_remote() # same as Git.ls_remote('.')
|
|
|
366
305
|
Git.default_branch('https://github.com/ruby-git/ruby-git') #=> 'main'
|
|
367
306
|
```
|
|
368
307
|
|
|
308
|
+
### Write Operations
|
|
309
|
+
|
|
369
310
|
And here are the operations that will need to write to your git repository.
|
|
370
311
|
|
|
371
312
|
```ruby
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
313
|
+
repo = Git.init # default is the current directory
|
|
314
|
+
repo = Git.init('project')
|
|
315
|
+
repo = Git.init(
|
|
316
|
+
'/home/schacon/proj',
|
|
317
|
+
{ :repository => '/opt/git/proj.git', :index => '/tmp/index'}
|
|
318
|
+
)
|
|
377
319
|
|
|
378
320
|
# Clone from a git url
|
|
379
321
|
git_url = 'https://github.com/ruby-git/ruby-git.git'
|
|
380
|
-
|
|
381
|
-
g = Git.clone(git_url)
|
|
322
|
+
repo = Git.clone(git_url)
|
|
382
323
|
|
|
383
324
|
# Clone into /tmp/clone/ruby-git-clean
|
|
384
325
|
name = 'ruby-git-clean'
|
|
385
326
|
path = '/tmp/clone'
|
|
386
|
-
|
|
387
|
-
|
|
327
|
+
repo = Git.clone(git_url, name, :path => path)
|
|
328
|
+
repo.dir #=> /tmp/clone/ruby-git-clean
|
|
388
329
|
|
|
389
|
-
|
|
390
|
-
|
|
330
|
+
repo.config('user.name', 'Scott Chacon')
|
|
331
|
+
repo.config('user.email', 'email@email.com')
|
|
391
332
|
|
|
392
333
|
# Clone can take a filter to tell the serve to send a partial clone
|
|
393
|
-
|
|
334
|
+
repo = Git.clone(git_url, name, :path => path, :filter => 'tree:0')
|
|
394
335
|
|
|
395
336
|
# Clone can control single-branch behavior (nil default keeps current git behavior)
|
|
396
|
-
|
|
337
|
+
repo = Git.clone(git_url, name, :path => path, :depth => 1, :single_branch => false)
|
|
397
338
|
|
|
398
339
|
# Clone can take an optional logger
|
|
399
|
-
logger = Logger.new
|
|
400
|
-
|
|
340
|
+
logger = Logger.new(STDOUT)
|
|
341
|
+
repo = Git.clone(git_url, 'my-repo', :log => logger)
|
|
401
342
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
343
|
+
repo.add # git add -- "."
|
|
344
|
+
repo.add(:all=>true) # git add --all -- "."
|
|
345
|
+
repo.add('file_path') # git add -- "file_path"
|
|
346
|
+
repo.add(['file_path_1', 'file_path_2']) # git add -- "file_path_1" "file_path_2"
|
|
406
347
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
348
|
+
repo.remove() # git rm -f -- "."
|
|
349
|
+
repo.remove('file.txt') # git rm -f -- "file.txt"
|
|
350
|
+
repo.remove(['file.txt', 'file2.txt']) # git rm -f -- "file.txt" "file2.txt"
|
|
351
|
+
repo.remove('file.txt', :recursive => true) # git rm -f -r -- "file.txt"
|
|
352
|
+
repo.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt"
|
|
412
353
|
|
|
413
|
-
|
|
414
|
-
|
|
354
|
+
repo.commit('message')
|
|
355
|
+
repo.commit_all('message')
|
|
415
356
|
|
|
416
357
|
# Sign a commit using the gpg key configured in the user.signingkey config setting
|
|
417
|
-
|
|
418
|
-
|
|
358
|
+
repo.config('user.signingkey', '0A46826A')
|
|
359
|
+
repo.commit('message', gpg_sign: true)
|
|
419
360
|
|
|
420
361
|
# Sign a commit using a specified gpg key
|
|
421
362
|
key_id = '0A46826A'
|
|
422
|
-
|
|
363
|
+
repo.commit('message', gpg_sign: key_id)
|
|
423
364
|
|
|
424
365
|
# Skip signing a commit (overriding any global gpgsign setting)
|
|
425
|
-
|
|
366
|
+
repo.commit('message', no_gpg_sign: true)
|
|
426
367
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
end
|
|
368
|
+
repo = Git.clone(git_url, 'myrepo')
|
|
369
|
+
repo.chdir do
|
|
370
|
+
File.write('test-file', 'blahblahblah')
|
|
371
|
+
repo.status.changed.each do |file|
|
|
372
|
+
puts file.blob(:index).contents
|
|
373
|
+
end
|
|
433
374
|
end
|
|
434
375
|
|
|
435
|
-
|
|
436
|
-
|
|
376
|
+
repo.reset # defaults to HEAD
|
|
377
|
+
repo.reset_hard(Git::Commit)
|
|
437
378
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
379
|
+
repo.branch('new_branch') # creates new or fetches existing
|
|
380
|
+
repo.branch('new_branch').checkout
|
|
381
|
+
repo.branch('new_branch').delete
|
|
382
|
+
repo.branch('existing_branch').checkout
|
|
383
|
+
repo.branch('main').contains?('existing_branch')
|
|
443
384
|
|
|
444
385
|
# delete remote branch
|
|
445
|
-
|
|
386
|
+
repo.push('origin', 'remote_branch_name', force: true, delete: true)
|
|
446
387
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
388
|
+
repo.checkout('new_branch')
|
|
389
|
+
repo.checkout('new_branch', new_branch: true, start_point: 'main')
|
|
390
|
+
repo.checkout(repo.branch('new_branch'))
|
|
450
391
|
|
|
451
|
-
|
|
452
|
-
|
|
392
|
+
repo.branch(name).merge(branch2)
|
|
393
|
+
repo.branch(branch2).merge # merges HEAD with branch2
|
|
453
394
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
395
|
+
repo.branch(name).in_branch(message) { # add files } # auto-commits
|
|
396
|
+
repo.merge('new_branch')
|
|
397
|
+
repo.merge('new_branch', 'merge commit message', no_ff: true)
|
|
398
|
+
repo.merge('origin/remote_branch')
|
|
399
|
+
repo.merge(repo.branch('main'))
|
|
400
|
+
repo.merge([branch1, branch2])
|
|
460
401
|
|
|
461
|
-
|
|
402
|
+
repo.merge_base('branch1', 'branch2')
|
|
462
403
|
|
|
463
|
-
r =
|
|
464
|
-
r =
|
|
404
|
+
r = repo.add_remote(name, uri) # Git::Remote
|
|
405
|
+
r = repo.add_remote(name, Git::Base) # Git::Remote
|
|
465
406
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
407
|
+
repo.remotes # array of Git::Remotes
|
|
408
|
+
repo.remote(name).fetch
|
|
409
|
+
repo.remote(name).remove
|
|
410
|
+
repo.remote(name).merge
|
|
411
|
+
repo.remote(name).merge(branch)
|
|
471
412
|
|
|
472
|
-
|
|
473
|
-
|
|
413
|
+
repo.remote_set_branches('origin', '*', add: true) # append additional fetch refspecs
|
|
414
|
+
repo.remote_set_branches('origin', 'feature', 'release/*') # replace fetch refspecs
|
|
474
415
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
416
|
+
repo.fetch
|
|
417
|
+
repo.fetch(repo.remotes.first)
|
|
418
|
+
repo.fetch('origin', {:ref => 'some/ref/head'} )
|
|
419
|
+
repo.fetch(all: true, force: true, depth: 2)
|
|
420
|
+
repo.fetch('origin', {:'update-head-ok' => true})
|
|
480
421
|
|
|
481
|
-
|
|
482
|
-
|
|
422
|
+
repo.pull
|
|
423
|
+
repo.pull(Git::Repo, Git::Branch) # fetch and a merge
|
|
483
424
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
425
|
+
repo.add_tag('tag_name') # returns Git::Tag
|
|
426
|
+
repo.add_tag('tag_name', 'object_reference')
|
|
427
|
+
repo.add_tag('tag_name', 'object_reference', {:options => 'here'})
|
|
428
|
+
repo.add_tag('tag_name', {:options => 'here'})
|
|
488
429
|
|
|
489
|
-
|
|
490
|
-
:a | :annotate
|
|
491
|
-
:d
|
|
492
|
-
:f
|
|
493
|
-
:m | :message
|
|
494
|
-
:s
|
|
430
|
+
repo.delete_tag('tag_name')
|
|
495
431
|
|
|
496
|
-
|
|
432
|
+
repo.repack
|
|
497
433
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
g.push
|
|
501
|
-
g.push(g.remote('name'))
|
|
434
|
+
repo.push
|
|
435
|
+
repo.push(repo.remote('name'))
|
|
502
436
|
|
|
503
437
|
# delete remote branch
|
|
504
|
-
|
|
438
|
+
repo.push('origin', 'remote_branch_name', force: true, delete: true)
|
|
505
439
|
|
|
506
440
|
# push all branches to remote at one time
|
|
507
|
-
|
|
441
|
+
repo.push('origin', all: true)
|
|
508
442
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
443
|
+
repo.worktree('/tmp/new_worktree').add
|
|
444
|
+
repo.worktree('/tmp/new_worktree', 'branch1').add
|
|
445
|
+
repo.worktree('/tmp/new_worktree').remove
|
|
446
|
+
repo.worktrees.prune
|
|
513
447
|
```
|
|
514
448
|
|
|
449
|
+
### Index and Tree Operations
|
|
450
|
+
|
|
515
451
|
Some examples of more low-level index and tree operations
|
|
516
452
|
|
|
517
453
|
```ruby
|
|
518
|
-
|
|
454
|
+
repo.with_temp_index do
|
|
519
455
|
|
|
520
|
-
|
|
521
|
-
|
|
456
|
+
repo.read_tree(tree3) # calls self.index.read_tree
|
|
457
|
+
repo.read_tree(tree1, :prefix => 'hi/')
|
|
522
458
|
|
|
523
|
-
c =
|
|
459
|
+
c = repo.commit_tree('message')
|
|
524
460
|
# or #
|
|
525
|
-
t =
|
|
526
|
-
c =
|
|
461
|
+
t = repo.write_tree
|
|
462
|
+
c = repo.commit_tree(t, :message => 'message', :parents => [sha1, sha2])
|
|
527
463
|
|
|
528
|
-
|
|
529
|
-
|
|
464
|
+
repo.branch('branch_name').update_ref(c)
|
|
465
|
+
repo.update_ref(branch, c)
|
|
530
466
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
467
|
+
repo.with_temp_working do # new blank working directory
|
|
468
|
+
repo.checkout
|
|
469
|
+
repo.checkout(another_index)
|
|
470
|
+
repo.commit # commits to temp_index
|
|
535
471
|
end
|
|
536
472
|
end
|
|
537
473
|
|
|
538
|
-
|
|
474
|
+
repo.set_index('/path/to/index')
|
|
539
475
|
|
|
540
|
-
|
|
541
|
-
g.with_index(path) do
|
|
476
|
+
repo.with_index(path) do
|
|
542
477
|
# calls set_index, then switches back after
|
|
543
478
|
end
|
|
544
479
|
|
|
545
|
-
|
|
480
|
+
repo.with_working(dir) do
|
|
546
481
|
# calls set_working, then switches back after
|
|
547
482
|
end
|
|
548
483
|
|
|
549
|
-
|
|
550
|
-
|
|
484
|
+
repo.with_temp_working(dir) do
|
|
485
|
+
repo.checkout_index(:prefix => dir, :path_limiter => path)
|
|
551
486
|
# do file work
|
|
552
|
-
|
|
487
|
+
repo.commit # commits to index
|
|
488
|
+
end
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## Errors Raised By This Gem
|
|
492
|
+
|
|
493
|
+
The git gem will only raise an `ArgumentError` or an error that is a subclass of
|
|
494
|
+
`Git::Error`. It does not explicitly raise any other types of errors.
|
|
495
|
+
|
|
496
|
+
It is recommended to rescue `Git::Error` to catch any runtime error raised by this
|
|
497
|
+
gem unless you need more specific error handling.
|
|
498
|
+
|
|
499
|
+
```ruby
|
|
500
|
+
begin
|
|
501
|
+
# some git operation
|
|
502
|
+
rescue Git::Error => e
|
|
503
|
+
puts "An error occurred: #{e.message}"
|
|
553
504
|
end
|
|
554
505
|
```
|
|
555
506
|
|
|
556
|
-
|
|
507
|
+
See [`Git::Error`](https://rubydoc.info/gems/git/Git/Error) for more information.
|
|
508
|
+
|
|
509
|
+
## Specifying And Handling Timeouts
|
|
510
|
+
|
|
511
|
+
The timeout feature was added in git gem version `2.0.0`.
|
|
512
|
+
|
|
513
|
+
A timeout for git command line operations can be set either globally or for specific
|
|
514
|
+
method calls that accept a `:timeout` parameter.
|
|
515
|
+
|
|
516
|
+
The timeout value must be a real, non-negative `Numeric` value that specifies a
|
|
517
|
+
number of seconds a `git` command will be given to complete before being sent a KILL
|
|
518
|
+
signal. This library may hang if the `git` command does not terminate after receiving
|
|
519
|
+
the KILL signal.
|
|
557
520
|
|
|
558
|
-
|
|
521
|
+
When a command times out, it is killed by sending it the `SIGKILL` signal and a
|
|
522
|
+
`Git::TimeoutError` is raised. This error derives from the `Git::SignaledError` and
|
|
523
|
+
`Git::Error`.
|
|
524
|
+
|
|
525
|
+
If the timeout value is `0` or `nil`, no timeout will be enforced.
|
|
559
526
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
527
|
+
If a method accepts a `:timeout` parameter and a receives a non-nil value, the value
|
|
528
|
+
of this parameter will override the global timeout value. In this context, a value of
|
|
529
|
+
`nil` (which is usually the default) will use the global timeout value and a value of
|
|
530
|
+
`0` will turn off timeout enforcement for that method call no matter what the global
|
|
531
|
+
value is.
|
|
563
532
|
|
|
564
|
-
|
|
565
|
-
once the following JRuby bug is fixed:
|
|
533
|
+
To set a global timeout, use the `Git.config` object:
|
|
566
534
|
|
|
567
|
-
|
|
535
|
+
```ruby
|
|
536
|
+
Git.config.timeout = nil # a value of nil or 0 means no timeout is enforced
|
|
537
|
+
Git.config.timeout = 1.5 # can be any real, non-negative Numeric interpreted as number of seconds
|
|
538
|
+
```
|
|
568
539
|
|
|
569
|
-
|
|
540
|
+
The global timeout can be overridden for a specific method if the method accepts a
|
|
541
|
+
`:timeout` parameter:
|
|
542
|
+
|
|
543
|
+
```ruby
|
|
544
|
+
repo_url = 'https://github.com/ruby-git/ruby-git.git'
|
|
545
|
+
Git.clone(repo_url) # Use the global timeout value
|
|
546
|
+
Git.clone(repo_url, timeout: nil) # Also uses the global timeout value
|
|
547
|
+
Git.clone(repo_url, timeout: 0) # Do not enforce a timeout
|
|
548
|
+
Git.clone(repo_url, timeout: 10.5) # Timeout after 10.5 seconds raising Git::SignaledError
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
If the command takes too long, a `Git::TimeoutError` will be raised:
|
|
552
|
+
|
|
553
|
+
```ruby
|
|
554
|
+
begin
|
|
555
|
+
Git.clone(repo_url, timeout: 10)
|
|
556
|
+
rescue Git::TimeoutError => e
|
|
557
|
+
e.result.tap do |r|
|
|
558
|
+
r.class #=> Git::CommandLineResult
|
|
559
|
+
r.status #=> #<Process::Status: pid 62173 SIGKILL (signal 9)>
|
|
560
|
+
r.status.timeout? #=> true
|
|
561
|
+
r.git_cmd # The git command ran as an array of strings
|
|
562
|
+
r.stdout # The command's output to stdout until it was terminated
|
|
563
|
+
r.stderr # The command's output to stderr until it was terminated
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
## Deprecations
|
|
569
|
+
|
|
570
|
+
This gem uses ActiveSupport's deprecation mechanism to report deprecation warnings.
|
|
571
|
+
|
|
572
|
+
You can silence deprecation warnings by adding this line to your source code:
|
|
573
|
+
|
|
574
|
+
```ruby
|
|
575
|
+
Git::Deprecation.behavior = :silence
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
See [the Active Support Deprecation
|
|
579
|
+
documentation](https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.html)
|
|
580
|
+
for more details.
|
|
581
|
+
|
|
582
|
+
If deprecation warnings are silenced, you should reenable them before upgrading the
|
|
583
|
+
git gem to the next major version. This will make it easier to identify changes
|
|
584
|
+
needed for the upgrade.
|
|
585
|
+
|
|
586
|
+
## Project Policies
|
|
587
|
+
|
|
588
|
+
These documents set expectations for behavior, contribution workflows, AI-assisted
|
|
589
|
+
changes, decision making, maintainer roles, and licensing. Please review them before
|
|
590
|
+
opening issues or pull requests.
|
|
591
|
+
|
|
592
|
+
| Document | Description |
|
|
593
|
+
| -------- | ----------- |
|
|
594
|
+
| [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) | We follow the Ruby community Code of Conduct; expect respectful, harassment-free participation and report concerns to maintainers. |
|
|
595
|
+
| [CONTRIBUTING](CONTRIBUTING.md) | How to report issues, submit PRs with Conventional Commits, meet coding/testing standards, and follow the Code of Conduct. |
|
|
596
|
+
| [AI_POLICY](AI_POLICY.md) | AI-assisted contributions are welcome. Contributors are expected to read and apply the AI Policy, and ensure any AI-assisted work meets our quality, security, and licensing standards. |
|
|
597
|
+
| [Ruby version support policy](#ruby-version-support-policy) | Supported Ruby runtimes and platforms; bump decisions and CI coverage expectations. |
|
|
598
|
+
| [Git version support policy](#git-version-support-policy) | Minimum supported git version and how version bumps are communicated and enforced. |
|
|
599
|
+
| [GOVERNANCE](GOVERNANCE.md) | Principles-first governance defining maintainer/project lead roles, least-privilege access, consensus/majority decisions, and nomination/emeritus steps. |
|
|
600
|
+
| [MAINTAINERS](MAINTAINERS.md) | Lists active maintainers (Project Lead noted) and emeritus alumni with links; see governance for role scope. |
|
|
601
|
+
| [LICENSE](LICENSE) | MIT License terms for using, modifying, and redistributing this project. |
|
|
602
|
+
|
|
603
|
+
### Ruby Version Support Policy
|
|
604
|
+
|
|
605
|
+
This gem is expected to function correctly on:
|
|
606
|
+
|
|
607
|
+
- All [non-EOL versions](https://www.ruby-lang.org/en/downloads/branches/) of the MRI
|
|
608
|
+
Ruby on Mac, Linux, and Windows
|
|
609
|
+
- The latest version of JRuby 9.4+ on Linux
|
|
610
|
+
- The latest version of TruffleRuby 24+ on Linux
|
|
611
|
+
|
|
612
|
+
It is this project's intent to support the latest version of JRuby on Windows once
|
|
613
|
+
the [process_executer](https://github.com/main-branch/process_executer) gem properly
|
|
614
|
+
supports subprocess status reporting on JRuby for Windows (see
|
|
615
|
+
[main-branch/process_executer#156](https://github.com/main-branch/process_executer/issues/156)).
|
|
616
|
+
|
|
617
|
+
### Git Version Support Policy
|
|
570
618
|
|
|
571
619
|
This gem requires git version 2.28.0 or greater as specified in the gemspec. This
|
|
572
620
|
requirement reflects:
|
|
@@ -585,12 +633,18 @@ gem as new git features are adopted or as maintaining backward compatibility bec
|
|
|
585
633
|
impractical. Such changes will be clearly documented in the CHANGELOG and release
|
|
586
634
|
notes.
|
|
587
635
|
|
|
588
|
-
##
|
|
636
|
+
## 📢 Project Announcements 📢
|
|
589
637
|
|
|
590
|
-
|
|
591
|
-
details.
|
|
638
|
+
### 2026-01-07: AI Policy Introduced
|
|
592
639
|
|
|
593
|
-
|
|
640
|
+
We have adopted a formal [AI Policy](AI_POLICY.md) to clarify expectations for
|
|
641
|
+
AI-assisted contributions. Please review it before opening a PR to ensure your
|
|
642
|
+
changes are fully understood, meet our quality bar, and respect licensing
|
|
643
|
+
requirements.
|
|
644
|
+
|
|
645
|
+
We chose a principles-based policy to respect contributors’ time and expertise. It’s
|
|
646
|
+
quick to read, easy to remember, and avoids unnecessary policy overhead while still
|
|
647
|
+
setting clear expectations.
|
|
594
648
|
|
|
595
649
|
### 2025-07-09: Architectural Redesign
|
|
596
650
|
|
|
@@ -643,11 +697,12 @@ rake rubocop
|
|
|
643
697
|
RuboCop is also run as part of the default rake task (by running `rake`) that is run
|
|
644
698
|
in our Continuous Integration workflow.
|
|
645
699
|
|
|
646
|
-
Going forward, any PRs that have any Robocop offenses will not be merged. In
|
|
647
|
-
|
|
648
|
-
|
|
700
|
+
Going forward, any PRs that have any Robocop offenses will not be merged. In certain
|
|
701
|
+
rare cases, it might be acceptable to disable a RuboCop check for the most limited
|
|
702
|
+
scope possible.
|
|
649
703
|
|
|
650
|
-
If you have a problem fixing a RuboCop offense, don't be afraid to ask a
|
|
704
|
+
If you have a problem fixing a RuboCop offense, don't be afraid to ask a
|
|
705
|
+
contributor.
|
|
651
706
|
|
|
652
707
|
### 2025-06-06: Default Branch Rename
|
|
653
708
|
|
data/lib/git/log.rb
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Git
|
|
4
|
-
# Builds and executes a `git log` query
|
|
4
|
+
# Builds and executes a `git log` query
|
|
5
5
|
#
|
|
6
6
|
# This class provides a fluent interface for building complex `git log` queries.
|
|
7
|
+
#
|
|
8
|
+
# Queries default to returning 30 commits; call {#max_count} with `:all` to
|
|
9
|
+
# return every matching commit. Calling {#all} adds the `--all` flag to include
|
|
10
|
+
# all refs in the search but does not change the number of commits returned.
|
|
11
|
+
#
|
|
7
12
|
# The query is lazily executed when results are requested either via the modern
|
|
8
13
|
# `#execute` method or the deprecated Enumerable methods.
|
|
9
14
|
#
|
data/lib/git/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: git
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.1.
|
|
4
|
+
version: 4.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Chacon and others
|
|
@@ -250,8 +250,11 @@ files:
|
|
|
250
250
|
- ".rubocop.yml"
|
|
251
251
|
- ".rubocop_todo.yml"
|
|
252
252
|
- ".yardopts"
|
|
253
|
+
- AI_POLICY.md
|
|
253
254
|
- CHANGELOG.md
|
|
255
|
+
- CODE_OF_CONDUCT.md
|
|
254
256
|
- CONTRIBUTING.md
|
|
257
|
+
- GOVERNANCE.md
|
|
255
258
|
- Gemfile
|
|
256
259
|
- LICENSE
|
|
257
260
|
- MAINTAINERS.md
|
|
@@ -305,8 +308,8 @@ licenses:
|
|
|
305
308
|
metadata:
|
|
306
309
|
homepage_uri: http://github.com/ruby-git/ruby-git
|
|
307
310
|
source_code_uri: http://github.com/ruby-git/ruby-git
|
|
308
|
-
changelog_uri: https://rubydoc.info/gems/git/4.1.
|
|
309
|
-
documentation_uri: https://rubydoc.info/gems/git/4.1.
|
|
311
|
+
changelog_uri: https://rubydoc.info/gems/git/4.1.1/file/CHANGELOG.md
|
|
312
|
+
documentation_uri: https://rubydoc.info/gems/git/4.1.1
|
|
310
313
|
rubygems_mfa_required: 'true'
|
|
311
314
|
rdoc_options: []
|
|
312
315
|
require_paths:
|