git 5.0.2 → 5.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94d97e48dd1d4b34affe837d38258f7b0f7edf02338d0e0def333ac80e147244
4
- data.tar.gz: 5367c11505c46d9745d492a97671346531fddfdc3649b445bae9eb2636f87202
3
+ metadata.gz: 6dcf907e2c0ccb6d916a9aa1d43f6c768e49555465a484e0231d919cb889b889
4
+ data.tar.gz: 5cce608675a41031f79318065e8c11125f9f23a154ab2ae6f578192010b04367
5
5
  SHA512:
6
- metadata.gz: 4e404e6b31961cf3c71e391ce4898436f07de8dd2ffc37947281f103513241c531e21aa799ae32296ec6ef47d2b1dad465205fd3b0936ee104b6774870805391
7
- data.tar.gz: 778bbd70beb547b4574e8d361acc2873320b42bd4b5f190012309a3b90da72d55468a8c5b4adf87a3ed773ab08945e7ac81b3d282c86bb8bda64821282a3c101
6
+ metadata.gz: 42dbbce6613ecd406e64771bb03d85416a4eae0fe12183fee03640292f5f18700175788c35c55836ad2d572bde6857421ed6cae8f9d7520dcd8bd12b498ae809
7
+ data.tar.gz: d55dd4bd23e700aacd23d8b850adada2e0e3a8f90176515e5de3b5213e43282ac5e8e105d500243bc54a0655472368e00becf4b6c01e59e4baf842223f8f89a7
@@ -0,0 +1,14 @@
1
+ ---
2
+ description: Address all unresolved Copilot review threads on the active pull request
3
+ argument-hint: "[PR number — defaults to the PR for the current branch]"
4
+ ---
5
+
6
+ Follow the shared agent prompt in
7
+ `.github/prompts/iteratively-address-copilot-reviews.prompt.md` exactly. That file
8
+ is the canonical instructions for this task and is shared with other AI agents; read
9
+ it before doing anything else.
10
+
11
+ @.github/prompts/iteratively-address-copilot-reviews.prompt.md
12
+
13
+ If `$ARGUMENTS` is non-empty, treat it as the pull request number to operate on
14
+ instead of detecting the PR from the current branch.
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "\"$CLAUDE_PROJECT_DIR/.github/hooks/run-bin-setup-once.sh\"",
10
+ "timeout": 900
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
16
+ }
data/.claude/skills ADDED
@@ -0,0 +1 @@
1
+ ../.github/skills
@@ -22,18 +22,6 @@ fine to use `#` in footer values such as `Closes: #999` or `Refs: #999`.
22
22
  - **RuboCop:** Use `RuboCop` for prose and `rubocop` for CLI or gem names. Never use
23
23
  `Rubocop`.
24
24
 
25
- ## Project Commands
26
-
27
- | Purpose | Command |
28
- | --- | --- |
29
- | First-time project or new worktree setup | `bin/setup` |
30
- | Run all tests and linters (CI-equivalent) | `bundle exec rake` |
31
- | Run all RSpec tests | `bundle exec rake spec` |
32
- | Run RSpec unit tests | `bundle exec rake spec:unit` |
33
- | Run RSpec integration tests | `bundle exec rake spec:integration` |
34
- | Run a specific RSpec spec | `bundle exec rspec <path>` |
35
- | Run linters | `bundle exec rake rubocop yard build` |
36
-
37
25
  ## Branch & PR Strategy
38
26
 
39
27
  | Target | When |
@@ -1,12 +1,18 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
+ # This hook is shared by every agent configured for this repo (GitHub Copilot via
5
+ # .github/hooks/, Claude Code via .claude/settings.json), so do not assume the
6
+ # caller's working directory.
7
+ command -v git >/dev/null 2>&1 || exit 0
8
+ cd "$(dirname "${BASH_SOURCE[0]}")/../.." || exit 0
9
+
4
10
  # Skip if this repo does not use bin/setup.
5
11
  [[ -x "./bin/setup" ]] || exit 0
6
12
 
7
- # Keep setup idempotent per-worktree.
8
- command -v git >/dev/null 2>&1 || exit 0
9
- marker="$(git rev-parse --git-path copilot-bin-setup.done 2>/dev/null)" || exit 0
13
+ # Keep setup idempotent per-worktree. The marker is shared across agents so that
14
+ # cloning and opening the repo in two different tools does not run setup twice.
15
+ marker="$(git rev-parse --git-path agent-bin-setup.done 2>/dev/null)" || exit 0
10
16
  [[ -f "$marker" ]] && exit 0
11
17
 
12
18
  ./bin/setup
@@ -16,4 +16,6 @@ Review our [guidelines for contributing](https://github.com/ruby-git/ruby-git/bl
16
16
  - [ ] I ran `bundle exec rake` locally on this branch and it passed (see
17
17
  [Local development setup](../CONTRIBUTING.md#local-development-setup)).
18
18
  - [ ] Tests added/updated as needed.
19
+ - [ ] `bundle exec rake spec:unit` reports 100% line and branch coverage (see
20
+ [Test coverage policy](../CONTRIBUTING.md#test-coverage-policy)).
19
21
  - [ ] Documentation updated where applicable (README and/or YARD).
@@ -908,7 +908,7 @@ For migration PRs, verify process constraints:
908
908
  - each slice is independently revertible
909
909
  - refactor-only changes are not mixed with unrelated behavior changes
910
910
  - quality gates pass for the slice — discover tasks via
911
- `bundle exec ruby -e "require 'rake'; load 'Rakefile'; puts Rake::Task['default:parallel'].prerequisites"`
911
+ `bundle exec ruby -e "require 'rake'; load 'Rakefile'; puts Rake::Task['default'].prerequisites"`
912
912
  and run each individually via `bundle exec rake <task>`, fixing failures before
913
913
  advancing
914
914
 
@@ -188,11 +188,11 @@ This skill supports three modes. Determine which mode applies before starting:
188
188
  requirements](REFERENCE.md#phased-rollout-requirements).
189
189
 
190
190
  5. **Run quality gates** — discover the prerequisite tasks for
191
- `default:parallel` and run them sequentially, fixing failures before
191
+ `default` and run them sequentially, fixing failures before
192
192
  advancing:
193
193
 
194
194
  ```bash
195
- bundle exec ruby -e "require 'rake'; load 'Rakefile'; puts Rake::Task['default:parallel'].prerequisites"
195
+ bundle exec ruby -e "require 'rake'; load 'Rakefile'; puts Rake::Task['default'].prerequisites"
196
196
  ```
197
197
 
198
198
  Run each listed task **individually** in order via `bundle exec rake <task>`
@@ -224,11 +224,11 @@ This skill supports three modes. Determine which mode applies before starting:
224
224
  - has tests that verify call-shape compatibility when classification is
225
225
  `legacy-contract` (positional hash and/or keyword-arg / `**opts` forms where required)
226
226
 
227
- 5. **Run quality gates** — discover the prerequisite tasks for `default:parallel`
227
+ 5. **Run quality gates** — discover the prerequisite tasks for `default`
228
228
  and run them sequentially, fixing failures before advancing:
229
229
 
230
230
  ```bash
231
- bundle exec ruby -e "require 'rake'; load 'Rakefile'; puts Rake::Task['default:parallel'].prerequisites"
231
+ bundle exec ruby -e "require 'rake'; load 'Rakefile'; puts Rake::Task['default'].prerequisites"
232
232
  ```
233
233
 
234
234
  Run each listed task **individually** in order via `bundle exec rake <task>`
@@ -68,9 +68,13 @@ Adoption and enforcement notes:
68
68
  - Apply these rules as hard requirements for new and modified unit specs.
69
69
  - Legacy specs may violate some rules; treat those as incremental cleanup work.
70
70
  - Branch and line coverage are both reported by SimpleCov in this repository.
71
- - `coverage_threshold: 100` is configured, but `fail_on_low_coverage` is currently
72
- `false`; enforce Rule 21 during review by checking the coverage report until
73
- strict failure is enabled.
71
+ - `minimum_coverage: { line: 100, branch: 100 }` is configured and enforced: a full
72
+ `rake spec:unit` run fails when either threshold is missed, and CI fails the pull
73
+ request with it. Rule 21 is a build gate, not just a review check. See the
74
+ [Test coverage policy](../../../CONTRIBUTING.md#test-coverage-policy) in
75
+ `CONTRIBUTING.md` for the full policy.
76
+ - Focused runs (`SPEC=<glob> rake spec:unit`, or `rspec <file>`) report coverage but
77
+ do not fail on it, since they load all of `lib/` while exercising only a slice.
74
78
 
75
79
  ## Related skills
76
80
 
@@ -484,10 +488,50 @@ Every conditional path through the public interface must be exercised by at leas
484
488
  one example. If a branch cannot be reached through the public interface, that is a
485
489
  design smell.
486
490
 
491
+ This is enforced by the build: a full `rake spec:unit` run fails below 100% line or
492
+ branch coverage, and the failure output names each uncovered line and branch.
493
+
494
+ When a branch is hard to cover, apply these in order:
495
+
496
+ 1. **Reach it through the public interface** — if it is reachable, test it.
497
+ 2. **Delete it** — a branch unreachable through the public interface is usually dead
498
+ code. Removing it is preferable to excluding it.
499
+ 3. **Exclude it with `# simplecov:disable`** — the last resort, per the exception below.
500
+
487
501
  > **Exception:** Defensive guards that require breaking OS-level invariants to reach
488
502
  > (e.g., `raise "unreachable"` that would require triggering out-of-memory) may be
489
- > excluded. Mark them explicitly with `# :nocov:` and a brief comment explaining why
490
- > — never leave branches silently uncovered.
503
+ > excluded. Mark them explicitly with a `# simplecov:disable` directive carrying a
504
+ > reason — never leave branches silently uncovered. Cover the smallest possible span,
505
+ > and expect a reviewer to challenge it. `lib/` currently contains no coverage
506
+ > directives.
507
+
508
+ Prefer the inline form for a single line. It applies only to its own line and needs no
509
+ matching `enable`, so a region can never be left open by accident:
510
+
511
+ ```ruby
512
+ raise 'unreachable' # simplecov:disable defensive guard; only reachable on OOM
513
+ ```
514
+
515
+ Use the block form only for a genuine span, and close it explicitly:
516
+
517
+ ```ruby
518
+ # simplecov:disable branch platform-specific fallback; not reachable on MRI
519
+ ...
520
+ # simplecov:enable branch
521
+ ```
522
+
523
+ Always name the narrowest criterion that solves the problem — `line`, `branch`,
524
+ `method`, or a comma-separated combination — and write the reason after it, so the
525
+ required justification lives in the directive.
526
+
527
+ > **Review check:** verify the criterion is spelled exactly. A word SimpleCov does not
528
+ > recognize is parsed as free-form reason text, which silently widens the directive to
529
+ > all three criteria rather than failing.
530
+
531
+ > **Coverage is a floor on evidence, not a proof of correctness.** Never write an
532
+ > example whose only purpose is to execute a line. Such a test turns the report green
533
+ > while violating [Rule 24](#rule-24-must-assert-observable-behavior-not-implementation-details),
534
+ > and must be rejected in review.
491
535
 
492
536
  ### Rule 22 (MUST): Error assertions must specify both the error class and a message pattern
493
537
 
@@ -614,7 +658,9 @@ After writing or modifying tests, verify compliance before finishing:
614
658
 
615
659
  1. **Run the specs:** `bundle exec rspec spec/unit/path/to_spec.rb`
616
660
  2. **Check branch coverage** meets 100% (Rule 21) — open `coverage/index.html` and
617
- confirm no uncovered branches in the class under test.
661
+ confirm no uncovered lines or branches in the class under test. A focused run
662
+ reports coverage but does not fail on it; `bundle exec rake spec:unit` is the
663
+ authority and will fail below 100%, naming each uncovered line and branch.
618
664
  3. **Re-check MUST rules.** Scan the spec against every MUST rule. Fix violations.
619
665
  4. **Run in random order** (Rule 27): `bundle exec rspec spec/unit/path/to_spec.rb --order rand`
620
666
 
@@ -53,5 +53,17 @@ jobs:
53
53
  run: bundle exec rake default
54
54
  timeout-minutes: 15
55
55
 
56
+ # The unit suite enforces 100% line and branch coverage (see the "Test coverage
57
+ # policy" section of CONTRIBUTING.md). The failure log names the uncovered lines
58
+ # and branches; this artifact adds the browsable HTML report for the same run.
59
+ - name: Upload Coverage Report
60
+ if: failure()
61
+ uses: actions/upload-artifact@v7
62
+ with:
63
+ name: coverage-ruby-${{ matrix.ruby }}-${{ matrix.operating-system }}
64
+ path: coverage/
65
+ if-no-files-found: ignore
66
+ retention-days: 7
67
+
56
68
  - name: Test Gem
57
69
  run: bundle exec rake test:gem
data/.gitignore CHANGED
@@ -25,3 +25,6 @@ git-reference/
25
25
  git-versions/
26
26
 
27
27
  tmp
28
+
29
+ # per-developer Claude Code overrides (shared config is in .claude/settings.json)
30
+ .claude/settings.local.json
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "5.0.2"
2
+ ".": "5.0.3"
3
3
  }
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --require spec_helper
2
- --format Fuubar
3
2
  --color
data/CHANGELOG.md CHANGED
@@ -5,6 +5,47 @@
5
5
 
6
6
  # Change Log
7
7
 
8
+ ## [5.0.3](https://github.com/ruby-git/ruby-git/compare/v5.0.2...v5.0.3) (2026-08-07)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Drop unsupported -- separator from remote remove/rename commands ([8ec466f](https://github.com/ruby-git/ruby-git/commit/8ec466f8b282a5e94abd7d499bc26a92d94b2fc3))
14
+ * Remove unreachable case branch in Patch#apply_file_mode ([896fc49](https://github.com/ruby-git/ruby-git/commit/896fc49e3c2c03c401fe1b213c3f75bb40730521))
15
+ * Remove unreachable nil check in Git::Parsers::Grep.parse ([74e919a](https://github.com/ruby-git/ruby-git/commit/74e919a401126ad4415615f92cc9597e966239c6))
16
+
17
+
18
+ ### Other Changes
19
+
20
+ * Add Claude Code support alongside GitHub Copilot ([37f7d6a](https://github.com/ruby-git/ruby-git/commit/37f7d6a14c6d53bcf5b9644b8023d323290a5977))
21
+ * Add unit spec for Git::EncodingUtils ([5f0f10e](https://github.com/ruby-git/ruby-git/commit/5f0f10e4db78324bbe453de49598564a25f3428a))
22
+ * Consolidate parallel and serial spec rake tasks ([49616b1](https://github.com/ruby-git/ruby-git/commit/49616b12f52c6941a8617afbf7c56e7d7d5fe0f6))
23
+ * Cover :index option in Git::Factories#worktree_open_options_after_init ([efeba22](https://github.com/ruby-git/ruby-git/commit/efeba2294bb05327489a6523c46f26dc7392a84e))
24
+ * Cover #path when both src and dst are nil ([3a1a05a](https://github.com/ruby-git/ruby-git/commit/3a1a05a9be13057a1fc304df5008866634179124))
25
+ * Cover edge-case branches in Git::Parsers::Diff ([38d8b3f](https://github.com/ruby-git/ruby-git/commit/38d8b3f88f4f76a65776e9f6b8b87c6bb839e710))
26
+ * Cover Errno::ESRCH timeout-race rescue in run_process_executer ([899bf36](https://github.com/ruby-git/ruby-git/commit/899bf36399489038524cecf1d7ac2c606df03bde))
27
+ * Cover Git::Branch#merge ([71c0ea3](https://github.com/ruby-git/ruby-git/commit/71c0ea39d4c786a38245a8fb95fd93235ee03903))
28
+ * Cover Git::Branch#stashes ([27ba130](https://github.com/ruby-git/ruby-git/commit/27ba130a6cd3ef78171d1bb20230459c3f678a3a))
29
+ * Cover Git::Diff#name_status ([fa2ee98](https://github.com/ruby-git/ruby-git/commit/fa2ee98fd4613177843d285f7bc4a2ffb44ca79c))
30
+ * Cover Git::Factories#parse_clone_stderr unparseable-output branch ([65aa9b9](https://github.com/ruby-git/ruby-git/commit/65aa9b9318c7f8a8986c2aaae7dd0af0aeec4d69))
31
+ * Cover Git::Parsers::CatFile.each_header without trailing separator ([b7a9ed9](https://github.com/ruby-git/ruby-git/commit/b7a9ed93e03dcbd22a4fb25e9bb7b9c49647262d))
32
+ * Cover Git::Parsers::LsTree.parse with no tab-separated filename ([98b9ebf](https://github.com/ruby-git/ruby-git/commit/98b9ebf03c49f51c76b2e56dd670a9f68f220da8))
33
+ * Cover Git::Parsers::Remote.apply_pair unrecognized-variable branch ([03b10f6](https://github.com/ruby-git/ruby-git/commit/03b10f618a2f012b578ab995120cedbcd96ed8d1))
34
+ * Cover Git::Stashes#save ([7bca04c](https://github.com/ruby-git/ruby-git/commit/7bca04c53e64c747627784773d0c03ad0b9ff2e3))
35
+ * Cover Git.const_missing fallback branch for unrelated constants ([05c3c43](https://github.com/ruby-git/ruby-git/commit/05c3c4350e18bf1403fa314902708cfc40848c70))
36
+ * Cover Git.export ([4bd7f58](https://github.com/ruby-git/ruby-git/commit/4bd7f58432a19385ff55aecca9e89e2d9a96fa4a))
37
+ * Cover normalize_fetch_keys with a String option key ([47fb7fe](https://github.com/ruby-git/ruby-git/commit/47fb7fe061df9177a26ec7ada90b35b902ffc1df))
38
+ * Disable coverage for spec:integration, add SPEC filtering, fix formatters ([cb53d03](https://github.com/ruby-git/ruby-git/commit/cb53d03f8b671873f24368aadcafec638de32345))
39
+ * Document the project test coverage policy ([d378c1e](https://github.com/ruby-git/ruby-git/commit/d378c1e8b75e0c4209e17cc040ed36eb93053797))
40
+ * Enforce 100% unit test coverage on pull requests ([a446098](https://github.com/ruby-git/ruby-git/commit/a446098af548039b2c8b68bbb6562a53cb79fe40))
41
+ * Guard checkout-index nonexistent-path spec for git &lt; 2.30.0 ([cf212a9](https://github.com/ruby-git/ruby-git/commit/cf212a98b41218a7940ce54aa9b7c56a630412c3))
42
+ * Guard worktree repair spec for git &lt; 2.29.0 ([c527fb1](https://github.com/ruby-git/ruby-git/commit/c527fb15c2f21f9be5913192d43c847cf49681eb))
43
+ * **merge:** Fix incorrect version-gated failure expectation in quit_spec ([24c5ba4](https://github.com/ruby-git/ruby-git/commit/24c5ba4ce77b02413485d226a94b283f6af9d110))
44
+ * Read the gem version without loading lib/git/version.rb ([45c4b14](https://github.com/ruby-git/ruby-git/commit/45c4b14e944fcb43bda800823e377cf954ce2d3b))
45
+ * Require git 2.39.0 for maintenance register/unregister --config-file specs ([5b1fd52](https://github.com/ruby-git/ruby-git/commit/5b1fd527c39e4b3f1796851795a44694d94f4402))
46
+ * Skip get-urlmatch scope spec on git &lt; 2.42.0 ([e1ede7a](https://github.com/ruby-git/ruby-git/commit/e1ede7adddea28b654a183c618fc2336b5ffb83b))
47
+ * Upgrade simplecov and simplecov-rspec to ~&gt; 1.0 ([65e92b9](https://github.com/ruby-git/ruby-git/commit/65e92b9a9a621435efbf2a0855d48c47bb62425d))
48
+
8
49
  ## [5.0.2](https://github.com/ruby-git/ruby-git/compare/v5.0.1...v5.0.2) (2026-08-02)
9
50
 
10
51
 
data/CLAUDE.md ADDED
@@ -0,0 +1,11 @@
1
+ # CLAUDE.md
2
+
3
+ This file exists so Claude Code picks up the same project instructions as every
4
+ other AI coding agent used in this repository.
5
+
6
+ **Do not add project guidance here.** The canonical instructions live in
7
+ [`.github/copilot-instructions.md`](.github/copilot-instructions.md) and are
8
+ imported below. Edit that file so all agents stay in sync. Reserve this file for
9
+ guidance that applies *only* to Claude Code.
10
+
11
+ @.github/copilot-instructions.md
data/CONTRIBUTING.md CHANGED
@@ -20,6 +20,7 @@
20
20
  - [Before requesting review](#before-requesting-review)
21
21
  - [Branch strategy](#branch-strategy)
22
22
  - [AI-assisted contributions](#ai-assisted-contributions)
23
+ - [Agent configuration](#agent-configuration)
23
24
  - [Agent skills](#agent-skills)
24
25
  - [Design philosophy](#design-philosophy)
25
26
  - [Layered architecture](#layered-architecture)
@@ -39,6 +40,7 @@
39
40
  - [What to know about Conventional Commits](#what-to-know-about-conventional-commits)
40
41
  - [Issue and PR references](#issue-and-pr-references)
41
42
  - [Testing guidelines](#testing-guidelines)
43
+ - [Test coverage policy](#test-coverage-policy)
42
44
  - [Unit tests vs Integration tests](#unit-tests-vs-integration-tests)
43
45
  - [Building a specific version of the Git command-line](#building-a-specific-version-of-the-git-command-line)
44
46
  - [Install pre-requisites](#install-pre-requisites)
@@ -215,6 +217,27 @@ and "CI is green" are not substitutes for the submitter running
215
217
  [the local validation step](#contributor-validation-policy) themselves; CI is a
216
218
  backstop, not a primary validation surface.
217
219
 
220
+ ### Agent configuration
221
+
222
+ Agent configuration is shared: each piece of guidance is stored once and surfaced to
223
+ every supported agent.
224
+
225
+ | Content | Canonical location | Also read by |
226
+ | --- | --- | --- |
227
+ | Project instructions | [`.github/copilot-instructions.md`](.github/copilot-instructions.md) | Claude Code, via an import in [`CLAUDE.md`](CLAUDE.md) |
228
+ | Skills | [`.github/skills/`](.github/skills/) | Claude Code, via the `.claude/skills` symlink |
229
+ | Prompts | [`.github/prompts/`](.github/prompts/) | Claude Code, via wrappers in `.claude/commands/` |
230
+ | Setup hook | [`.github/hooks/run-bin-setup-once.sh`](.github/hooks/run-bin-setup-once.sh) | Claude Code, via `.claude/settings.json` |
231
+
232
+ Always edit the canonical file. The Claude Code side is a pointer in every case, so
233
+ changes reach both agents without a sync step.
234
+
235
+ One caveat: `.claude/skills` is a committed symlink. Git for Windows only
236
+ materializes symlinks when `core.symlinks` is enabled (which requires Developer Mode
237
+ or an elevated shell). Without it, Windows contributors get a plain text file there
238
+ and Claude Code silently loads no skills; either enable symlinks or point your agent
239
+ at [`.github/skills/`](.github/skills/) directly. Copilot is unaffected.
240
+
218
241
  ### Agent skills
219
242
 
220
243
  If you use an AI coding agent that understands repository skills, the
@@ -904,12 +927,138 @@ process.stdin.on('end', () =>
904
927
  local working copy.
905
928
  - Test runs are covered by SimpleCov by default. Set `COVERAGE=false` (or `0`/`no`/
906
929
  `off`) to skip coverage, e.g. `COVERAGE=false bundle exec rake spec`.
930
+ `rake spec:integration` always disables coverage, regardless of `COVERAGE`:
931
+ integration tests aren't meant to be exhaustive, so tracking their coverage would
932
+ misleadingly suggest that low integration coverage is a problem to fix.
933
+ - `rake spec:integration` runs in parallel (via `parallel_tests`) on MRI. Set
934
+ `PARALLEL_TESTS=false` (or `0`/`no`/`off`) to force serial execution, e.g.
935
+ `PARALLEL_TESTS=false bundle exec rake spec:integration`. A run narrowed by `SPEC`
936
+ to a single spec file always runs serially — there is nothing to divide across
937
+ workers, and serial execution gives per-example (documentation) output.
938
+ - Set `SPEC=<glob>` to run specific files instead of a task's whole directory, e.g.
939
+ `SPEC=spec/unit/git/version_spec.rb bundle exec rake spec:unit`.
940
+ - Each task runs only the matches that live under its own directory, so one glob
941
+ spanning `spec/unit/` and `spec/integration/` can drive `bundle exec rake spec` and
942
+ exercise both layers of an area in a single command:
943
+
944
+ ```bash
945
+ # Unit and integration specs for the add command
946
+ SPEC=spec/**/git/commands/add_spec.rb bundle exec rake spec
947
+
948
+ # Unit and integration specs for every command class
949
+ SPEC=spec/**/git/commands bundle exec rake spec
950
+ ```
951
+
952
+ The glob is expanded by Rake, not the shell, so `**` works the same in any shell.
953
+ A task whose directory contains none of the matches is skipped with a message —
954
+ `SPEC=spec/unit/...` on `rake spec` runs the unit specs and skips
955
+ `spec:integration`. A glob matching nothing anywhere fails the task outright.
907
956
 
908
957
  This project uses **RSpec** (`spec/`) as its sole test framework. Structure,
909
958
  naming, setup, stubbing, and coverage rules for unit specs are defined in the
910
959
  [`rspec-unit-testing-standards`](.github/skills/rspec-unit-testing-standards/SKILL.md)
911
960
  skill — follow it when writing or reviewing specs under `spec/unit/`.
912
961
 
962
+ #### Test coverage policy
963
+
964
+ **Every pull request to `main` must keep `bundle exec rake spec:unit` at 100% line
965
+ coverage and 100% branch coverage of `lib/`.** CI fails the build when it drops
966
+ below either threshold.
967
+
968
+ This is enforceable without being onerous because unit coverage in this project is
969
+ deterministic: `lib/` has no Ruby-version, Ruby-engine, or platform conditionals, and
970
+ no unit spec is conditionally skipped. Every supported MRI runtime measures exactly
971
+ the same lines and branches, so a coverage failure is always something the pull
972
+ request introduced.
973
+
974
+ What the policy does and does not cover:
975
+
976
+ - **Scope is the unit suite on MRI.** Integration specs are deliberately not
977
+ exhaustive and are not measured (`rake spec:integration` always disables coverage).
978
+ JRuby and TruffleRuby do not produce reliable coverage data and are not measured.
979
+ - **Enforcement applies to full-suite runs.** A focused run
980
+ (`SPEC=<glob> bundle exec rake spec:unit`, or `bundle exec rspec <file>`) still
981
+ reports coverage but will not fail on it, so the usual edit-test loop is unaffected.
982
+ Set `FAIL_ON_LOW_COVERAGE=true` to force enforcement on for a focused run.
983
+ - **A focused run lists gaps only in the code it is about.** The reported percentage is
984
+ always for the whole of `lib/`, but the list of uncovered lines and branches is scoped
985
+ to the files the run tests — the classes it describes, plus the `lib/` file each spec
986
+ file mirrors. So a focused run answers "is what I just changed fully covered?" without
987
+ waiting for CI:
988
+
989
+ ```text
990
+ Reporting uncovered lines and branches for 1 of 225 files.
991
+
992
+ No uncovered lines and branches in this file.
993
+ ```
994
+
995
+ Ignore the percentage on a focused run; it is low because `spec_helper` loads all of
996
+ `lib/`, not because anything is wrong. Set `LIST_UNCOVERED_FILES=all` to list gaps for
997
+ every file instead.
998
+ - **The thresholds do not move.** Do not lower `minimum_coverage` and do not add a
999
+ SimpleCov filter to exclude a file. The only sanctioned escape hatch is a
1000
+ `# simplecov:disable` directive.
1001
+ - **Every file under `lib/` is measured.** SimpleCov only tracks files loaded after it
1002
+ starts, so a file loaded earlier is silently absent from the report rather than
1003
+ counted as uncovered. This is why `git.gemspec` reads the version string out of
1004
+ `lib/git/version.rb` instead of `require`ing it: the `Gemfile` uses `gemspec`, so
1005
+ requiring it there would load it on every `bundle exec`, before SimpleCov starts.
1006
+ Keep new code out of the load path that runs ahead of `spec_helper`.
1007
+
1008
+ When a branch is hard to cover, apply these in order:
1009
+
1010
+ 1. **Reach it through the public interface.** If a branch is reachable, test it.
1011
+ 2. **Delete it.** A branch that cannot be reached through the public interface is
1012
+ usually dead code, and removing it is preferable to excluding it. See commit
1013
+ `74e919a4` ("fix: remove unreachable nil check in `Git::Parsers::Grep.parse`") for
1014
+ the pattern.
1015
+ 3. **Exclude it with `# simplecov:disable`.** Reserved for defensive guards that could
1016
+ only be reached by breaking an OS-level invariant. Cover the smallest possible span,
1017
+ state why the code is unreachable, and expect a reviewer to question it. `lib/`
1018
+ currently contains no coverage directives.
1019
+
1020
+ Use the inline form wherever the exclusion is a single line — it applies only to the
1021
+ line it sits on and needs no matching `enable`, which makes it impossible to leave a
1022
+ region accidentally open:
1023
+
1024
+ ```ruby
1025
+ raise 'unreachable' # simplecov:disable defensive guard; only reachable on OOM
1026
+ ```
1027
+
1028
+ The block form covers a span and stays in effect until the matching
1029
+ `# simplecov:enable` (or end of file, if you forget it):
1030
+
1031
+ ```ruby
1032
+ # simplecov:disable branch platform-specific fallback; not reachable on MRI
1033
+ ...
1034
+ # simplecov:enable branch
1035
+ ```
1036
+
1037
+ Always name the narrowest criterion that solves the problem — `line`, `branch`,
1038
+ `method`, or a comma-separated combination — and spell it exactly. A word SimpleCov
1039
+ does not recognize is treated as free-form reason text, which silently widens the
1040
+ directive to all three criteria instead of failing. Write the reason after the
1041
+ criteria, so the required justification lives in the directive itself.
1042
+
1043
+ **Coverage is a floor on evidence, not a proof of correctness.** A test written only
1044
+ to execute a line, without asserting a meaningful outcome, violates Rule 24 of the
1045
+ [`rspec-unit-testing-standards`](.github/skills/rspec-unit-testing-standards/SKILL.md)
1046
+ skill and will be rejected in review even though it turns the report green. The
1047
+ threshold exists to surface untested behavior, not to be satisfied.
1048
+
1049
+ To see exactly what is uncovered:
1050
+
1051
+ ```bash
1052
+ # Names every uncovered line and branch (printed automatically when a full run fails)
1053
+ $ LIST_UNCOVERED_DETAIL=true bundle exec rake spec:unit
1054
+
1055
+ # Browsable HTML report, also uploaded as a CI artifact when a build fails
1056
+ $ open coverage/index.html
1057
+ ```
1058
+
1059
+ This policy applies to `main` only. The `4.x` maintenance branch predates it and is
1060
+ not held to these thresholds.
1061
+
913
1062
  #### Unit tests vs Integration tests
914
1063
 
915
1064
  This project uses two types of RSpec tests, organized by directory:
data/Rakefile CHANGED
@@ -9,19 +9,8 @@ default_tasks = %i[spec:unit spec:integration rubocop]
9
9
  default_tasks << :yard if Rake::Task.task_defined?(:yard)
10
10
  default_tasks << :build
11
11
 
12
- default_tasks_parallel = %w[spec:unit:parallel spec:integration:parallel rubocop]
13
- default_tasks_parallel << :yard if Rake::Task.task_defined?(:yard)
14
- default_tasks_parallel << :build
15
-
16
- # Use parallel test execution for MRI where it cuts build times by 30-48%.
17
- # JRuby and TruffleRuby are slower with parallel_tests because each worker
18
- # process pays JVM/Truffle startup and warm-up overhead independently,
19
- # resulting in 18-28% slower builds vs. serial execution.
20
- parallel_supported = RUBY_ENGINE == 'ruby'
21
- task default: parallel_supported ? default_tasks_parallel : default_tasks
22
-
23
- desc 'Same as default but runs tests in parallel'
24
- task 'default:parallel': default_tasks_parallel
12
+ desc 'Run all CI tasks (tests, linters, yard, and build)'
13
+ task default: default_tasks
25
14
 
26
15
  module Rake
27
16
  # Overload Rake::Task to add logging
data/git.gemspec CHANGED
@@ -1,7 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $LOAD_PATH.unshift File.expand_path('lib', __dir__)
4
- require 'git/version'
3
+ # Read the version out of lib/git/version.rb rather than requiring it.
4
+ #
5
+ # The Gemfile uses `gemspec`, so Bundler evaluates this file on every `bundle exec`.
6
+ # `require`ing lib/git/version.rb here would therefore load it before SimpleCov
7
+ # starts in spec_helper, leaving it invisible to the coverage report -- an
8
+ # unmeasured hole in the 100% coverage gate. See the "Test coverage policy" section
9
+ # of CONTRIBUTING.md.
10
+ #
11
+ # release-please rewrites the `VERSION = '...'` assignment in place (see
12
+ # `version-file` in .release-please-config.json), so matching on it stays correct
13
+ # across releases. If the match ever fails, the raise below stops the build
14
+ # immediately rather than letting a nil version reach the specification.
15
+ version = File.read(File.expand_path('lib/git/version.rb', __dir__))[/^\s*VERSION\s*=\s*['"]([^'"]+)['"]/, 1]
16
+ raise 'Could not determine Git::VERSION from lib/git/version.rb' if version.nil?
5
17
 
6
18
  Gem::Specification.new do |spec|
7
19
  spec.author = 'Scott Chacon and others'
@@ -17,7 +29,7 @@ Gem::Specification.new do |spec|
17
29
  including branching and merging, object inspection and manipulation, history, patch
18
30
  generation and more.
19
31
  DESCRIPTION
20
- spec.version = Git::VERSION
32
+ spec.version = version
21
33
 
22
34
  spec.metadata['homepage_uri'] = spec.homepage
23
35
  spec.metadata['source_code_uri'] = spec.homepage
@@ -41,9 +53,9 @@ Gem::Specification.new do |spec|
41
53
  spec.add_development_dependency 'rake', '~> 13.3'
42
54
  spec.add_development_dependency 'rspec', '~> 3.13'
43
55
  spec.add_development_dependency 'rubocop', '~> 1.82'
44
- spec.add_development_dependency 'simplecov', '~> 0.22'
56
+ spec.add_development_dependency 'simplecov', '~> 1.0'
45
57
  spec.add_development_dependency 'simplecov-lcov', '~> 0.9'
46
- spec.add_development_dependency 'simplecov-rspec', '~> 0.4'
58
+ spec.add_development_dependency 'simplecov-rspec', '~> 1.1'
47
59
 
48
60
  if RUBY_ENGINE == 'truffleruby' && Gem::Version.new(RUBY_ENGINE_VERSION) < Gem::Version.new('34.0.0')
49
61
  # i18n 1.15+ uses Fiber.[] (Ruby 3.2 Fiber storage) which TruffleRuby < 34.0.0 does not implement
@@ -2399,11 +2399,11 @@ module Git
2399
2399
  build_option(args, entry[:name], @option_definitions[entry[:name]], normalized_opts[entry[:name]])
2400
2400
  when :operand
2401
2401
  build_single_positional(args, entry[:name], allocated_positionals)
2402
- # :nocov: this case should be unreachable
2402
+ # simplecov:disable this case should be unreachable
2403
2403
  else
2404
2404
  raise ArgumentError, "unknown entry kind: #{entry[:kind].inspect}"
2405
2405
  end
2406
- # :nocov:
2406
+ # simplecov:enable
2407
2407
  end
2408
2408
 
2409
2409
  # Replace the END_OF_OPTIONS_MARKER with the stored `as:` value if any element
@@ -13,9 +13,9 @@ module Git
13
13
  # remove = Git::Commands::Remote::Remove.new(execution_context)
14
14
  # remove.call('origin')
15
15
  #
16
- # @example Remove a remote with a name that looks like a flag
17
- # remove = Git::Commands::Remote::Remove.new(execution_context)
18
- # remove.call('-weirdremote')
16
+ # @note No `end_of_options` boundary: `git remote remove` did not accept a `--`
17
+ # separator until git 2.38.0, so a name that looks like a flag (e.g. `-weird`)
18
+ # raises `ArgumentError` instead of being sent to git.
19
19
  #
20
20
  # @note `arguments` block audited against https://git-scm.com/docs/git-remote/2.53.0
21
21
  #
@@ -30,8 +30,6 @@ module Git
30
30
  literal 'remote'
31
31
  literal 'remove'
32
32
 
33
- end_of_options
34
-
35
33
  operand :name, required: true
36
34
  end
37
35
 
@@ -22,6 +22,13 @@ module Git
22
22
  # rename = Git::Commands::Remote::Rename.new(execution_context)
23
23
  # rename.call('origin', 'upstream', no_progress: true)
24
24
  #
25
+ # @note No `end_of_options` boundary despite `:progress` preceding the operands:
26
+ # `git remote rename` did not accept a `--` separator until git 2.36.0. Since
27
+ # the `old`/`new` operands are still validated (an operand is rejected as
28
+ # option-like whenever no `--` boundary exists anywhere in the definition),
29
+ # a name that looks like a flag (e.g. `-weird`) raises `ArgumentError` instead
30
+ # of ever reaching git, so omitting the boundary introduces no ambiguity.
31
+ #
25
32
  # @note `arguments` block audited against https://git-scm.com/docs/git-remote/2.53.0
26
33
  #
27
34
  # @see Git::Commands::Remote
@@ -36,8 +43,6 @@ module Git
36
43
  literal 'rename'
37
44
  flag_option :progress, negatable: true
38
45
 
39
- end_of_options
40
-
41
46
  operand :old, required: true
42
47
  operand :new, required: true
43
48
  end
@@ -593,11 +593,10 @@ module Git
593
593
  # @return [void]
594
594
  #
595
595
  def apply_file_mode(type, mode)
596
- case type
597
- when 'new'
596
+ if type == 'new'
598
597
  @current_file[:dst_mode] = mode
599
598
  @current_file[:src_path] = nil
600
- when 'deleted'
599
+ else
601
600
  @current_file[:src_mode] = mode
602
601
  @current_file[:dst_path] = nil
603
602
  end
@@ -32,7 +32,7 @@ module Git
32
32
  def parse(output)
33
33
  output.each_line.with_object(Hash.new { |h, k| h[k] = [] }) do |line, hsh|
34
34
  filename, line_num, text = line.chomp.split("\0", 3)
35
- next unless text && line_num&.match?(/\A\d+\z/)
35
+ next unless text && line_num.match?(/\A\d+\z/)
36
36
 
37
37
  hsh[filename] << [line_num.to_i, text]
38
38
  end
data/lib/git/version.rb CHANGED
@@ -4,7 +4,7 @@ module Git
4
4
  # The current gem version
5
5
  #
6
6
  # @return [String] the current gem version
7
- VERSION = '5.0.2'
7
+ VERSION = '5.0.3'
8
8
 
9
9
  # Represents a git version with major, minor, and patch components
10
10
  #
data/tasks/rspec.rake CHANGED
@@ -1,48 +1,111 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rspec/core/rake_task'
3
+ # Skip parallel test execution when the PARALLEL_TESTS environment variable is set to a falsy value
4
+ def parallel_tests_disabled_via_env?
5
+ parallel_tests_env = ENV.fetch('PARALLEL_TESTS', 'true').strip.downcase
6
+ %w[false 0 no off].include?(parallel_tests_env)
7
+ end
8
+
9
+ # Use parallel test execution for MRI where it cuts build times by 30-48%.
10
+ # JRuby and TruffleRuby are slower with parallel_tests because each worker
11
+ # process pays JVM/Truffle startup and warm-up overhead independently,
12
+ # resulting in 18-28% slower builds vs. serial execution.
13
+ def parallel_tests?
14
+ RUBY_ENGINE == 'ruby' && !parallel_tests_disabled_via_env?
15
+ end
4
16
 
5
- # Run all specs
6
- RSpec::Core::RakeTask.new(:spec) do |t|
7
- t.pattern = 'spec/**/*_spec.rb'
17
+ # SPEC lets a developer target one or more specific files, e.g.
18
+ # `SPEC=spec/unit/git/version_spec.rb rake spec:unit`, running just those files
19
+ # instead of the whole directory. Both rspec and parallel_rspec recurse a bare
20
+ # directory argument using their own default *_spec.rb pattern, so no explicit
21
+ # --pattern flag is needed for the non-SPEC case.
22
+ #
23
+ # Matches are filtered to dir so that each task only ever runs the specs it owns,
24
+ # no matter how broad SPEC is. This keeps every task self-consistent (a unit spec
25
+ # can never be run by spec:integration under integration's runner and env) and lets
26
+ # a single cross-layer glob drive `rake spec`, e.g.
27
+ # `SPEC=spec/**/git/commands/add_spec.rb rake spec` runs the unit file under
28
+ # spec:unit and the integration file under spec:integration. A SPEC that matches
29
+ # files elsewhere in spec/ but none under dir yields no targets, and the caller
30
+ # skips the task rather than falling back to running all of dir.
31
+ def spec_targets(dir)
32
+ spec_files = ENV.fetch('SPEC', nil)&.strip
33
+ return [dir] if spec_files.nil? || spec_files.empty?
34
+
35
+ targets = FileList[spec_files].sort
36
+ raise "SPEC=#{spec_files.inspect} did not match any files" if targets.empty?
37
+
38
+ targets.select { |target| target.delete_prefix('./').start_with?(dir) }
8
39
  end
9
40
 
10
- # Run only unit specs (mocked, fast)
11
- RSpec::Core::RakeTask.new('spec:unit') do |t|
12
- t.pattern = 'spec/unit/**/*_spec.rb'
13
- # On JRuby, use 'documentation' formatter so each test name is printed before
14
- # it runs. When the suite hangs, the last printed line identifies the blocking
15
- # test. Mirrors the same diagnostic added to spec:integration in PR #1274.
16
- t.rspec_opts = '--format documentation' if RUBY_ENGINE == 'jruby'
41
+ # True when targets name exactly one spec file (as opposed to a directory, or
42
+ # several files).
43
+ def single_spec_file?(targets)
44
+ targets.one? && File.file?(targets.first)
17
45
  end
18
46
 
19
- # Run only integration specs (real git, slower)
20
- RSpec::Core::RakeTask.new('spec:integration') do |t|
21
- t.pattern = 'spec/integration/**/*_spec.rb'
22
- # On JRuby, override the default Fuubar formatter with 'documentation' so that
23
- # each test name is printed before it runs. This makes CI logs useful when the
24
- # suite hangs: the last printed test is the one that caused the hang.
25
- t.rspec_opts = '--format documentation' if RUBY_ENGINE == 'jruby'
47
+ # The runner for targets: parallel_rspec only when the task runs in parallel and
48
+ # there is more than one spec file to spread across workers.
49
+ #
50
+ # A single file always uses plain rspec. Worker startup is pure overhead with nothing
51
+ # to divide, and parallel_tests sets TEST_ENV_NUMBER in every worker, which makes
52
+ # spec_helper fall back from the documentation formatter to plain dots -- the opposite
53
+ # of what a run narrowed to one file wants.
54
+ def spec_runner(targets, parallel:)
55
+ parallel && !single_spec_file?(targets) ? 'parallel_rspec' : 'rspec'
26
56
  end
27
57
 
28
- # Run all specs in parallel
29
- desc 'Run all specs in parallel'
30
- task 'spec:parallel' do
31
- sh 'bundle exec parallel_rspec spec/'
58
+ # Run the SPEC-filtered targets for dir, or announce a skip when SPEC selected nothing
59
+ # under dir. Silently doing nothing would read as a passing run of the whole directory.
60
+ def run_spec_task(name, dir, env, parallel:)
61
+ targets = spec_targets(dir)
62
+
63
+ if targets.empty?
64
+ puts "Skipping #{name}: SPEC=#{ENV.fetch('SPEC', nil)} matched no files under #{dir}"
65
+ else
66
+ sh env, 'bundle', 'exec', spec_runner(targets, parallel: parallel), *targets
67
+ end
32
68
  end
33
69
 
34
- # Run only unit specs in parallel
35
- desc 'Run unit specs in parallel'
36
- task 'spec:unit:parallel' do
37
- sh 'bundle exec parallel_rspec spec/unit/'
70
+ def define_parallel_spec_task(name, dir, env: {})
71
+ task name do
72
+ run_spec_task(name, dir, env, parallel: true)
73
+ end
38
74
  end
39
75
 
40
- # Run only integration specs in parallel
41
- desc 'Run integration specs in parallel'
42
- task 'spec:integration:parallel' do
43
- sh 'bundle exec parallel_rspec spec/integration/'
76
+ def define_serial_spec_task(name, dir, env: {})
77
+ task name do
78
+ run_spec_task(name, dir, env, parallel: false)
79
+ end
44
80
  end
45
81
 
82
+ # Define a spec task that runs in parallel (via parallel_tests) when parallel_tests? is
83
+ # true, and serially (via a direct `bundle exec rspec` call) otherwise. env, when given,
84
+ # is passed to `sh` and scoped to just the spawned test subprocess(es).
85
+ def define_spec_task(name, dir, desc_text, env: {})
86
+ desc desc_text
87
+ parallel_tests? ? define_parallel_spec_task(name, dir, env: env) : define_serial_spec_task(name, dir, env: env)
88
+ end
89
+
90
+ # Run only unit specs. These run in a few seconds, so parallel_tests startup
91
+ # overhead isn't worth it - always run serially.
92
+ desc 'Run unit RSpec tests (mocked, fast; SPEC=<glob> to run specific files)'
93
+ define_serial_spec_task('spec:unit', 'spec/unit/')
94
+
95
+ # Run only integration specs. Coverage is forced off (regardless of the COVERAGE
96
+ # env var): integration tests intentionally aren't exhaustive, so tracking or
97
+ # reporting coverage for them would misleadingly suggest that low integration
98
+ # coverage is a problem to fix.
99
+ define_spec_task(
100
+ 'spec:integration', 'spec/integration/',
101
+ 'Run integration RSpec tests (real git, slower; SPEC=<glob> to run specific files)',
102
+ env: { 'COVERAGE' => 'false' }
103
+ )
104
+
105
+ # Run all specs, keeping unit and integration output clearly separated
106
+ desc 'Run unit and integration RSpec tests (SPEC=<glob> to run specific files)'
107
+ task spec: %w[spec:unit spec:integration]
108
+
46
109
  CLEAN << 'coverage'
47
110
  CLEAN << '.rspec_status'
48
111
  CLEAN << 'rspec-report.xml'
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: 5.0.2
4
+ version: 5.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon and others
@@ -169,14 +169,14 @@ dependencies:
169
169
  requirements:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
- version: '0.22'
172
+ version: '1.0'
173
173
  type: :development
174
174
  prerelease: false
175
175
  version_requirements: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '0.22'
179
+ version: '1.0'
180
180
  - !ruby/object:Gem::Dependency
181
181
  name: simplecov-lcov
182
182
  requirement: !ruby/object:Gem::Requirement
@@ -197,14 +197,14 @@ dependencies:
197
197
  requirements:
198
198
  - - "~>"
199
199
  - !ruby/object:Gem::Version
200
- version: '0.4'
200
+ version: '1.1'
201
201
  type: :development
202
202
  prerelease: false
203
203
  version_requirements: !ruby/object:Gem::Requirement
204
204
  requirements:
205
205
  - - "~>"
206
206
  - !ruby/object:Gem::Version
207
- version: '0.4'
207
+ version: '1.1'
208
208
  - !ruby/object:Gem::Dependency
209
209
  name: irb
210
210
  requirement: !ruby/object:Gem::Requirement
@@ -298,6 +298,9 @@ executables: []
298
298
  extensions: []
299
299
  extra_rdoc_files: []
300
300
  files:
301
+ - ".claude/commands/address-copilot-reviews.md"
302
+ - ".claude/settings.json"
303
+ - ".claude/skills"
301
304
  - ".commitlintrc.yml"
302
305
  - ".dockerignore"
303
306
  - ".github/copilot-instructions.md"
@@ -356,6 +359,7 @@ files:
356
359
  - ".yardopts"
357
360
  - AI_POLICY.md
358
361
  - CHANGELOG.md
362
+ - CLAUDE.md
359
363
  - CODE_OF_CONDUCT.md
360
364
  - CONTRIBUTING.md
361
365
  - GOVERNANCE.md
@@ -626,8 +630,8 @@ licenses:
626
630
  metadata:
627
631
  homepage_uri: http://github.com/ruby-git/ruby-git
628
632
  source_code_uri: http://github.com/ruby-git/ruby-git
629
- changelog_uri: https://rubydoc.info/gems/git/5.0.2/file/CHANGELOG.md
630
- documentation_uri: https://rubydoc.info/gems/git/5.0.2
633
+ changelog_uri: https://rubydoc.info/gems/git/5.0.3/file/CHANGELOG.md
634
+ documentation_uri: https://rubydoc.info/gems/git/5.0.3
631
635
  rubygems_mfa_required: 'true'
632
636
  rdoc_options: []
633
637
  require_paths: