git 5.6.0 → 6.0.0

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +132 -16
  3. data/CONTRIBUTING.md +44 -31
  4. data/README.md +135 -67
  5. data/UPGRADING.md +915 -268
  6. data/git.gemspec +6 -8
  7. data/lib/git/author_info.rb +1 -2
  8. data/lib/git/commands/base.rb +22 -2
  9. data/lib/git/commands/cat_file/raw.rb +0 -68
  10. data/lib/git/commands/maintenance/register.rb +0 -4
  11. data/lib/git/commands/maintenance/run.rb +0 -4
  12. data/lib/git/commands/maintenance/start.rb +0 -4
  13. data/lib/git/commands/maintenance/stop.rb +0 -4
  14. data/lib/git/commands/maintenance/unregister.rb +0 -4
  15. data/lib/git/commands/maintenance.rb +0 -2
  16. data/lib/git/commands/show_ref/exclude_existing.rb +1 -1
  17. data/lib/git/commands/show_ref/exists.rb +0 -5
  18. data/lib/git/commands/show_ref/list.rb +1 -1
  19. data/lib/git/commands/show_ref/verify.rb +1 -1
  20. data/lib/git/commands/show_ref.rb +1 -1
  21. data/lib/git/commands/worktree/repair.rb +0 -5
  22. data/lib/git/diff_path_status.rb +2 -2
  23. data/lib/git/encoding_utils.rb +25 -0
  24. data/lib/git/errors.rb +23 -5
  25. data/lib/git/factories.rb +361 -125
  26. data/lib/git/log.rb +3 -75
  27. data/lib/git/object.rb +4 -185
  28. data/lib/git/path_resolver.rb +104 -36
  29. data/lib/git/repository/branching.rb +21 -189
  30. data/lib/git/repository/committing.rb +0 -25
  31. data/lib/git/repository/context_helpers.rb +249 -155
  32. data/lib/git/repository/diffing.rb +2 -44
  33. data/lib/git/repository/merging.rb +32 -54
  34. data/lib/git/repository/object_operations.rb +121 -338
  35. data/lib/git/repository/remote_operations.rb +7 -219
  36. data/lib/git/repository/staging.rb +6 -184
  37. data/lib/git/repository/stashing.rb +126 -130
  38. data/lib/git/repository/status_operations.rb +1 -54
  39. data/lib/git/repository/worktree_operations.rb +31 -118
  40. data/lib/git/repository.rb +20 -299
  41. data/lib/git/system_call_guard.rb +95 -0
  42. data/lib/git/version.rb +1 -1
  43. data/lib/git.rb +47 -364
  44. metadata +25 -19
  45. data/lib/git/author.rb +0 -46
  46. data/lib/git/branch.rb +0 -693
  47. data/lib/git/branches.rb +0 -194
  48. data/lib/git/remote.rb +0 -191
  49. data/lib/git/stash.rb +0 -124
  50. data/lib/git/stashes.rb +0 -198
  51. data/lib/git/status.rb +0 -384
  52. data/lib/git/worktree.rb +0 -180
  53. data/lib/git/worktrees.rb +0 -152
data/README.md CHANGED
@@ -15,10 +15,12 @@ Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?log
15
15
  [![AI Policy](https://img.shields.io/badge/AI%20Policy-Doc-blue)](AI_POLICY.md)
16
16
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
17
17
 
18
- > **v5.0.0 is here.** This is a major release with a redesigned internal
19
- > architecture, but most v4.x code runs unchanged thanks to compatibility
20
- > shims. See [UPGRADING.md](UPGRADING.md) for the migration guide and
21
- > [CHANGELOG.md](CHANGELOG.md) for full release notes.
18
+ > **v6.0.0 is released.** It is a major release that removes the APIs deprecated
19
+ > during v5.x, raises the minimum Ruby version to 3.3 and the minimum git version
20
+ > to 2.43.0, and changes a few behaviors that had no deprecation path. See
21
+ > [Upgrading to v6.x](UPGRADING.md#upgrading-to-v6x) for the migration guide and
22
+ > [CHANGELOG.md](CHANGELOG.md) for full release notes. v5.x continues to receive
23
+ > fixes from the `5.x` branch.
22
24
 
23
25
  - [Summary](#summary)
24
26
  - [Install](#install)
@@ -38,6 +40,8 @@ Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?log
38
40
  - [Deprecation policy](#deprecation-policy)
39
41
  - [Release support policy](#release-support-policy)
40
42
  - [Project announcements](#project-announcements)
43
+ - [2026-09-04: v5.x releases move to the 5.x branch](#2026-09-04-v5x-releases-move-to-the-5x-branch)
44
+ - [2026-09-04: Retired branches deleted](#2026-09-04-retired-branches-deleted)
41
45
  - [2026-08-23: v5.x deprecations and the v6.0.0 roadmap](#2026-08-23-v5x-deprecations-and-the-v600-roadmap)
42
46
  - [2026-07-28: v5.0.0 released](#2026-07-28-v500-released)
43
47
  - [2026-01-07: AI policy introduced](#2026-01-07-ai-policy-introduced)
@@ -66,7 +70,7 @@ methods you can call on a repository object.
66
70
  ## Install
67
71
 
68
72
  This gem is a wrapper around the `git` command line, so a `git` executable (version
69
- 2.28.0 or greater) must be installed and on your `PATH`. See the [Git version support
73
+ 2.43.0 or greater) must be installed and on your `PATH`. See the [Git version support
70
74
  policy](#git-version-support-policy) for details.
71
75
 
72
76
  Install the gem and add to the application's Gemfile by executing:
@@ -146,12 +150,12 @@ Git.config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
146
150
 
147
151
  How SSH configuration is determined:
148
152
 
149
- - If `git_ssh` is not specified in the API call, the global config (`Git.configure {
150
- |c| c.git_ssh = ... }`) is used.
151
- - If `git_ssh: nil` is specified, SSH is disabled for that instance (no SSH key or
152
- script will be used).
153
- - If `git_ssh` is a non-empty string, it is used for that instance (overriding the
154
- global config).
153
+ - If the API call does not specify `git_ssh`, the gem uses the global config
154
+ (`Git.configure { |c| c.git_ssh = ... }`).
155
+ - If the call specifies `git_ssh: nil`, the gem disables SSH for that instance and
156
+ uses no SSH key or script.
157
+ - If `git_ssh` is a non-empty string, the gem uses it for that instance instead of
158
+ the global config.
155
159
 
156
160
  You can also specify a custom SSH script on a per-repository basis:
157
161
 
@@ -167,8 +171,8 @@ git = Git.clone('git@github.com:user/repo.git', 'local-dir',
167
171
  git = Git.init('new-repo', git_ssh: 'ssh -i /path/to/private_key')
168
172
  ```
169
173
 
170
- This is especially useful in multi-threaded applications where different repositories
171
- require different SSH credentials.
174
+ This matters in multi-threaded applications where different repositories need
175
+ different SSH credentials.
172
176
 
173
177
  ### Git configuration
174
178
 
@@ -196,13 +200,12 @@ The [`Git::Repository`](https://rubydoc.info/gems/git/Git/Repository) reference
196
200
  covers everything else: reading history, diffs, branches, remotes, worktrees,
197
201
  staging, and low-level index and tree work. It documents every method and the object
198
202
  type each one returns (such as `Git::Log`, `Git::Object::Commit`, `Git::Diff`,
199
- `Git::Branch`, and `Git::Worktree`), so you can follow the links from a method to
200
- the full API of its result.
203
+ `Git::BranchInfo`, and `Git::WorktreeInfo`), so you can follow the links from a method
204
+ to the full API of its result.
201
205
 
202
206
  ## Errors raised by this gem
203
207
 
204
- The git gem raises only `ArgumentError` or errors that subclass `Git::Error`. It
205
- does not explicitly raise any other types of errors.
208
+ The git gem raises only `ArgumentError` or errors that subclass `Git::Error`.
206
209
 
207
210
  Rescue `Git::Error` to catch any runtime error raised by this gem, unless you need
208
211
  more specific error handling.
@@ -215,6 +218,26 @@ rescue Git::Error => e
215
218
  end
216
219
  ```
217
220
 
221
+ Operating system errors from the gem's own filesystem operations, such as reading
222
+ a `.git` pointer file or creating a temporary file, are raised as `Git::Error`.
223
+ The original `SystemCallError` is available through `cause`:
224
+
225
+ ```ruby
226
+ begin
227
+ repo = Git.open('/path/to/repo')
228
+ rescue Git::Error => e
229
+ puts e.cause.class if e.cause.is_a?(SystemCallError) #=> Errno::EACCES
230
+ end
231
+ ```
232
+
233
+ The promise covers errors the gem raises from its own operations. Two things pass
234
+ through unchanged. An error raised by a block your code passes to a method such as
235
+ `chdir` or `with_temp_working` is your error, and the gem does not relabel it. And
236
+ with the `raise` behavior described under [Deprecation policy](#deprecation-policy), a
237
+ deprecated call raises `ActiveSupport::DeprecationException`, which is intentionally
238
+ not a `Git::Error` so a broad rescue cannot hide a deprecation your code opted to
239
+ treat as fatal.
240
+
218
241
  See [`Git::Error`](https://rubydoc.info/gems/git/Git/Error) for more information.
219
242
 
220
243
  ## Specifying and handling timeouts
@@ -222,13 +245,11 @@ See [`Git::Error`](https://rubydoc.info/gems/git/Git/Error) for more information
222
245
  Set a timeout for git command line operations either globally or per method call for
223
246
  methods that accept a `:timeout` parameter.
224
247
 
225
- The timeout value must be a real, non-negative `Numeric` value that specifies the
226
- number of seconds a `git` command is given to complete before being sent a KILL
227
- signal. This library may hang if the `git` command does not terminate after
228
- receiving the KILL signal.
229
-
230
- When a command times out, the gem kills it with the `SIGKILL` signal and raises a
231
- `Git::TimeoutError`. This error derives from `Git::SignaledError` and `Git::Error`.
248
+ The timeout is the number of seconds a `git` command may run before the gem sends
249
+ it `SIGKILL`. It must be a real, non-negative `Numeric`. When a command times out,
250
+ the gem kills it and raises `Git::TimeoutError`, which derives from
251
+ `Git::SignaledError` and `Git::Error`. The gem may hang if the `git` command does
252
+ not terminate after receiving `SIGKILL`.
232
253
 
233
254
  If the timeout value is `0` or `nil`, no timeout is enforced.
234
255
 
@@ -262,7 +283,7 @@ begin
262
283
  Git.clone(repo_url, timeout: 10)
263
284
  rescue Git::TimeoutError => e
264
285
  e.result.tap do |r|
265
- r.class #=> Git::CommandLineResult
286
+ r.class #=> Git::CommandLine::Result
266
287
  r.status #=> #<Process::Status: pid 62173 SIGKILL (signal 9)>
267
288
  r.status.timeout? #=> true
268
289
  r.git_cmd # The git command ran as an array of strings
@@ -291,6 +312,17 @@ GIT_DEPRECATION_BEHAVIOR=silence
291
312
  Accepted environment variable values are the behavior names supported by your
292
313
  installed ActiveSupport version.
293
314
 
315
+ A deprecated method warns on every call, so a call site inside a loop produces one
316
+ warning per iteration. The gem does not deduplicate warnings. To quiet one call site
317
+ without hiding other deprecations, wrap it in `Git::Deprecation.silence`:
318
+
319
+ ```ruby
320
+ Git::Deprecation.silence { repo.set_index(index_file) }
321
+ ```
322
+
323
+ Prefer this over setting the behavior to `silence` globally, which also hides the
324
+ warnings for deprecations added in later releases.
325
+
294
326
  If `GIT_DEPRECATION_BEHAVIOR` is set to an unsupported value, loading the gem
295
327
  raises `ArgumentError` with the accepted behavior names.
296
328
 
@@ -299,7 +331,7 @@ documentation](https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.htm
299
331
  for more details.
300
332
 
301
333
  Before upgrading the git gem to the next major version, follow the upgrade procedure
302
- in [UPGRADING.md](UPGRADING.md#upgrading-to-v600). It turns the warnings into errors so
334
+ in [UPGRADING.md](UPGRADING.md#upgrading-to-v6x). It turns the warnings into errors so
303
335
  that you cannot miss one.
304
336
 
305
337
  For the full list of deprecated methods and their replacements, see
@@ -331,7 +363,7 @@ gem sets. It is unaffected by the locale: the behavior is identical under `en_US
331
363
  and case-insensitive matching are unaffected on every platform.
332
364
 
333
365
  **Workaround.** Perl-compatible regular expressions do match characters on Git for
334
- Windows, so the surfaces that can reach a PCRE engine accept an opt-in selector:
366
+ Windows, so the methods that can reach a PCRE engine accept an opt-in selector:
335
367
 
336
368
  ```ruby
337
369
  repo.grep('^.PFEL', nil, perl_regexp: true) # matches on every platform
@@ -396,8 +428,18 @@ This gem is expected to function correctly on:
396
428
 
397
429
  - All [non-EOL versions](https://www.ruby-lang.org/en/downloads/branches/) of the MRI
398
430
  Ruby on Mac, Linux, and Windows
399
- - The latest version of JRuby 9.4+ on Linux
400
- - The latest version of TruffleRuby 24+ on Linux
431
+ - JRuby and TruffleRuby on Linux, starting from the earliest release whose Ruby
432
+ compatibility target is at or above the oldest supported MRI version, unless a
433
+ newer release is otherwise needed (for example, when a release does not
434
+ implement a feature the gem depends on)
435
+
436
+ Consult the CI build matrix in
437
+ [`.github/workflows/continuous_integration.yml`](.github/workflows/continuous_integration.yml)
438
+ for the exact JRuby and TruffleRuby versions tested. Newer releases of each engine
439
+ are expected to work but are not tested.
440
+
441
+ Because the JRuby and TruffleRuby floors derive from the MRI floor, they move
442
+ whenever the oldest supported MRI version changes.
401
443
 
402
444
  This project intends to support the latest version of JRuby on Windows once
403
445
  the [process_executer](https://github.com/main-branch/process_executer) gem properly
@@ -406,21 +448,17 @@ supports subprocess status reporting on JRuby for Windows (see
406
448
 
407
449
  ### Git version support policy
408
450
 
409
- This gem requires git version 2.28.0 or greater as specified in the gemspec. This
410
- requirement reflects:
411
-
412
- - The minimum git version necessary to support all features provided by this gem
413
- - A reasonable balance between supporting older systems and using modern git
414
- capabilities
415
- - The practical limitations of testing across multiple git versions in CI
451
+ This gem requires git 2.43.0 or later, as the gemspec declares. The floor weighs the
452
+ git features the gem depends on, the systems users still run, and the git versions
453
+ CI can test.
416
454
 
417
- Git 2.28.0 was released on July 27, 2020. While this gem may work with earlier
418
- versions of git, compatibility with versions prior to 2.28.0 is not tested or
419
- guaranteed. Users on older git versions should upgrade to at least 2.28.0.
455
+ Git 2.43.0 was released on November 20, 2023. The gem may work with an older git,
456
+ but the project does not test or support versions before 2.43.0. Users on an older
457
+ git should upgrade to at least 2.43.0.
420
458
 
421
- The supported git version may be increased in future major or minor releases of this
422
- gem as new git features are adopted or as maintaining backward compatibility becomes
423
- impractical. Such changes will be documented in the CHANGELOG and release notes.
459
+ A later major or minor release may raise the floor when the gem adopts a newer git
460
+ feature or when keeping compatibility with an old git becomes impractical. The
461
+ CHANGELOG and release notes document each such change.
424
462
 
425
463
  ### Deprecation policy
426
464
 
@@ -437,12 +475,16 @@ The recommended way to upgrade across a major version:
437
475
  your test suite and, if possible, staging.
438
476
  3. Fix each deprecation using the entries in [UPGRADING.md](UPGRADING.md) until the
439
477
  suite is clean.
440
- 4. Upgrade to the next major release.
478
+ 4. Work through the changes that a clean run does not catch, listed in that major's
479
+ section of [UPGRADING.md](UPGRADING.md).
480
+ 5. Upgrade to the next major release.
441
481
 
442
482
  Because every deprecation warning is present in the last release of a major series,
443
- this procedure finds every change the next major requires. The version-specific steps
444
- are in [UPGRADING.md](UPGRADING.md#upgrading-to-v600). See
445
- [Deprecations](#deprecations) for how to configure the warnings.
483
+ steps 2 and 3 find every call to a deprecated API. A major release may also change a
484
+ behavior that had no deprecation path, such as the return type of a method that
485
+ keeps its name; step 4 covers those. The version-specific steps are in
486
+ [UPGRADING.md](UPGRADING.md#upgrading-to-v6x). See [Deprecations](#deprecations)
487
+ for how to configure the warnings.
446
488
 
447
489
  ### Release support policy
448
490
 
@@ -461,21 +503,47 @@ supported until v6.0.0 ships, and v5.x until v7.0.0.
461
503
 
462
504
  ## Project announcements
463
505
 
506
+ ### 2026-09-04: v5.x releases move to the `5.x` branch
507
+
508
+ On September 4, 2026, we created the `5.x` branch from v5.4.1. Every further v5.x
509
+ release is cut from that branch, and the next release from `main` is v6.0.0. Nothing
510
+ changes for users of the gem: v5.x continues to receive bug fixes and security fixes
511
+ per the [Release support policy](#release-support-policy), and v4.x is supported
512
+ until v6.0.0 ships.
513
+
514
+ For contributors, fixes still land on `main` first and are backported to `5.x`. A fix
515
+ for a problem that exists only in v5.x targets `5.x` directly. See the
516
+ [branch strategy](CONTRIBUTING.md#branch-strategy) and
517
+ [issue #1717](https://github.com/ruby-git/ruby-git/issues/1717), the v6.0.0 roadmap.
518
+
519
+ ### 2026-09-04: Retired branches deleted
520
+
521
+ On September 4, 2026, we deleted the `v1` and `master` branches. Neither had a
522
+ purpose: support for v1.x ended when v3.0.0 shipped, per the
523
+ [Release support policy](#release-support-policy), and `master` was the pre-rename
524
+ default branch, frozen since the rename to `main` on 2025-06-06. Every v1.x release
525
+ remains available as a tag, so nothing released was lost.
526
+
527
+ The branches that remain are the ones the release support policy describes: `main`
528
+ releases the next version, `4.x` maintains the v4.x series, and `5.x` maintains the
529
+ v5.x series. See [issue #1786](https://github.com/ruby-git/ruby-git/issues/1786) for
530
+ the details.
531
+
464
532
  ### 2026-08-23: v5.x deprecations and the v6.0.0 roadmap
465
533
 
466
- The road to v6.0.0 is now planned and public. The remaining ActiveRecord-style
534
+ The v6.0.0 plan is public. The remaining ActiveRecord-style
467
535
  classes (`Git::Branch`, `Git::Remote`, `Git::Stash`, `Git::Worktree`,
468
536
  `Git::Object::Tag`, `Git::Status`, `Git::Author`, and their collections) will be
469
537
  deprecated during the v5.x series in favor of the immutable `*Info` value-object
470
538
  APIs. v6.0.0 will remove each deprecated class once a normal v5.x release has carried
471
539
  its deprecation warning and UPGRADING.md entry, per the
472
540
  [Deprecation policy](#deprecation-policy). v6.0.0 will not ship until every planned
473
- deprecation has shipped that way. v6.0.0 also raises the version floors: git ≥ 2.42.0,
474
- Ruby ≥ 3.4.
541
+ deprecation has shipped that way. v6.0.0 also raises the version floors to git 2.43.0
542
+ and Ruby 3.3.
475
543
 
476
- [Issue #1717](https://github.com/ruby-git/ruby-git/issues/1717) is the living
477
- roadmap, tracking scope, sequencing, and status. If your code uses the classes
478
- above, you can start migrating now. Each deprecation names its replacement, and
544
+ [Issue #1717](https://github.com/ruby-git/ruby-git/issues/1717) is the roadmap
545
+ and tracks scope, order, and status. If your code uses the classes above, you can
546
+ start migrating now. Each deprecation names its replacement, and
479
547
  [UPGRADING.md](UPGRADING.md) carries the migration guide as releases ship.
480
548
 
481
549
  ### 2026-07-28: v5.0.0 released
@@ -484,7 +552,7 @@ We have published [`git v5.0.0`](https://rubygems.org/gems/git/versions/5.0.0),
484
552
  first stable release of the v5.x series, after five public beta releases in June and
485
553
  July 2026.
486
554
 
487
- **v5.0.0 is a major release with breaking changes.** See
555
+ v5.0.0 is a major release with breaking changes. See
488
556
  [UPGRADING.md](UPGRADING.md) for the complete migration guide.
489
557
 
490
558
  To install:
@@ -504,22 +572,22 @@ while emitting deprecation warnings that tell you what to migrate before v6.0.0.
504
572
 
505
573
  ### 2026-01-07: AI policy introduced
506
574
 
507
- We have adopted a formal [AI Policy](AI_POLICY.md) to clarify expectations for
508
- AI-assisted contributions. Please review it before opening a PR to ensure your
509
- changes are fully understood, meet our quality bar, and respect licensing
510
- requirements.
575
+ We have adopted an [AI Policy](AI_POLICY.md) that sets expectations for
576
+ AI-assisted contributions. Read it before opening a PR. It asks that you understand
577
+ every change you submit, that the work meets the project's quality bar, and that it
578
+ respects licensing requirements.
511
579
 
512
- We chose a principles-based policy to respect contributors' time and expertise. It
513
- is quick to read and easy to remember, and it still sets clear expectations.
580
+ The policy states principles rather than a checklist, so it is short to read and
581
+ still sets clear expectations.
514
582
 
515
583
  ### 2025-07-09: Architectural redesign
516
584
 
517
585
  On this date we announced an architectural redesign of the git gem. The architecture
518
- at the time was difficult to maintain and evolve; the redesign replaced it with a
519
- clearer, more testable three-layer structure of commands, parsers, and a
520
- `Git::Repository` facade.
586
+ at the time was difficult to maintain and change. The redesign replaced it with a
587
+ three-layer structure of commands, parsers, and a `Git::Repository` facade, which is
588
+ easier to test because each layer can be exercised on its own.
521
589
 
522
- **The redesign shipped in v5.0.0 and is complete.** `Git::Base` and `Git::Lib` are
590
+ The redesign shipped in v5.0.0 and is complete. `Git::Base` and `Git::Lib` are
523
591
  gone, along with the `g.lib` accessor. See [UPGRADING.md](UPGRADING.md) for what
524
592
  changed and how to migrate.
525
593
 
@@ -537,10 +605,10 @@ to new code live in [`.github/skills/`](.github/skills/).
537
605
 
538
606
  ### 2025-07-07: We now use RuboCop
539
607
 
540
- To improve code consistency and maintainability, the `ruby-git` project has adopted
541
- [RuboCop](https://rubocop.org/) as our static code analyzer and formatter. All new
542
- contributions must follow the style guidelines enforced by our RuboCop
543
- configuration.
608
+ The `ruby-git` project has adopted [RuboCop](https://rubocop.org/) as its static
609
+ code analyzer and formatter so that contributions share one style. All new
610
+ contributions must follow the style rules the project's RuboCop configuration
611
+ enforces.
544
612
 
545
613
  Run RuboCop from the project's Rakefile:
546
614