git 4.3.2 → 5.0.0.beta.2

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 (297) hide show
  1. checksums.yaml +4 -4
  2. data/.github/copilot-instructions.md +73 -2705
  3. data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +188 -0
  4. data/.github/pull_request_template.md +3 -1
  5. data/.github/skills/breaking-change-analysis/SKILL.md +102 -0
  6. data/.github/skills/ci-cd-troubleshooting/SKILL.md +264 -0
  7. data/.github/skills/command-implementation/REFERENCE.md +993 -0
  8. data/.github/skills/command-implementation/SKILL.md +229 -0
  9. data/.github/skills/command-test-conventions/SKILL.md +660 -0
  10. data/.github/skills/command-yard-documentation/SKILL.md +426 -0
  11. data/.github/skills/dependency-management/SKILL.md +72 -0
  12. data/.github/skills/development-workflow/SKILL.md +506 -0
  13. data/.github/skills/extract-command-from-lib/SKILL.md +487 -0
  14. data/.github/skills/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +22 -0
  15. data/.github/skills/extract-facade-from-base-lib/SKILL.md +600 -0
  16. data/.github/skills/facade-implementation/REFERENCE.md +840 -0
  17. data/.github/skills/facade-implementation/SKILL.md +274 -0
  18. data/.github/skills/facade-test-conventions/SKILL.md +394 -0
  19. data/.github/skills/facade-yard-documentation/SKILL.md +429 -0
  20. data/.github/skills/make-skill-template/SKILL.md +176 -0
  21. data/.github/skills/pr-readiness-review/SKILL.md +185 -0
  22. data/.github/skills/project-context/SKILL.md +313 -0
  23. data/.github/skills/pull-request-review/SKILL.md +168 -0
  24. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +131 -0
  25. data/.github/skills/release-management/SKILL.md +125 -0
  26. data/.github/skills/review-arguments-dsl/CHECKLIST.md +788 -0
  27. data/.github/skills/review-arguments-dsl/SKILL.md +214 -0
  28. data/.github/skills/review-backward-compatibility/SKILL.md +275 -0
  29. data/.github/skills/review-cross-command-consistency/SKILL.md +139 -0
  30. data/.github/skills/reviewing-skills/SKILL.md +189 -0
  31. data/.github/skills/rspec-unit-testing-standards/SKILL.md +639 -0
  32. data/.github/skills/tdd-refactor-step/SKILL.md +236 -0
  33. data/.github/skills/test-debugging/SKILL.md +160 -0
  34. data/.github/skills/yard-documentation/SKILL.md +793 -0
  35. data/.github/workflows/continuous_integration.yml +3 -2
  36. data/.github/workflows/enforce_conventional_commits.yml +1 -1
  37. data/.github/workflows/experimental_continuous_integration.yml +2 -2
  38. data/.github/workflows/release.yml +3 -4
  39. data/.gitignore +8 -0
  40. data/.husky/pre-commit +13 -0
  41. data/.release-please-manifest.json +1 -1
  42. data/.rspec +3 -0
  43. data/.rubocop.yml +12 -3
  44. data/.rubocop_todo.yml +23 -5
  45. data/.yardopts +1 -0
  46. data/CHANGELOG.md +0 -40
  47. data/CONTRIBUTING.md +694 -53
  48. data/README.md +67 -15
  49. data/Rakefile +61 -9
  50. data/UPGRADING.md +141 -0
  51. data/commitlint.test +4 -0
  52. data/git.gemspec +18 -7
  53. data/lib/git/args_builder.rb +0 -8
  54. data/lib/git/branch.rb +369 -43
  55. data/lib/git/branch_delete_failure.rb +31 -0
  56. data/lib/git/branch_delete_result.rb +63 -0
  57. data/lib/git/branch_info.rb +178 -0
  58. data/lib/git/branches.rb +122 -24
  59. data/lib/git/command_line/base.rb +255 -0
  60. data/lib/git/command_line/capturing.rb +251 -0
  61. data/lib/git/command_line/result.rb +96 -0
  62. data/lib/git/command_line/streaming.rb +196 -0
  63. data/lib/git/command_line.rb +43 -322
  64. data/lib/git/command_line_result.rb +4 -88
  65. data/lib/git/commands/add.rb +131 -0
  66. data/lib/git/commands/am/abort.rb +43 -0
  67. data/lib/git/commands/am/apply.rb +252 -0
  68. data/lib/git/commands/am/continue.rb +43 -0
  69. data/lib/git/commands/am/quit.rb +43 -0
  70. data/lib/git/commands/am/retry.rb +47 -0
  71. data/lib/git/commands/am/show_current_patch.rb +64 -0
  72. data/lib/git/commands/am/skip.rb +42 -0
  73. data/lib/git/commands/am.rb +33 -0
  74. data/lib/git/commands/apply.rb +237 -0
  75. data/lib/git/commands/archive/list_formats.rb +46 -0
  76. data/lib/git/commands/archive.rb +140 -0
  77. data/lib/git/commands/arguments.rb +3510 -0
  78. data/lib/git/commands/base.rb +404 -0
  79. data/lib/git/commands/branch/copy.rb +94 -0
  80. data/lib/git/commands/branch/create.rb +173 -0
  81. data/lib/git/commands/branch/delete.rb +80 -0
  82. data/lib/git/commands/branch/list.rb +162 -0
  83. data/lib/git/commands/branch/move.rb +94 -0
  84. data/lib/git/commands/branch/set_upstream.rb +86 -0
  85. data/lib/git/commands/branch/show_current.rb +49 -0
  86. data/lib/git/commands/branch/unset_upstream.rb +57 -0
  87. data/lib/git/commands/branch.rb +34 -0
  88. data/lib/git/commands/cat_file/batch.rb +369 -0
  89. data/lib/git/commands/cat_file/filtered.rb +105 -0
  90. data/lib/git/commands/cat_file/raw.rb +216 -0
  91. data/lib/git/commands/cat_file.rb +49 -0
  92. data/lib/git/commands/checkout/branch.rb +151 -0
  93. data/lib/git/commands/checkout/files.rb +115 -0
  94. data/lib/git/commands/checkout.rb +38 -0
  95. data/lib/git/commands/checkout_index.rb +105 -0
  96. data/lib/git/commands/clean.rb +100 -0
  97. data/lib/git/commands/clone.rb +240 -0
  98. data/lib/git/commands/commit.rb +272 -0
  99. data/lib/git/commands/commit_tree.rb +100 -0
  100. data/lib/git/commands/config_option_syntax/add.rb +83 -0
  101. data/lib/git/commands/config_option_syntax/get.rb +117 -0
  102. data/lib/git/commands/config_option_syntax/get_all.rb +115 -0
  103. data/lib/git/commands/config_option_syntax/get_color.rb +91 -0
  104. data/lib/git/commands/config_option_syntax/get_color_bool.rb +93 -0
  105. data/lib/git/commands/config_option_syntax/get_regexp.rb +115 -0
  106. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +107 -0
  107. data/lib/git/commands/config_option_syntax/list.rb +107 -0
  108. data/lib/git/commands/config_option_syntax/remove_section.rb +74 -0
  109. data/lib/git/commands/config_option_syntax/rename_section.rb +78 -0
  110. data/lib/git/commands/config_option_syntax/replace_all.rb +104 -0
  111. data/lib/git/commands/config_option_syntax/set.rb +114 -0
  112. data/lib/git/commands/config_option_syntax/unset.rb +89 -0
  113. data/lib/git/commands/config_option_syntax/unset_all.rb +89 -0
  114. data/lib/git/commands/config_option_syntax.rb +56 -0
  115. data/lib/git/commands/describe.rb +155 -0
  116. data/lib/git/commands/diff.rb +656 -0
  117. data/lib/git/commands/diff_files.rb +518 -0
  118. data/lib/git/commands/diff_index.rb +496 -0
  119. data/lib/git/commands/fetch.rb +352 -0
  120. data/lib/git/commands/fsck.rb +136 -0
  121. data/lib/git/commands/gc.rb +132 -0
  122. data/lib/git/commands/grep.rb +338 -0
  123. data/lib/git/commands/init.rb +99 -0
  124. data/lib/git/commands/log.rb +632 -0
  125. data/lib/git/commands/ls_files.rb +191 -0
  126. data/lib/git/commands/ls_remote.rb +155 -0
  127. data/lib/git/commands/ls_tree.rb +131 -0
  128. data/lib/git/commands/maintenance/register.rb +75 -0
  129. data/lib/git/commands/maintenance/run.rb +104 -0
  130. data/lib/git/commands/maintenance/start.rb +66 -0
  131. data/lib/git/commands/maintenance/stop.rb +55 -0
  132. data/lib/git/commands/maintenance/unregister.rb +79 -0
  133. data/lib/git/commands/maintenance.rb +31 -0
  134. data/lib/git/commands/merge/abort.rb +44 -0
  135. data/lib/git/commands/merge/continue.rb +44 -0
  136. data/lib/git/commands/merge/quit.rb +46 -0
  137. data/lib/git/commands/merge/start.rb +245 -0
  138. data/lib/git/commands/merge.rb +28 -0
  139. data/lib/git/commands/merge_base.rb +86 -0
  140. data/lib/git/commands/mv.rb +77 -0
  141. data/lib/git/commands/name_rev.rb +114 -0
  142. data/lib/git/commands/pull.rb +377 -0
  143. data/lib/git/commands/push.rb +246 -0
  144. data/lib/git/commands/read_tree.rb +149 -0
  145. data/lib/git/commands/remote/add.rb +91 -0
  146. data/lib/git/commands/remote/get_url.rb +66 -0
  147. data/lib/git/commands/remote/list.rb +54 -0
  148. data/lib/git/commands/remote/prune.rb +61 -0
  149. data/lib/git/commands/remote/remove.rb +52 -0
  150. data/lib/git/commands/remote/rename.rb +69 -0
  151. data/lib/git/commands/remote/set_branches.rb +63 -0
  152. data/lib/git/commands/remote/set_head.rb +82 -0
  153. data/lib/git/commands/remote/set_url.rb +71 -0
  154. data/lib/git/commands/remote/set_url_add.rb +61 -0
  155. data/lib/git/commands/remote/set_url_delete.rb +64 -0
  156. data/lib/git/commands/remote/show.rb +71 -0
  157. data/lib/git/commands/remote/update.rb +72 -0
  158. data/lib/git/commands/remote.rb +42 -0
  159. data/lib/git/commands/repack.rb +277 -0
  160. data/lib/git/commands/reset.rb +147 -0
  161. data/lib/git/commands/rev_parse.rb +297 -0
  162. data/lib/git/commands/revert/abort.rb +45 -0
  163. data/lib/git/commands/revert/continue.rb +57 -0
  164. data/lib/git/commands/revert/quit.rb +47 -0
  165. data/lib/git/commands/revert/skip.rb +44 -0
  166. data/lib/git/commands/revert/start.rb +153 -0
  167. data/lib/git/commands/revert.rb +29 -0
  168. data/lib/git/commands/rm.rb +114 -0
  169. data/lib/git/commands/show.rb +632 -0
  170. data/lib/git/commands/show_ref/exclude_existing.rb +120 -0
  171. data/lib/git/commands/show_ref/exists.rb +78 -0
  172. data/lib/git/commands/show_ref/list.rb +145 -0
  173. data/lib/git/commands/show_ref/verify.rb +120 -0
  174. data/lib/git/commands/show_ref.rb +42 -0
  175. data/lib/git/commands/stash/apply.rb +75 -0
  176. data/lib/git/commands/stash/branch.rb +65 -0
  177. data/lib/git/commands/stash/clear.rb +41 -0
  178. data/lib/git/commands/stash/create.rb +58 -0
  179. data/lib/git/commands/stash/drop.rb +67 -0
  180. data/lib/git/commands/stash/list.rb +39 -0
  181. data/lib/git/commands/stash/pop.rb +78 -0
  182. data/lib/git/commands/stash/push.rb +103 -0
  183. data/lib/git/commands/stash/show.rb +149 -0
  184. data/lib/git/commands/stash/store.rb +63 -0
  185. data/lib/git/commands/stash.rb +38 -0
  186. data/lib/git/commands/status.rb +169 -0
  187. data/lib/git/commands/symbolic_ref/delete.rb +68 -0
  188. data/lib/git/commands/symbolic_ref/read.rb +95 -0
  189. data/lib/git/commands/symbolic_ref/update.rb +76 -0
  190. data/lib/git/commands/symbolic_ref.rb +38 -0
  191. data/lib/git/commands/tag/create.rb +139 -0
  192. data/lib/git/commands/tag/delete.rb +55 -0
  193. data/lib/git/commands/tag/list.rb +143 -0
  194. data/lib/git/commands/tag/verify.rb +71 -0
  195. data/lib/git/commands/tag.rb +26 -0
  196. data/lib/git/commands/update_ref/batch.rb +140 -0
  197. data/lib/git/commands/update_ref/delete.rb +92 -0
  198. data/lib/git/commands/update_ref/update.rb +106 -0
  199. data/lib/git/commands/update_ref.rb +42 -0
  200. data/lib/git/commands/version.rb +57 -0
  201. data/lib/git/commands/worktree/add.rb +140 -0
  202. data/lib/git/commands/worktree/list.rb +64 -0
  203. data/lib/git/commands/worktree/lock.rb +58 -0
  204. data/lib/git/commands/worktree/management_base.rb +51 -0
  205. data/lib/git/commands/worktree/move.rb +66 -0
  206. data/lib/git/commands/worktree/prune.rb +67 -0
  207. data/lib/git/commands/worktree/remove.rb +63 -0
  208. data/lib/git/commands/worktree/repair.rb +76 -0
  209. data/lib/git/commands/worktree/unlock.rb +47 -0
  210. data/lib/git/commands/worktree.rb +43 -0
  211. data/lib/git/commands/write_tree.rb +68 -0
  212. data/lib/git/commands.rb +87 -0
  213. data/lib/git/config.rb +17 -0
  214. data/lib/git/config_entry_info.rb +106 -0
  215. data/lib/git/configuring.rb +665 -0
  216. data/lib/git/deprecation.rb +9 -0
  217. data/lib/git/detached_head_info.rb +54 -0
  218. data/lib/git/diff.rb +293 -7
  219. data/lib/git/diff_file_numstat_info.rb +29 -0
  220. data/lib/git/diff_file_patch_info.rb +134 -0
  221. data/lib/git/diff_file_raw_info.rb +127 -0
  222. data/lib/git/diff_info.rb +169 -0
  223. data/lib/git/diff_path_status.rb +67 -19
  224. data/lib/git/diff_result.rb +32 -0
  225. data/lib/git/diff_stats.rb +51 -14
  226. data/lib/git/dirstat_info.rb +86 -0
  227. data/lib/git/errors.rb +65 -2
  228. data/lib/git/execution_context/global.rb +31 -0
  229. data/lib/git/execution_context/repository.rb +136 -0
  230. data/lib/git/execution_context.rb +501 -0
  231. data/lib/git/file_ref.rb +74 -0
  232. data/lib/git/fsck_object.rb +9 -9
  233. data/lib/git/fsck_result.rb +1 -1
  234. data/lib/git/log.rb +9 -2
  235. data/lib/git/object.rb +90 -27
  236. data/lib/git/parsers/branch.rb +224 -0
  237. data/lib/git/parsers/cat_file.rb +111 -0
  238. data/lib/git/parsers/config_entry.rb +110 -0
  239. data/lib/git/parsers/diff.rb +585 -0
  240. data/lib/git/parsers/fsck.rb +133 -0
  241. data/lib/git/parsers/grep.rb +42 -0
  242. data/lib/git/parsers/ls_remote.rb +79 -0
  243. data/lib/git/parsers/ls_tree.rb +58 -0
  244. data/lib/git/parsers/stash.rb +208 -0
  245. data/lib/git/parsers/tag.rb +257 -0
  246. data/lib/git/remote.rb +120 -9
  247. data/lib/git/repository/branching.rb +743 -0
  248. data/lib/git/repository/committing.rb +187 -0
  249. data/lib/git/repository/configuring.rb +351 -0
  250. data/lib/git/repository/context_helpers.rb +264 -0
  251. data/lib/git/repository/diffing.rb +775 -0
  252. data/lib/git/repository/factories.rb +682 -0
  253. data/lib/git/repository/inspecting.rb +252 -0
  254. data/lib/git/repository/logging.rb +247 -0
  255. data/lib/git/repository/maintenance.rb +65 -0
  256. data/lib/git/repository/merging.rb +357 -0
  257. data/lib/git/repository/object_operations.rb +1199 -0
  258. data/lib/git/repository/path_resolver.rb +207 -0
  259. data/lib/git/repository/remote_operations.rb +898 -0
  260. data/lib/git/repository/shared_private.rb +51 -0
  261. data/lib/git/repository/staging.rb +554 -0
  262. data/lib/git/repository/stashing.rb +143 -0
  263. data/lib/git/repository/status_operations.rb +201 -0
  264. data/lib/git/repository/worktree_operations.rb +159 -0
  265. data/lib/git/repository.rb +203 -1
  266. data/lib/git/stash.rb +78 -4
  267. data/lib/git/stash_info.rb +104 -0
  268. data/lib/git/stashes.rb +125 -13
  269. data/lib/git/status.rb +215 -18
  270. data/lib/git/tag_delete_failure.rb +31 -0
  271. data/lib/git/tag_delete_result.rb +63 -0
  272. data/lib/git/tag_info.rb +105 -0
  273. data/lib/git/version.rb +109 -2
  274. data/lib/git/version_constraint.rb +81 -0
  275. data/lib/git/worktree.rb +108 -6
  276. data/lib/git/worktrees.rb +94 -7
  277. data/lib/git.rb +260 -61
  278. data/redesign/1_architecture_existing.md +54 -18
  279. data/redesign/2_architecture_redesign.md +365 -46
  280. data/redesign/3_architecture_implementation.md +1497 -63
  281. data/redesign/Phase 4 - Step A.md +360 -0
  282. data/redesign/beta_release.md +107 -0
  283. data/redesign/c1c2_audit.md +566 -0
  284. data/redesign/c1c2_bucket6_lib_orphans.md +626 -0
  285. data/redesign/config_design.rb +501 -0
  286. data/tasks/gem_tasks.rake +4 -0
  287. data/tasks/npm_tasks.rake +7 -0
  288. data/tasks/rspec.rake +48 -0
  289. data/tasks/test.rake +13 -1
  290. data/tasks/yard.rake +34 -7
  291. metadata +365 -22
  292. data/lib/git/base.rb +0 -1128
  293. data/lib/git/index.rb +0 -6
  294. data/lib/git/lib.rb +0 -2277
  295. data/lib/git/path.rb +0 -38
  296. data/lib/git/working_directory.rb +0 -6
  297. /data/{release-please-config.json → .release-please-config.json} +0 -0
data/README.md CHANGED
@@ -30,6 +30,8 @@ Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?log
30
30
  - [Ruby Version Support Policy](#ruby-version-support-policy)
31
31
  - [Git Version Support Policy](#git-version-support-policy)
32
32
  - [📢 Project Announcements 📢](#-project-announcements-)
33
+ - [2026-06-25: v5.0.0.beta.2 Released](#2026-06-25-v500beta2-released)
34
+ - [2026-06-04: v5.0.0.beta.1 Released](#2026-06-04-v500beta1-released)
33
35
  - [2026-01-07: AI Policy Introduced](#2026-01-07-ai-policy-introduced)
34
36
  - [2025-07-09: Architectural Redesign](#2025-07-09-architectural-redesign)
35
37
  - [2025-07-07: We Now Use RuboCop](#2025-07-07-we-now-use-rubocop)
@@ -51,7 +53,7 @@ Get started by obtaining a repository object by:
51
53
  [Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method)
52
54
 
53
55
  Methods that can be called on a repository object are documented in
54
- [Git::Base](https://rubydoc.info/gems/git/Git/Base)
56
+ [Git::Repository](https://rubydoc.info/gems/git/Git/Repository)
55
57
 
56
58
  ## Install
57
59
 
@@ -86,8 +88,8 @@ All functionality for this gem starts with the top-level
86
88
  non-repo scoped `git` commands such as `config`.
87
89
 
88
90
  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
+ return a [`Git::Repository`](https://rubydoc.info/gems/git/Git/Repository) object. The
92
+ `Git::Repository` object is used to run repo-specific `git` commands such as `add`,
91
93
  `commit`, `push`, and `log`.
92
94
 
93
95
  Clone, read status, and log:
@@ -190,11 +192,11 @@ Here are the operations that need read permission only:
190
192
  ```ruby
191
193
  repo = Git.open(working_dir, :log => Logger.new(STDOUT))
192
194
 
193
- repo.index
194
- repo.index.readable?
195
- repo.index.writable?
196
- repo.repo
197
- repo.dir
195
+ repo.index # Pathname to the index file
196
+ repo.index.readable? # check if index is readable
197
+ repo.index.writable? # check if index is writable
198
+ repo.repo # Pathname to the .git directory
199
+ repo.dir # Pathname to the working directory
198
200
 
199
201
  # ls-tree with recursion into subtrees (list files)
200
202
  repo.ls_tree("HEAD", recursive: true)
@@ -415,8 +417,8 @@ repo.merge([branch1, branch2])
415
417
 
416
418
  repo.merge_base('branch1', 'branch2')
417
419
 
418
- r = repo.add_remote(name, uri) # Git::Remote
419
- r = repo.add_remote(name, Git::Base) # Git::Remote
420
+ r = repo.remote_add(name, uri) # Git::Remote
421
+ r = repo.remote_add(name, other_repo) # Git::Remote (other_repo is a Git::Repository instance)
420
422
 
421
423
  repo.remotes # array of Git::Remotes
422
424
  repo.remote(name).fetch
@@ -436,12 +438,12 @@ repo.fetch('origin', {:'update-head-ok' => true})
436
438
  repo.pull
437
439
  repo.pull(Git::Repo, Git::Branch) # fetch and a merge
438
440
 
439
- repo.add_tag('tag_name') # returns Git::Tag
440
- repo.add_tag('tag_name', 'object_reference')
441
- repo.add_tag('tag_name', 'object_reference', {:options => 'here'})
442
- repo.add_tag('tag_name', {:options => 'here'})
441
+ repo.tag_add('tag_name') # returns Git::Object::Tag
442
+ repo.tag_add('tag_name', 'object_reference')
443
+ repo.tag_add('tag_name', 'object_reference', {:options => 'here'})
444
+ repo.tag_add('tag_name', {:options => 'here'})
443
445
 
444
- repo.delete_tag('tag_name')
446
+ repo.tag_delete('tag_name')
445
447
 
446
448
  repo.repack
447
449
 
@@ -649,6 +651,56 @@ notes.
649
651
 
650
652
  ## 📢 Project Announcements 📢
651
653
 
654
+ ### 2026-06-25: v5.0.0.beta.2 Released
655
+
656
+ The architectural redesign is approximately **90% complete** and we have published
657
+ [`git v5.0.0.beta.2`](https://rubygems.org/gems/git/versions/5.0.0.beta.2) as our
658
+ second pre-release.
659
+
660
+ **To try the beta**, add the pre-release version to your `Gemfile`:
661
+
662
+ ```ruby
663
+ gem 'git', '~> 5.0.0.beta'
664
+ ```
665
+
666
+ Or install it directly:
667
+
668
+ ```sh
669
+ gem install git --pre
670
+ ```
671
+
672
+ The intent is full backward compatibility with v4.x, but given the size and scope of
673
+ the redesign, some incompatibilities may exist. Please give the latest beta a try and
674
+ [open an issue](https://github.com/ruby-git/ruby-git/issues) if you hit anything
675
+ unexpected — your feedback helps us ship a solid v5.0.0.
676
+
677
+ See [UPGRADING.md](UPGRADING.md) for a full list of deprecations and breaking changes.
678
+
679
+ ### 2026-06-04: v5.0.0.beta.1 Released
680
+
681
+ The architectural redesign is approximately **65% complete** and we have published
682
+ [`git v5.0.0.beta.1`](https://rubygems.org/gems/git/versions/5.0.0.beta.1) as our
683
+ first pre-release.
684
+
685
+ **To try the beta**, add the pre-release version to your `Gemfile`:
686
+
687
+ ```ruby
688
+ gem 'git', '~> 5.0.0.beta'
689
+ ```
690
+
691
+ Or install it directly:
692
+
693
+ ```sh
694
+ gem install git --pre
695
+ ```
696
+
697
+ The intent is full backward compatibility with 4.x, but given the size and scope of
698
+ the redesign, some incompatibilities may exist. Please give the latest beta a try and
699
+ [open an issue](https://github.com/ruby-git/ruby-git/issues) if you hit anything
700
+ unexpected — your feedback helps us ship a solid 5.0.0.
701
+
702
+ See [UPGRADING.md](UPGRADING.md) for a full list of deprecations and breaking changes.
703
+
652
704
  ### 2026-01-07: AI Policy Introduced
653
705
 
654
706
  We have adopted a formal [AI Policy](AI_POLICY.md) to clarify expectations for
data/Rakefile CHANGED
@@ -5,14 +5,66 @@ require 'rake/clean'
5
5
  # Load all .rake files from tasks and its subdirectories.
6
6
  Dir.glob('tasks/**/*.rake').each { |r| load r }
7
7
 
8
- default_tasks = []
9
- default_tasks << :test if Rake::Task.task_defined?(:test)
10
- default_tasks << :rubocop if Rake::Task.task_defined?(:rubocop)
8
+ desc 'Run all tests (TestUnit and RSpec)'
9
+ task 'test-all': %i[test spec]
10
+
11
+ desc 'Run all tests in parallel (TestUnit and RSpec run concurrently)'
12
+ task 'test-all:parallel' do
13
+ errors = []
14
+ mutex = Mutex.new
15
+ threads = %w[test:parallel spec:parallel].map do |t|
16
+ Thread.new do
17
+ Rake::Task[t].invoke
18
+ rescue Exception => e # rubocop:disable Lint/RescueException
19
+ mutex.synchronize { errors << e }
20
+ end
21
+ end
22
+ threads.each(&:join)
23
+ raise errors.first if errors.any?
24
+ end
25
+
26
+ default_tasks = %i[test spec:unit spec:integration rubocop]
11
27
  default_tasks << :yard if Rake::Task.task_defined?(:yard)
12
- default_tasks << :'yardstick:coverage' if Rake::Task.task_defined?(:'yardstick:coverage')
13
- # Do not include yardstick as a default task for now since there are too many
14
- # warnings. Will work to get the warnings down before re-enabling it.
15
- # default_tasks << :yardstick if Rake::Task.task_defined?(:yardstick)
16
- default_tasks << :build if Rake::Task.task_defined?(:build)
28
+ default_tasks << :build
29
+
30
+ default_tasks_parallel = %w[test:parallel spec:unit:parallel spec:integration:parallel rubocop]
31
+ default_tasks_parallel << :yard if Rake::Task.task_defined?(:yard)
32
+ default_tasks_parallel << :build
33
+
34
+ # Use parallel test execution for MRI where it cuts build times by 30-48%.
35
+ # JRuby and TruffleRuby are slower with parallel_tests because each worker
36
+ # process pays JVM/Truffle startup and warm-up overhead independently,
37
+ # resulting in 18-28% slower builds vs. serial execution.
38
+ parallel_supported = RUBY_ENGINE == 'ruby'
39
+ task default: parallel_supported ? default_tasks_parallel : default_tasks
40
+
41
+ desc 'Same as default but runs tests in parallel'
42
+ task 'default:parallel': default_tasks_parallel
43
+
44
+ module Rake
45
+ # Overload Rake::Task to add logging
46
+ class Task
47
+ # Store the original execute method
48
+ alias original_execute execute
49
+
50
+ # Override execute to add a print statement
51
+ def execute(args = nil)
52
+ # Only output the task name if it wasn't the only top-level task
53
+ # rake default # => output task name for each task called by the default task
54
+ # rake rubocop # => do not output the task name
55
+ # rake rubocop yard # => output task name for rubocop and yard
56
+ top_level_tasks = Rake.application.top_level_tasks
57
+ box("Rake task: #{name}") unless top_level_tasks.length == 1 && name == top_level_tasks[0]
58
+ original_execute(args)
59
+ end
60
+
61
+ private
17
62
 
18
- task default: default_tasks
63
+ def box(message)
64
+ width = message.length + 2
65
+ puts "┌#{'─' * width}┐"
66
+ puts "│ #{message} │"
67
+ puts "└#{'─' * width}┘"
68
+ end
69
+ end
70
+ end
data/UPGRADING.md ADDED
@@ -0,0 +1,141 @@
1
+ # Upgrading the `git` Gem
2
+
3
+ > **⚠️ Work in progress — v5.0.0 is currently in beta.**
4
+ > This document is updated incrementally as development continues and is not yet
5
+ > complete. If you encounter a compatibility problem not covered here, please
6
+ > [open an issue](https://github.com/ruby-git/ruby-git/issues).
7
+
8
+ - [Upgrading from v4.x to v5.x](#upgrading-from-v4x-to-v5x)
9
+ - [Overview](#overview)
10
+ - [`Git::Lib` removal](#gitlib-removal)
11
+ - [Methods with a direct replacement](#methods-with-a-direct-replacement)
12
+ - [Methods with no replacement](#methods-with-no-replacement)
13
+ - [Internal plumbing methods (no replacement)](#internal-plumbing-methods-no-replacement)
14
+ - [Deprecated methods](#deprecated-methods)
15
+
16
+ ## Upgrading from v4.x to v5.x
17
+
18
+ ### Overview
19
+
20
+ The primary goal of v5.0.0 is to move everyone onto a new internal architecture
21
+ while keeping the existing v4.x API working. The vast majority of v4.x code
22
+ requires no changes to run on v5.x.
23
+
24
+ The new architecture delivered in v5.0.0 is the foundation for future API
25
+ improvements across upcoming major releases.
26
+
27
+ The new architecture introduces a layered design (`Git::Commands`, `Git::Repository`,
28
+ and associated parsers). Compatibility shims — deprecated forwarding methods that map
29
+ old call patterns to the new API — ensure that v4.x code continues to work. These
30
+ shims emit deprecation warnings that tell you exactly what to change and what will be
31
+ eliminated in a future major release (most likely v6.0.0).
32
+
33
+ Hard breaks are limited to a small number of methods that had no safe
34
+ migration path — these are described in detail below.
35
+
36
+ Our intent is to make upgrading to v5.x as smooth as possible. For information
37
+ on how to suppress or configure deprecation warnings, see the
38
+ [Deprecations](README.md#deprecations) section of the README.
39
+
40
+ ---
41
+
42
+ ### `Git::Lib` removal
43
+
44
+ The object returned by `Git.open`, `Git.clone`, and `Git.init` — the object
45
+ you call methods on to interact with your repository — inadvertently exposed
46
+ a `#lib` method that gave access to `Git::Lib`, the gem's internal
47
+ implementation class. This was never intended to be public; it was an
48
+ implementation detail that leaked out. `Git::Lib` is removed in v5.0.0.
49
+
50
+ Calling `#lib` on the repository object returns `self` with a deprecation
51
+ warning so that existing `g.lib.*` call chains continue to work during
52
+ migration. The `#lib` method itself is removed in v6.0.0. Calls to methods
53
+ that have no replacement (see below) raise `NoMethodError` with an
54
+ informative message.
55
+
56
+ Most public behavior previously accessible via `g.lib.*` is available
57
+ directly on the repository object (i.e., `g.*`). A small number of methods
58
+ have no replacement — see below. The sections below list every affected method.
59
+
60
+ #### Methods with a direct replacement
61
+
62
+ All of the following `g.lib.*` calls work in v5.x but emit a deprecation
63
+ warning. Migrate to the replacement shown to silence the `g.lib.*` deprecation
64
+ warning; note that some replacements are themselves deprecated — see the table
65
+ notes for the final migration target.
66
+
67
+ | Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
68
+ |---------------------------------------------------|-------------|
69
+ | `g.lib.config_get(name)` | `g.config(name)` |
70
+ | `g.lib.config_list` | `g.config` |
71
+ | `g.lib.config_set(name, value)` | `g.config(name, value)` |
72
+ | `g.lib.git_version` | `g.git_version` |
73
+ | `g.lib.global_config_get(name)` | `g.global_config(name)` |
74
+ | `g.lib.global_config_list` | `g.global_config` |
75
+ | `g.lib.global_config_set(name, value)` | `g.global_config(name, value)` |
76
+ | `g.lib.parse_config(file)` | `g.config(file: file)` |
77
+ | `g.lib.stash_list` | `g.stash_list` *(also deprecated — use `g.stashes_all`)* |
78
+ | `g.lib.unmerged` | `g.unmerged` |
79
+ | `g.lib.change_head_branch(name)` | `g.change_head_branch(name)` |
80
+ | `g.lib.branch_current` | `g.current_branch` |
81
+ | `g.lib.ls_remote(location, opts)` | `g.ls_remote(location, opts)` |
82
+ | `g.lib.current_branch_state` | `g.current_branch_state` |
83
+
84
+ > **Note — `current_branch_state` return type change:** `g.lib.current_branch_state`
85
+ > returned a `Git::Lib::HeadState` (a mutable `Struct`). `g.current_branch_state`
86
+ > returns a `Git::Repository::Branching::HeadState` (an immutable `Data` object).
87
+ > Both expose `.state` (`:active`, `:unborn`, or `:detached`) and `.name`. If your
88
+ > code relies on the struct being mutable or uses positional construction
89
+ > (`Git::Lib::HeadState.new(:active, 'main')`), update to keyword construction:
90
+ > `Git::Repository::Branching::HeadState.new(state: :active, name: 'main')`.
91
+
92
+ #### Methods with no replacement
93
+
94
+ | v4.x call | Notes |
95
+ |-----------|-------|
96
+ | `g.lib.list_files(ref_dir)` | Walked `.git/refs/` directly. Use `g.branches`, `g.tags`, or `g.remotes` instead. |
97
+
98
+ #### Internal plumbing methods (no replacement)
99
+
100
+ The following methods were technically public on `Git::Lib` but are internal
101
+ helpers with no plausible external use. They have no replacement in v5.0.0:
102
+
103
+ - `assert_args_are_not_options`
104
+ - `assert_valid_opts`
105
+ - `cat_file_object_meta`
106
+ - `command_capturing`
107
+ - `command_streaming`
108
+ - `each_cat_file_header`
109
+ - `handle_deprecated_path_option`
110
+ - `normalize_pathspecs`
111
+ - `parse_cat_file_meta`
112
+ - `parse_config_list`
113
+ - `process_commit_data`
114
+ - `validate_pathspec_types`
115
+
116
+ ---
117
+
118
+ ### Deprecated methods
119
+
120
+ The following methods are available in v5.x with deprecation warnings and
121
+ are removed in v6.0.0.
122
+
123
+ | Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
124
+ |---------------------------------------------------|-------------|
125
+ | `g.config_get(name)` | `g.config(name)` |
126
+ | `g.config_list` | `g.config` |
127
+ | `g.config_set(name, value)` | `g.config(name, value)` |
128
+ | `g.global_config_get(name)` | `g.global_config(name)` |
129
+ | `g.global_config_list` | `g.global_config` |
130
+ | `g.global_config_set(name, value)` | `g.global_config(name, value)` |
131
+ | `g.parse_config(file)` | `g.config(file: file)` |
132
+ | `g.stash_list` | `g.stashes_all` |
133
+ | `g.add_remote(name, url, opts)` | `g.remote_add(name, url, opts)` |
134
+ | `g.remove_remote(name)` | `g.remote_remove(name)` |
135
+ | `g.set_remote_url(name, url)` | `g.remote_set_url(name, url)` |
136
+ | `g.add_tag(name, ...)` | `g.tag_add(name, ...)` |
137
+ | `g.delete_tag(name)` | `g.tag_delete(name)` |
138
+ | `include Git; config(...)` | `Git.open(Dir.pwd).config(...)` |
139
+ | `include Git; global_config(...)` | `Git.global_config(...)` |
140
+
141
+ ---
data/commitlint.test ADDED
@@ -0,0 +1,4 @@
1
+ test: update the tests
2
+
3
+ Wow I really want to edit the PR #1024 but I can't.
4
+
data/git.gemspec CHANGED
@@ -35,18 +35,29 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency 'rchardet', '~> 1.9'
36
36
 
37
37
  spec.add_development_dependency 'create_github_release', '~> 2.1'
38
+ spec.add_development_dependency 'fuubar', '~> 2.5'
38
39
  spec.add_development_dependency 'main_branch_shared_rubocop_config', '~> 0.1'
39
- spec.add_development_dependency 'minitar', '~> 1.0'
40
- spec.add_development_dependency 'mocha', '~> 2.7'
41
- spec.add_development_dependency 'rake', '~> 13.2'
42
- spec.add_development_dependency 'rubocop', '~> 1.77'
40
+ spec.add_development_dependency 'minitar', '~> 1.1'
41
+ spec.add_development_dependency 'mocha', '~> 2.8'
42
+ spec.add_development_dependency 'parallel_tests', '~> 5.6'
43
+ spec.add_development_dependency 'rake', '~> 13.3'
44
+ spec.add_development_dependency 'rspec', '~> 3.13'
45
+ spec.add_development_dependency 'rubocop', '~> 1.82'
46
+ spec.add_development_dependency 'simplecov', '~> 0.22'
47
+ spec.add_development_dependency 'simplecov-lcov', '~> 0.9'
48
+ spec.add_development_dependency 'simplecov-rspec', '~> 0.4'
49
+ spec.add_development_dependency 'test-unit', '~> 3.7'
43
50
 
44
- spec.add_development_dependency 'test-unit', '~> 3.6'
51
+ if RUBY_ENGINE == 'truffleruby' && Gem::Version.new(RUBY_ENGINE_VERSION) < Gem::Version.new('34.0.0')
52
+ # i18n 1.15+ uses Fiber.[] (Ruby 3.2 Fiber storage) which TruffleRuby < 34.0.0 does not implement
53
+ spec.add_development_dependency 'i18n', '< 1.15'
54
+ end
45
55
 
46
- unless RUBY_PLATFORM == 'java'
47
- spec.add_development_dependency 'irb', '~> 1.6'
56
+ unless RUBY_PLATFORM == 'java' || RUBY_ENGINE == 'truffleruby'
57
+ spec.add_development_dependency 'irb', '~> 1.16'
48
58
  spec.add_development_dependency 'redcarpet', '~> 3.6'
49
59
  spec.add_development_dependency 'yard', '~> 0.9', '>= 0.9.28'
60
+ spec.add_development_dependency 'yard_example_test', '~> 0.2', '>= 0.2.1'
50
61
  spec.add_development_dependency 'yardstick', '~> 0.9'
51
62
  end
52
63
 
@@ -12,14 +12,6 @@ module Git
12
12
  ARG_BUILDERS = {
13
13
  boolean: ->(config, value) { value ? config[:flag] : [] },
14
14
 
15
- boolean_negatable: lambda do |config, value|
16
- case value
17
- when true then config[:flag]
18
- when false then config[:flag].sub('--', '--no-')
19
- else []
20
- end
21
- end,
22
-
23
15
  valued_equals: ->(config, value) { "#{config[:flag]}=#{value}" if value },
24
16
 
25
17
  valued_space: ->(config, value) { [config[:flag], value.to_s] if value },