git 1.19.1 → 5.5.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 (265) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -1
  3. data/AI_POLICY.md +24 -0
  4. data/CHANGELOG.md +689 -0
  5. data/CODE_OF_CONDUCT.md +25 -0
  6. data/CONTRIBUTING.md +1175 -97
  7. data/GOVERNANCE.md +106 -0
  8. data/LICENSE +1 -1
  9. data/MAINTAINERS.md +17 -4
  10. data/README.md +476 -320
  11. data/UPGRADING.md +1138 -0
  12. data/git.gemspec +124 -36
  13. data/lib/git/author.rb +39 -7
  14. data/lib/git/author_info.rb +66 -0
  15. data/lib/git/branch.rb +615 -65
  16. data/lib/git/branch_delete_failure.rb +34 -0
  17. data/lib/git/branch_delete_result.rb +66 -0
  18. data/lib/git/branch_info.rb +237 -0
  19. data/lib/git/branches.rb +167 -44
  20. data/lib/git/command_line/base.rb +247 -0
  21. data/lib/git/command_line/capturing.rb +308 -0
  22. data/lib/git/command_line/result.rb +88 -0
  23. data/lib/git/command_line/streaming.rb +236 -0
  24. data/lib/git/command_line.rb +52 -0
  25. data/lib/git/commands/add.rb +139 -0
  26. data/lib/git/commands/am/abort.rb +43 -0
  27. data/lib/git/commands/am/apply.rb +263 -0
  28. data/lib/git/commands/am/continue.rb +43 -0
  29. data/lib/git/commands/am/quit.rb +43 -0
  30. data/lib/git/commands/am/retry.rb +49 -0
  31. data/lib/git/commands/am/show_current_patch.rb +64 -0
  32. data/lib/git/commands/am/skip.rb +42 -0
  33. data/lib/git/commands/am.rb +33 -0
  34. data/lib/git/commands/apply.rb +242 -0
  35. data/lib/git/commands/archive/list_formats.rb +46 -0
  36. data/lib/git/commands/archive.rb +145 -0
  37. data/lib/git/commands/arguments.rb +4521 -0
  38. data/lib/git/commands/base.rb +502 -0
  39. data/lib/git/commands/branch/copy.rb +102 -0
  40. data/lib/git/commands/branch/create.rb +177 -0
  41. data/lib/git/commands/branch/delete.rb +88 -0
  42. data/lib/git/commands/branch/list.rb +178 -0
  43. data/lib/git/commands/branch/move.rb +102 -0
  44. data/lib/git/commands/branch/set_upstream.rb +86 -0
  45. data/lib/git/commands/branch/show_current.rb +49 -0
  46. data/lib/git/commands/branch/unset_upstream.rb +53 -0
  47. data/lib/git/commands/branch.rb +34 -0
  48. data/lib/git/commands/cat_file/batch.rb +385 -0
  49. data/lib/git/commands/cat_file/filtered.rb +105 -0
  50. data/lib/git/commands/cat_file/raw.rb +271 -0
  51. data/lib/git/commands/cat_file.rb +49 -0
  52. data/lib/git/commands/checkout/branch.rb +153 -0
  53. data/lib/git/commands/checkout/files.rb +116 -0
  54. data/lib/git/commands/checkout.rb +38 -0
  55. data/lib/git/commands/checkout_index.rb +106 -0
  56. data/lib/git/commands/clean.rb +102 -0
  57. data/lib/git/commands/clone.rb +241 -0
  58. data/lib/git/commands/commit.rb +273 -0
  59. data/lib/git/commands/commit_tree.rb +101 -0
  60. data/lib/git/commands/config_option_syntax/add.rb +86 -0
  61. data/lib/git/commands/config_option_syntax/get.rb +121 -0
  62. data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
  63. data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
  64. data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
  65. data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
  66. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
  67. data/lib/git/commands/config_option_syntax/list.rb +111 -0
  68. data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
  69. data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
  70. data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
  71. data/lib/git/commands/config_option_syntax/set.rb +119 -0
  72. data/lib/git/commands/config_option_syntax/unset.rb +92 -0
  73. data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
  74. data/lib/git/commands/config_option_syntax.rb +56 -0
  75. data/lib/git/commands/describe.rb +156 -0
  76. data/lib/git/commands/diff.rb +657 -0
  77. data/lib/git/commands/diff_files.rb +519 -0
  78. data/lib/git/commands/diff_index.rb +499 -0
  79. data/lib/git/commands/fetch.rb +354 -0
  80. data/lib/git/commands/fsck.rb +138 -0
  81. data/lib/git/commands/gc.rb +134 -0
  82. data/lib/git/commands/grep.rb +339 -0
  83. data/lib/git/commands/init.rb +101 -0
  84. data/lib/git/commands/log.rb +634 -0
  85. data/lib/git/commands/ls_files.rb +195 -0
  86. data/lib/git/commands/ls_remote.rb +161 -0
  87. data/lib/git/commands/ls_tree.rb +135 -0
  88. data/lib/git/commands/maintenance/register.rb +77 -0
  89. data/lib/git/commands/maintenance/run.rb +109 -0
  90. data/lib/git/commands/maintenance/start.rb +71 -0
  91. data/lib/git/commands/maintenance/stop.rb +60 -0
  92. data/lib/git/commands/maintenance/unregister.rb +84 -0
  93. data/lib/git/commands/maintenance.rb +31 -0
  94. data/lib/git/commands/merge/abort.rb +44 -0
  95. data/lib/git/commands/merge/continue.rb +44 -0
  96. data/lib/git/commands/merge/quit.rb +46 -0
  97. data/lib/git/commands/merge/start.rb +250 -0
  98. data/lib/git/commands/merge.rb +28 -0
  99. data/lib/git/commands/merge_base.rb +91 -0
  100. data/lib/git/commands/mv.rb +82 -0
  101. data/lib/git/commands/name_rev.rb +119 -0
  102. data/lib/git/commands/pull.rb +382 -0
  103. data/lib/git/commands/push.rb +251 -0
  104. data/lib/git/commands/read_tree.rb +154 -0
  105. data/lib/git/commands/remote/add.rb +96 -0
  106. data/lib/git/commands/remote/get_url.rb +68 -0
  107. data/lib/git/commands/remote/list.rb +56 -0
  108. data/lib/git/commands/remote/prune.rb +63 -0
  109. data/lib/git/commands/remote/remove.rb +52 -0
  110. data/lib/git/commands/remote/rename.rb +76 -0
  111. data/lib/git/commands/remote/set_branches.rb +70 -0
  112. data/lib/git/commands/remote/set_head.rb +89 -0
  113. data/lib/git/commands/remote/set_url.rb +78 -0
  114. data/lib/git/commands/remote/set_url_add.rb +70 -0
  115. data/lib/git/commands/remote/set_url_delete.rb +71 -0
  116. data/lib/git/commands/remote/show.rb +77 -0
  117. data/lib/git/commands/remote/update.rb +79 -0
  118. data/lib/git/commands/remote.rb +42 -0
  119. data/lib/git/commands/repack.rb +281 -0
  120. data/lib/git/commands/reset.rb +154 -0
  121. data/lib/git/commands/rev_parse.rb +304 -0
  122. data/lib/git/commands/revert/abort.rb +45 -0
  123. data/lib/git/commands/revert/continue.rb +62 -0
  124. data/lib/git/commands/revert/quit.rb +47 -0
  125. data/lib/git/commands/revert/skip.rb +44 -0
  126. data/lib/git/commands/revert/start.rb +158 -0
  127. data/lib/git/commands/revert.rb +29 -0
  128. data/lib/git/commands/rm.rb +113 -0
  129. data/lib/git/commands/show.rb +632 -0
  130. data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
  131. data/lib/git/commands/show_ref/exists.rb +80 -0
  132. data/lib/git/commands/show_ref/list.rb +149 -0
  133. data/lib/git/commands/show_ref/verify.rb +122 -0
  134. data/lib/git/commands/show_ref.rb +42 -0
  135. data/lib/git/commands/stash/apply.rb +81 -0
  136. data/lib/git/commands/stash/branch.rb +67 -0
  137. data/lib/git/commands/stash/clear.rb +43 -0
  138. data/lib/git/commands/stash/create.rb +60 -0
  139. data/lib/git/commands/stash/drop.rb +73 -0
  140. data/lib/git/commands/stash/list.rb +43 -0
  141. data/lib/git/commands/stash/pop.rb +87 -0
  142. data/lib/git/commands/stash/push.rb +112 -0
  143. data/lib/git/commands/stash/show.rb +158 -0
  144. data/lib/git/commands/stash/store.rb +72 -0
  145. data/lib/git/commands/stash.rb +38 -0
  146. data/lib/git/commands/status.rb +174 -0
  147. data/lib/git/commands/symbolic_ref/delete.rb +72 -0
  148. data/lib/git/commands/symbolic_ref/read.rb +99 -0
  149. data/lib/git/commands/symbolic_ref/update.rb +79 -0
  150. data/lib/git/commands/symbolic_ref.rb +38 -0
  151. data/lib/git/commands/tag/create.rb +142 -0
  152. data/lib/git/commands/tag/delete.rb +57 -0
  153. data/lib/git/commands/tag/list.rb +146 -0
  154. data/lib/git/commands/tag/verify.rb +71 -0
  155. data/lib/git/commands/tag.rb +26 -0
  156. data/lib/git/commands/update_ref/batch.rb +145 -0
  157. data/lib/git/commands/update_ref/delete.rb +90 -0
  158. data/lib/git/commands/update_ref/update.rb +103 -0
  159. data/lib/git/commands/update_ref.rb +42 -0
  160. data/lib/git/commands/version.rb +60 -0
  161. data/lib/git/commands/worktree/add.rb +139 -0
  162. data/lib/git/commands/worktree/list.rb +64 -0
  163. data/lib/git/commands/worktree/lock.rb +58 -0
  164. data/lib/git/commands/worktree/management_base.rb +51 -0
  165. data/lib/git/commands/worktree/move.rb +66 -0
  166. data/lib/git/commands/worktree/prune.rb +67 -0
  167. data/lib/git/commands/worktree/remove.rb +63 -0
  168. data/lib/git/commands/worktree/repair.rb +76 -0
  169. data/lib/git/commands/worktree/unlock.rb +47 -0
  170. data/lib/git/commands/worktree.rb +43 -0
  171. data/lib/git/commands/write_tree.rb +68 -0
  172. data/lib/git/commands.rb +88 -0
  173. data/lib/git/config.rb +72 -5
  174. data/lib/git/config_entry_info.rb +106 -0
  175. data/lib/git/configuring.rb +795 -0
  176. data/lib/git/detached_head_info.rb +57 -0
  177. data/lib/git/diff.rb +437 -86
  178. data/lib/git/diff_file_numstat_info.rb +31 -0
  179. data/lib/git/diff_file_patch_info.rb +136 -0
  180. data/lib/git/diff_file_raw_info.rb +129 -0
  181. data/lib/git/diff_info.rb +162 -0
  182. data/lib/git/diff_path_status.rb +107 -0
  183. data/lib/git/diff_result.rb +34 -0
  184. data/lib/git/diff_stats.rb +111 -0
  185. data/lib/git/dirstat_info.rb +102 -0
  186. data/lib/git/encoding_utils.rb +32 -1
  187. data/lib/git/errors.rb +285 -0
  188. data/lib/git/escaped_path.rb +57 -5
  189. data/lib/git/execution_context/global.rb +31 -0
  190. data/lib/git/execution_context/repository.rb +151 -0
  191. data/lib/git/execution_context.rb +559 -0
  192. data/lib/git/factories.rb +813 -0
  193. data/lib/git/file_ref.rb +77 -0
  194. data/lib/git/fsck_object.rb +56 -0
  195. data/lib/git/fsck_result.rb +132 -0
  196. data/lib/git/log.rb +306 -90
  197. data/lib/git/object.rb +563 -141
  198. data/lib/git/parsers/branch.rb +240 -0
  199. data/lib/git/parsers/cat_file.rb +111 -0
  200. data/lib/git/parsers/config_entry.rb +110 -0
  201. data/lib/git/parsers/diff.rb +792 -0
  202. data/lib/git/parsers/fsck.rb +144 -0
  203. data/lib/git/parsers/grep.rb +42 -0
  204. data/lib/git/parsers/ls_remote.rb +79 -0
  205. data/lib/git/parsers/ls_tree.rb +58 -0
  206. data/lib/git/parsers/remote.rb +162 -0
  207. data/lib/git/parsers/stash.rb +292 -0
  208. data/lib/git/parsers/status.rb +251 -0
  209. data/lib/git/parsers/tag.rb +341 -0
  210. data/lib/git/parsers/worktree.rb +185 -0
  211. data/lib/git/path_resolver.rb +206 -0
  212. data/lib/git/remote.rb +165 -12
  213. data/lib/git/remote_info.rb +203 -0
  214. data/lib/git/repository/branching.rb +964 -0
  215. data/lib/git/repository/committing.rb +246 -0
  216. data/lib/git/repository/context_helpers.rb +293 -0
  217. data/lib/git/repository/diffing.rb +785 -0
  218. data/lib/git/repository/inspecting.rb +252 -0
  219. data/lib/git/repository/logging.rb +410 -0
  220. data/lib/git/repository/maintenance.rb +65 -0
  221. data/lib/git/repository/merging.rb +451 -0
  222. data/lib/git/repository/object_operations.rb +1551 -0
  223. data/lib/git/repository/remote_operations.rb +984 -0
  224. data/lib/git/repository/shared_private.rb +120 -0
  225. data/lib/git/repository/staging.rb +587 -0
  226. data/lib/git/repository/stashing.rb +623 -0
  227. data/lib/git/repository/status_operations.rb +249 -0
  228. data/lib/git/repository/worktree_operations.rb +339 -0
  229. data/lib/git/repository.rb +484 -2
  230. data/lib/git/stash.rb +109 -12
  231. data/lib/git/stash_info.rb +102 -0
  232. data/lib/git/stashes.rb +169 -26
  233. data/lib/git/status.rb +308 -122
  234. data/lib/git/status_file_info.rb +258 -0
  235. data/lib/git/status_info.rb +189 -0
  236. data/lib/git/tag_delete_failure.rb +34 -0
  237. data/lib/git/tag_delete_result.rb +66 -0
  238. data/lib/git/tag_info.rb +99 -0
  239. data/lib/git/url.rb +15 -8
  240. data/lib/git/version.rb +113 -2
  241. data/lib/git/version_constraint.rb +85 -0
  242. data/lib/git/worktree.rb +150 -8
  243. data/lib/git/worktree_info.rb +128 -0
  244. data/lib/git/worktrees.rb +118 -13
  245. data/lib/git.rb +632 -234
  246. metadata +369 -54
  247. data/.github/stale.yml +0 -25
  248. data/.github/workflows/continuous_integration.yml +0 -49
  249. data/.gitignore +0 -10
  250. data/Dockerfile.changelog-rs +0 -12
  251. data/Gemfile +0 -5
  252. data/ISSUE_TEMPLATE.md +0 -15
  253. data/PULL_REQUEST_TEMPLATE.md +0 -9
  254. data/RELEASING.md +0 -70
  255. data/Rakefile +0 -60
  256. data/lib/git/base/factory.rb +0 -99
  257. data/lib/git/base.rb +0 -711
  258. data/lib/git/command_line_result.rb +0 -86
  259. data/lib/git/failed_error.rb +0 -53
  260. data/lib/git/git_execute_error.rb +0 -7
  261. data/lib/git/index.rb +0 -5
  262. data/lib/git/lib.rb +0 -1328
  263. data/lib/git/path.rb +0 -31
  264. data/lib/git/signaled_error.rb +0 -50
  265. data/lib/git/working_directory.rb +0 -4
data/README.md CHANGED
@@ -3,425 +3,581 @@
3
3
  # @title README
4
4
  -->
5
5
 
6
- # The Git Gem
6
+ # The git gem
7
7
 
8
8
  [![Gem Version](https://badge.fury.io/rb/git.svg)](https://badge.fury.io/rb/git)
9
+ [![Build Status](https://github.com/ruby-git/ruby-git/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/ruby-git/ruby-git/actions/workflows/continuous_integration.yml)
9
10
  [![Documentation](https://img.shields.io/badge/Documentation-Latest-green)](https://rubydoc.info/gems/git/)
10
- [![Change Log](https://img.shields.io/badge/CHANGELOG-Latest-green)](https://rubydoc.info/gems/git/file/CHANGELOG.md)
11
- [![Build Status](https://github.com/ruby-git/ruby-git/workflows/CI/badge.svg?branch=master)](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI)
12
- [![Code Climate](https://codeclimate.com/github/ruby-git/ruby-git.png)](https://codeclimate.com/github/ruby-git/ruby-git)
11
+ [![Change
12
+ Log](https://img.shields.io/badge/CHANGELOG-Latest-green)](https://rubydoc.info/gems/git/file/CHANGELOG.md)
13
+ [![Conventional
14
+ Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white)](https://conventionalcommits.org)
15
+ [![AI Policy](https://img.shields.io/badge/AI%20Policy-Doc-blue)](AI_POLICY.md)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
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.
22
+
23
+ - [Summary](#summary)
24
+ - [Install](#install)
25
+ - [Quick start](#quick-start)
26
+ - [Examples](#examples)
27
+ - [Gem configuration](#gem-configuration)
28
+ - [Git configuration](#git-configuration)
29
+ - [Full API](#full-api)
30
+ - [Errors raised by this gem](#errors-raised-by-this-gem)
31
+ - [Specifying and handling timeouts](#specifying-and-handling-timeouts)
32
+ - [Deprecations](#deprecations)
33
+ - [Platform limitations](#platform-limitations)
34
+ - [Regex metacharacters on Git for Windows](#regex-metacharacters-on-git-for-windows)
35
+ - [Project policies](#project-policies)
36
+ - [Ruby version support policy](#ruby-version-support-policy)
37
+ - [Git version support policy](#git-version-support-policy)
38
+ - [Deprecation policy](#deprecation-policy)
39
+ - [Release support policy](#release-support-policy)
40
+ - [Project announcements](#project-announcements)
41
+ - [2026-08-23: v5.x deprecations and the v6.0.0 roadmap](#2026-08-23-v5x-deprecations-and-the-v600-roadmap)
42
+ - [2026-07-28: v5.0.0 released](#2026-07-28-v500-released)
43
+ - [2026-01-07: AI policy introduced](#2026-01-07-ai-policy-introduced)
44
+ - [2025-07-09: Architectural redesign](#2025-07-09-architectural-redesign)
45
+ - [2025-07-07: We now use RuboCop](#2025-07-07-we-now-use-rubocop)
46
+ - [2025-06-06: Default branch rename](#2025-06-06-default-branch-rename)
47
+ - [2025-05-15: We've switched to Conventional Commits](#2025-05-15-weve-switched-to-conventional-commits)
48
+
49
+ ## Summary
50
+
51
+ The [git gem](https://rubygems.org/gems/git) provides a Ruby interface to the `git`
52
+ command line.
53
+
54
+ Get a repository object by:
55
+
56
+ - opening an existing working copy with
57
+ [Git.open](https://rubydoc.info/gems/git/Git#open-class_method)
58
+ - initializing a new repository with
59
+ [Git.init](https://rubydoc.info/gems/git/Git#init-class_method)
60
+ - cloning a repository with
61
+ [Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method)
62
+
63
+ [Git::Repository](https://rubydoc.info/gems/git/Git/Repository) documents the
64
+ methods you can call on a repository object.
13
65
 
14
- The [git gem](https://rubygems.org/gems/git) provides an API that can be used to
15
- create, read, and manipulate Git repositories by wrapping system calls to the `git`
16
- command line. The API can be used for working with Git in complex interactions
17
- including branching and merging, object inspection and manipulation, history, patch
18
- generation and more.
66
+ ## Install
19
67
 
20
- ## v2.0.0 pre-release
68
+ 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
70
+ policy](#git-version-support-policy) for details.
21
71
 
22
- git 2.0.0 is available as a pre-release version for testing! Please give it a try.
72
+ Install the gem and add to the application's Gemfile by executing:
23
73
 
24
- **JRuby on Windows is not yet supported by the 2.x release line. Users running JRuby
25
- on Windows should continue to use the 1.x release line.**
74
+ ```shell
75
+ bundle add git
76
+ ```
26
77
 
27
- The changes coming in this major release include:
78
+ If you are not using bundler to manage dependencies, install the gem by executing:
28
79
 
29
- * Create a policy of supported Ruby versions to support only non-EOL Ruby versions
30
- * Create a policy of supported Git CLI versions (released 2020-12-25)
31
- * Update the required Ruby version to at least 3.0 (released 2020-07-27)
32
- * Update the required Git command line version to at least 2.28
33
- * Update how CLI commands are called to use the [process_executer](https://github.com/main-branch/process_executer)
34
- gem which is built on top of [Kernel.spawn](https://ruby-doc.org/3.3.0/Kernel.html#method-i-spawn).
35
- See [PR #617](https://github.com/ruby-git/ruby-git/pull/617) for more details
36
- on the motivation for this implementation.
80
+ ```shell
81
+ gem install git
82
+ ```
37
83
 
38
- The tentative plan is to release `2.0.0` near the end of March 2024 depending on
39
- the feedback received during the pre-release period.
84
+ ## Quick start
40
85
 
41
- The `master` branch will be used for `2.x` development. If needed, fixes for `1.x`
42
- version will be done on the `v1` branch.
86
+ All functionality for this gem starts with the top-level
87
+ [`Git`](https://rubydoc.info/gems/git/Git) module. Use this module to run non-repo
88
+ scoped `git` commands such as `config`.
43
89
 
44
- ## Homepage
90
+ The `Git` module also has factory methods such as `open`, `clone`, and `init` which
91
+ return a [`Git::Repository`](https://rubydoc.info/gems/git/Git/Repository) object. Use
92
+ the `Git::Repository` object to run repo-specific `git` commands such as `add`,
93
+ `commit`, `push`, and `log`.
45
94
 
46
- The project source code is at:
95
+ Clone, read status, and log:
47
96
 
48
- http://github.com/ruby-git/ruby-git
97
+ ```ruby
98
+ require 'git'
49
99
 
50
- ## Documentation
100
+ repo = Git.clone('https://github.com/ruby-git/ruby-git.git', 'ruby-git')
101
+ repo.status_info.changed.each_key { |path| puts "changed: #{path}" }
102
+ repo.log(5).execute.each { |c| puts c.message }
103
+ ```
51
104
 
52
- Detailed documentation can be found at:
105
+ Open an existing repo and commit:
53
106
 
54
- https://rubydoc.info/gems/git/Git.html
107
+ ```ruby
108
+ require 'git'
55
109
 
56
- Get started by obtaining a repository object by:
110
+ repo = Git.open('/path/to/repo')
111
+ repo.add(all: true)
112
+ repo.commit('chore: update files')
113
+ repo.push
114
+ ```
57
115
 
58
- * opening an existing working copy with [Git.open](https://rubydoc.info/gems/git/Git#open-class_method)
59
- * initializing a new repository with [Git.init](https://rubydoc.info/gems/git/Git#init-class_method)
60
- * cloning a repository with [Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method)
116
+ Initialize a new repo and make the first commit:
61
117
 
62
- Methods that can be called on a repository object are documented in [Git::Base](https://rubydoc.info/gems/git/Git/Base)
118
+ ```ruby
119
+ require 'git'
63
120
 
64
- ## Install
121
+ repo = Git.init('my_project')
122
+ repo.add(all: true)
123
+ repo.commit('initial commit')
124
+ ```
125
+
126
+ ## Examples
127
+
128
+ These examples cover configuring the gem and git itself. For the full set of
129
+ repository operations, see [Full API](#full-api) below.
130
+
131
+ ### Gem configuration
132
+
133
+ Configure the git gem:
65
134
 
66
- You can install Ruby/Git like this:
135
+ ```ruby
136
+ Git.configure do |config|
137
+ config.binary_path = '/usr/local/bin/git'
138
+ config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
139
+ end
67
140
 
141
+ # or
142
+
143
+ Git.config.binary_path = '/usr/local/bin/git'
144
+ Git.config.git_ssh = 'ssh -i ~/.ssh/id_rsa'
68
145
  ```
69
- sudo gem install git
146
+
147
+ How SSH configuration is determined:
148
+
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).
155
+
156
+ You can also specify a custom SSH script on a per-repository basis:
157
+
158
+ ```ruby
159
+ # Use a specific SSH key for a single repository
160
+ git = Git.open('/path/to/repo', git_ssh: 'ssh -i /path/to/private_key')
161
+
162
+ # Or when cloning
163
+ git = Git.clone('git@github.com:user/repo.git', 'local-dir',
164
+ git_ssh: 'ssh -i /path/to/private_key')
165
+
166
+ # Or when initializing
167
+ git = Git.init('new-repo', git_ssh: 'ssh -i /path/to/private_key')
70
168
  ```
71
169
 
72
- ## Code Status
170
+ This is especially useful in multi-threaded applications where different repositories
171
+ require different SSH credentials.
172
+
173
+ ### Git configuration
73
174
 
175
+ Read and set `git` configuration values (via `git config`):
74
176
 
75
- ## Major Objects
177
+ ```ruby
178
+ # Global config (in ~/.gitconfig)
179
+ entries = Git.config_list(global: true) # returns Array<Git::ConfigEntryInfo>
180
+ entry = Git.config_get('user.email', global: true) # returns Git::ConfigEntryInfo or nil
181
+ email = entry&.value # => "user@example.com" or nil
182
+ Git.config_set('user.email', 'user@example.com', global: true)
183
+
184
+ # Repository config
185
+ repo = Git.open('path/to/repo')
186
+ entries = repo.config_list # returns Array<Git::ConfigEntryInfo>
187
+ entry = repo.config_get('user.email') # returns Git::ConfigEntryInfo or nil
188
+ email = entry&.value # => "anotheruser@example.com" or nil
189
+ repo.config_set('user.email', 'anotheruser@example.com')
190
+ ```
76
191
 
77
- **Git::Base** - The object returned from a `Git.open` or `Git.clone`. Most major actions are called from this object.
192
+ ### Full API
78
193
 
79
- **Git::Object** - The base object for your tree, blob and commit objects, returned from `@git.gtree` or `@git.object` calls. the `Git::AbstractObject` will have most of the calls in common for all those objects.
194
+ The quick start and the configuration sections above cover the most common setup.
195
+ The [`Git::Repository`](https://rubydoc.info/gems/git/Git/Repository) reference
196
+ covers everything else: reading history, diffs, branches, remotes, worktrees,
197
+ staging, and low-level index and tree work. It documents every method and the object
198
+ 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.
80
201
 
81
- **Git::Diff** - returns from a `@git.diff` command. It is an Enumerable that returns `Git::Diff:DiffFile` objects from which you can get per file patches and insertion/deletion statistics. You can also get total statistics from the Git::Diff object directly.
202
+ ## Errors raised by this gem
82
203
 
83
- **Git::Status** - returns from a `@git.status` command. It is an Enumerable that returns
84
- `Git:Status::StatusFile` objects for each object in git, which includes files in the working
85
- directory, in the index and in the repository. Similar to running 'git status' on the command line to determine untracked and changed files.
204
+ The git gem raises only `ArgumentError` or errors that subclass `Git::Error`. It
205
+ does not explicitly raise any other types of errors.
86
206
 
87
- **Git::Branches** - Enumerable object that holds `Git::Branch objects`. You can call .local or .remote on it to filter to just your local or remote branches.
207
+ Rescue `Git::Error` to catch any runtime error raised by this gem, unless you need
208
+ more specific error handling.
88
209
 
89
- **Git::Remote**- A reference to a remote repository that is tracked by this repository.
210
+ ```ruby
211
+ begin
212
+ # some git operation
213
+ rescue Git::Error => e
214
+ puts "An error occurred: #{e.message}"
215
+ end
216
+ ```
90
217
 
91
- **Git::Log** - An Enumerable object that references all the `Git::Object::Commit` objects that encompass your log query, which can be constructed through methods on the `Git::Log object`,
92
- like:
218
+ See [`Git::Error`](https://rubydoc.info/gems/git/Git/Error) for more information.
93
219
 
94
- `@git.log(20).object("some_file").since("2 weeks ago").between('v2.6', 'v2.7').each { |commit| [block] }`
220
+ ## Specifying and handling timeouts
95
221
 
96
- Pass the `--all` option to `git log` as follows:
222
+ Set a timeout for git command line operations either globally or per method call for
223
+ methods that accept a `:timeout` parameter.
97
224
 
98
- `@git.log.all.each { |commit| [block] }`
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.
99
229
 
100
- **Git::Worktrees** - Enumerable object that holds `Git::Worktree objects`.
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`.
101
232
 
102
- ## Examples
233
+ If the timeout value is `0` or `nil`, no timeout is enforced.
103
234
 
104
- Here are a bunch of examples of how to use the Ruby/Git package.
235
+ If a method accepts a `:timeout` parameter and receives a non-nil value, that value
236
+ overrides the global timeout. In this context, a value of `nil`, which is usually
237
+ the default, uses the global timeout value, and a value of `0` turns off timeout
238
+ enforcement for that method call no matter what the global value is.
105
239
 
106
- Ruby < 1.9 will require rubygems to be loaded.
240
+ To set a global timeout, use the `Git.config` object:
107
241
 
108
242
  ```ruby
109
- require 'rubygems'
243
+ Git.config.timeout = nil # a value of nil or 0 means no timeout is enforced
244
+ Git.config.timeout = 1.5 # can be any real, non-negative Numeric interpreted as number of seconds
110
245
  ```
111
246
 
112
- Require the 'git' gem.
247
+ The global timeout can be overridden for a specific method if the method accepts a
248
+ `:timeout` parameter:
249
+
113
250
  ```ruby
114
- require 'git'
251
+ repo_url = 'https://github.com/ruby-git/ruby-git.git'
252
+ Git.clone(repo_url) # Use the global timeout value
253
+ Git.clone(repo_url, timeout: nil) # Also uses the global timeout value
254
+ Git.clone(repo_url, timeout: 0) # Do not enforce a timeout
255
+ Git.clone(repo_url, timeout: 10.5) # Timeout after 10.5 seconds raising Git::TimeoutError
115
256
  ```
116
257
 
117
- Git env config
258
+ If the command takes too long, the gem raises `Git::TimeoutError`:
118
259
 
119
260
  ```ruby
120
- Git.configure do |config|
121
- # If you want to use a custom git binary
122
- config.binary_path = '/git/bin/path'
123
-
124
- # If you need to use a custom SSH script
125
- config.git_ssh = '/path/to/ssh/script'
261
+ begin
262
+ Git.clone(repo_url, timeout: 10)
263
+ rescue Git::TimeoutError => e
264
+ e.result.tap do |r|
265
+ r.class #=> Git::CommandLineResult
266
+ r.status #=> #<Process::Status: pid 62173 SIGKILL (signal 9)>
267
+ r.status.timeout? #=> true
268
+ r.git_cmd # The git command ran as an array of strings
269
+ r.stdout # The command's output to stdout until it was terminated
270
+ r.stderr # The command's output to stderr until it was terminated
271
+ end
126
272
  end
127
273
  ```
128
274
 
129
- _NOTE: Another way to specify where is the `git` binary is through the environment variable `GIT_PATH`_
275
+ ## Deprecations
276
+
277
+ This gem uses ActiveSupport's deprecation mechanism to report deprecation warnings.
130
278
 
131
- Here are the operations that need read permission only.
279
+ You can silence deprecation warnings by adding this line to your source code:
132
280
 
133
281
  ```ruby
134
- g = Git.open(working_dir, :log => Logger.new(STDOUT))
135
-
136
- g.index
137
- g.index.readable?
138
- g.index.writable?
139
- g.repo
140
- g.dir
141
-
142
- g.log # returns a Git::Log object, which is an Enumerator of Git::Commit objects
143
- g.log(200)
144
- g.log.since('2 weeks ago')
145
- g.log.between('v2.5', 'v2.6')
146
- g.log.each {|l| puts l.sha }
147
- g.gblob('v2.5:Makefile').log.since('2 weeks ago')
148
-
149
- g.object('HEAD^').to_s # git show / git rev-parse
150
- g.object('HEAD^').contents
151
- g.object('v2.5:Makefile').size
152
- g.object('v2.5:Makefile').sha
153
-
154
- g.gtree(treeish)
155
- g.gblob(treeish)
156
- g.gcommit(treeish)
157
-
158
-
159
- commit = g.gcommit('1cc8667014381')
160
-
161
- commit.gtree
162
- commit.parent.sha
163
- commit.parents.size
164
- commit.author.name
165
- commit.author.email
166
- commit.author.date.strftime("%m-%d-%y")
167
- commit.committer.name
168
- commit.date.strftime("%m-%d-%y")
169
- commit.message
170
-
171
- tree = g.gtree("HEAD^{tree}")
172
-
173
- tree.blobs
174
- tree.subtrees
175
- tree.children # blobs and subtrees
176
-
177
- g.revparse('v2.5:Makefile')
178
-
179
- g.branches # returns Git::Branch objects
180
- g.branches.local
181
- g.current_branch
182
- g.branches.remote
183
- g.branches[:master].gcommit
184
- g.branches['origin/master'].gcommit
185
-
186
- g.grep('hello') # implies HEAD
187
- g.blob('v2.5:Makefile').grep('hello')
188
- g.tag('v2.5').grep('hello', 'docs/')
189
- g.describe()
190
- g.describe('0djf2aa')
191
- g.describe('HEAD', {:all => true, :tags => true})
192
-
193
- g.diff(commit1, commit2).size
194
- g.diff(commit1, commit2).stats
195
- g.diff(commit1, commit2).name_status
196
- g.gtree('v2.5').diff('v2.6').insertions
197
- g.diff('gitsearch1', 'v2.5').path('lib/')
198
- g.diff('gitsearch1', @git.gtree('v2.5'))
199
- g.diff('gitsearch1', 'v2.5').path('docs/').patch
200
- g.gtree('v2.5').diff('v2.6').patch
201
-
202
- g.gtree('v2.5').diff('v2.6').each do |file_diff|
203
- puts file_diff.path
204
- puts file_diff.patch
205
- puts file_diff.blob(:src).contents
206
- end
282
+ Git::Deprecation.behavior = :silence
283
+ ```
207
284
 
208
- g.worktrees # returns Git::Worktree objects
209
- g.worktrees.count
210
- g.worktrees.each do |worktree|
211
- worktree.dir
212
- worktree.gcommit
213
- worktree.to_s
214
- end
285
+ Or by setting this environment variable before loading the gem:
286
+
287
+ ```sh
288
+ GIT_DEPRECATION_BEHAVIOR=silence
289
+ ```
290
+
291
+ Accepted environment variable values are the behavior names supported by your
292
+ installed ActiveSupport version.
215
293
 
216
- g.config('user.name') # returns 'Scott Chacon'
217
- g.config # returns whole config hash
294
+ If `GIT_DEPRECATION_BEHAVIOR` is set to an unsupported value, loading the gem
295
+ raises `ArgumentError` with the accepted behavior names.
218
296
 
219
- # Configuration can be set when cloning using the :config option.
220
- # This option can be an single configuration String or an Array
221
- # if multiple config items need to be set.
222
- #
223
- g = Git.clone(
224
- git_uri, destination_path,
225
- :config => [
226
- 'core.sshCommand=ssh -i /home/user/.ssh/id_rsa',
227
- 'submodule.recurse=true'
228
- ]
229
- )
297
+ See [the Active Support Deprecation
298
+ documentation](https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.html)
299
+ for more details.
230
300
 
231
- g.tags # returns array of Git::Tag objects
301
+ 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
303
+ that you cannot miss one.
232
304
 
233
- g.show()
234
- g.show('HEAD')
235
- g.show('v2.8', 'README.md')
305
+ For the full list of deprecated methods and their replacements, see
306
+ [UPGRADING.md](UPGRADING.md).
236
307
 
237
- Git.ls_remote('https://github.com/ruby-git/ruby-git.git') # returns a hash containing the available references of the repo.
238
- Git.ls_remote('/path/to/local/repo')
239
- Git.ls_remote() # same as Git.ls_remote('.')
308
+ ## Platform limitations
240
309
 
241
- Git.default_branch('https://github.com/ruby-git/ruby-git') #=> 'master'
310
+ ### Regex metacharacters on Git for Windows
311
+
312
+ On Git for Windows, git's regex engine matches **bytes** rather than characters. A
313
+ metacharacter such as `.`, or a POSIX character class such as `[[:alpha:]]`, therefore
314
+ never matches a whole multi-byte character. The same call matches on Linux and macOS.
315
+
316
+ The failure is silent. Nothing raises, and the result is indistinguishable from a
317
+ pattern that genuinely does not occur:
318
+
319
+ ```ruby
320
+ # File content, commit message, and config value are all 'ÄPFEL sind gut'.
321
+ # 'Ä' is two bytes in UTF-8 (C3 84), so '.' has to match both to match the character.
322
+
323
+ repo.grep('^.PFEL') # => {} on Windows, matches elsewhere
324
+ repo.log.grep('^.PFEL').execute.size # => 0 on Windows, 1 elsewhere
325
+ repo.config_get_all('test.desc', '^.PFEL') # => [] on Windows, matches elsewhere
242
326
  ```
243
327
 
244
- And here are the operations that will need to write to your git repository.
328
+ This is a property of the regex engine git bundles on that platform, not something the
329
+ gem sets. It is unaffected by the locale: the behavior is identical under `en_US.UTF-8`,
330
+ `C.UTF-8`, `C`, and with no `LC_ALL` set at all. Literal (metacharacter-free) patterns
331
+ and case-insensitive matching are unaffected on every platform.
332
+
333
+ **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:
245
335
 
246
336
  ```ruby
247
- g = Git.init
248
- Git.init('project')
249
- Git.init('/home/schacon/proj',
250
- { :repository => '/opt/git/proj.git',
251
- :index => '/tmp/index'} )
252
-
253
- # Clone from a git url
254
- git_url = 'https://github.com/ruby-git/ruby-git.git'
255
- # Clone into the ruby-git directory
256
- g = Git.clone(git_url)
257
-
258
- # Clone into /tmp/clone/ruby-git-clean
259
- name = 'ruby-git-clean'
260
- path = '/tmp/clone'
261
- g = Git.clone(git_url, name, :path => path)
262
- g.dir #=> /tmp/clone/ruby-git-clean
263
-
264
- g.config('user.name', 'Scott Chacon')
265
- g.config('user.email', 'email@email.com')
266
-
267
- # Clone can take a filter to tell the serve to send a partial clone
268
- g = Git.clone(git_url, name, :path => path, :filter => 'tree:0')
269
-
270
- # Clone can take an optional logger
271
- logger = Logger.new
272
- g = Git.clone(git_url, NAME, :log => logger)
273
-
274
- g.add # git add -- "."
275
- g.add(:all=>true) # git add --all -- "."
276
- g.add('file_path') # git add -- "file_path"
277
- g.add(['file_path_1', 'file_path_2']) # git add -- "file_path_1" "file_path_2"
278
-
279
- g.remove() # git rm -f -- "."
280
- g.remove('file.txt') # git rm -f -- "file.txt"
281
- g.remove(['file.txt', 'file2.txt']) # git rm -f -- "file.txt" "file2.txt"
282
- g.remove('file.txt', :recursive => true) # git rm -f -r -- "file.txt"
283
- g.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt"
284
-
285
- g.commit('message')
286
- g.commit_all('message')
287
-
288
- # Sign a commit using the gpg key configured in the user.signingkey config setting
289
- g.config('user.signingkey', '0A46826A')
290
- g.commit('message', gpg_sign: true)
291
-
292
- # Sign a commit using a specified gpg key
293
- key_id = '0A46826A'
294
- g.commit('message', gpg_sign: key_id)
295
-
296
- # Skip signing a commit (overriding any global gpgsign setting)
297
- g.commit('message', no_gpg_sign: true)
298
-
299
- g = Git.clone(repo, 'myrepo')
300
- g.chdir do
301
- new_file('test-file', 'blahblahblah')
302
- g.status.changed.each do |file|
303
- puts file.blob(:index).contents
304
- end
305
- end
337
+ repo.grep('^.PFEL', nil, perl_regexp: true) # matches on every platform
338
+ repo.log.perl_regexp.grep('^.PFEL').execute # matches on every platform
339
+ repo.full_log_commits(grep: '^.PFEL', perl_regexp: true)
340
+ ```
306
341
 
307
- g.reset # defaults to HEAD
308
- g.reset_hard(Git::Commit)
342
+ Two caveats:
309
343
 
310
- g.branch('new_branch') # creates new or fetches existing
311
- g.branch('new_branch').checkout
312
- g.branch('new_branch').delete
313
- g.branch('existing_branch').checkout
314
- g.branch('master').contains?('existing_branch')
344
+ - **PCRE is a different dialect.** Git's other modes are POSIX basic regular
345
+ expressions (the default) and POSIX extended regular expressions (selected
346
+ explicitly). Selecting PCRE is a deliberate choice by the caller, so the gem does
347
+ not substitute it automatically based on the host.
348
+ - **PCRE must be compiled in.** Git for Windows and the mainstream Linux and macOS
349
+ packages ship it, but git built without `USE_LIBPCRE` fails with `cannot use
350
+ Perl-compatible regexes...`.
315
351
 
316
- # delete remote branch
317
- g.push('origin', 'remote_branch_name', force: true, delete: true)
352
+ **There is no workaround for `git config` value patterns.** They are POSIX extended
353
+ regular expressions with no PCRE mode, so `config_get`, `config_get_all`,
354
+ `config_get_regexp`, `config_replace_all`, `config_unset`, and `config_unset_all` cannot
355
+ match a metacharacter against a non-ASCII character on Git for Windows. Match on ASCII
356
+ text or an exact value instead.
318
357
 
319
- g.checkout('new_branch')
320
- g.checkout('new_branch', new_branch: true, start_point: 'master')
321
- g.checkout(g.branch('new_branch'))
358
+ `config_replace_all` deserves particular care, because there the failure is worse than
359
+ an empty result. When the value pattern selects nothing, `git config --replace-all`
360
+ *adds* the new value as an additional entry rather than replacing one, and exits zero:
322
361
 
323
- g.branch(name).merge(branch2)
324
- g.branch(branch2).merge # merges HEAD with branch2
362
+ ```ruby
363
+ # Existing value of test.desc is 'ÄPFEL sind gut'
364
+ repo.config_replace_all('test.desc', 'NEW', '^.PFEL')
325
365
 
326
- g.branch(name).in_branch(message) { # add files } # auto-commits
327
- g.merge('new_branch')
328
- g.merge('new_branch', 'merge commit message', no_ff: true)
329
- g.merge('origin/remote_branch')
330
- g.merge(g.branch('master'))
331
- g.merge([branch1, branch2])
366
+ repo.config_get_all('test.desc').map(&:value)
367
+ # => ["NEW"] elsewhere, replaced as intended
368
+ # => ["ÄPFEL sind gut", "NEW"] on Windows, original kept and duplicate added
369
+ ```
332
370
 
333
- g.merge_base('branch1', 'branch2')
371
+ So a replace can silently leave the original value in place and add a second entry beside
372
+ it. Confirm with `config_get_all` when the key must end up single-valued.
373
+
374
+ ## Project policies
334
375
 
335
- r = g.add_remote(name, uri) # Git::Remote
336
- r = g.add_remote(name, Git::Base) # Git::Remote
376
+ These documents set expectations for behavior, contribution workflows, AI-assisted
377
+ changes, decision making, maintainer roles, and licensing. Please review them before
378
+ opening issues or pull requests.
379
+
380
+ | Document | Description |
381
+ | -------- | ----------- |
382
+ | [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) | We follow the Ruby community Code of Conduct; expect respectful, harassment-free participation and report concerns to maintainers. |
383
+ | [CONTRIBUTING](CONTRIBUTING.md) | How to report issues, submit PRs with Conventional Commits, meet coding/testing standards, and follow the Code of Conduct. |
384
+ | [AI_POLICY](AI_POLICY.md) | AI-assisted contributions are welcome. Contributors are expected to read and apply the AI Policy, and ensure any AI-assisted work meets our quality, security, and licensing standards. |
385
+ | [Ruby version support policy](#ruby-version-support-policy) | Supported Ruby runtimes and platforms; bump decisions and CI coverage expectations. |
386
+ | [Git version support policy](#git-version-support-policy) | Minimum supported git version and how version bumps are communicated and enforced. |
387
+ | [Deprecation policy](#deprecation-policy) | When an API may be removed, what a deprecation warning says, and how to upgrade across a major version. |
388
+ | [Release support policy](#release-support-policy) | Which branch releases what, and how long each major series is supported. |
389
+ | [GOVERNANCE](GOVERNANCE.md) | Principles-first governance defining maintainer/project lead roles, least-privilege access, consensus/majority decisions, and nomination/emeritus steps. |
390
+ | [MAINTAINERS](MAINTAINERS.md) | Lists active maintainers (Project Lead noted) and emeritus alumni with links; see governance for role scope. |
391
+ | [LICENSE](LICENSE) | MIT License terms for using, modifying, and redistributing this project. |
337
392
 
338
- g.remotes # array of Git::Remotes
339
- g.remote(name).fetch
340
- g.remote(name).remove
341
- g.remote(name).merge
342
- g.remote(name).merge(branch)
393
+ ### Ruby version support policy
343
394
 
344
- g.fetch
345
- g.fetch(g.remotes.first)
346
- g.fetch('origin', {:ref => 'some/ref/head'} )
347
- g.fetch(all: true, force: true, depth: 2)
348
- g.fetch('origin', {:'update-head-ok' => true})
395
+ This gem is expected to function correctly on:
349
396
 
350
- g.pull
351
- g.pull(Git::Repo, Git::Branch) # fetch and a merge
397
+ - All [non-EOL versions](https://www.ruby-lang.org/en/downloads/branches/) of the MRI
398
+ 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
352
401
 
353
- g.add_tag('tag_name') # returns Git::Tag
354
- g.add_tag('tag_name', 'object_reference')
355
- g.add_tag('tag_name', 'object_reference', {:options => 'here'})
356
- g.add_tag('tag_name', {:options => 'here'})
402
+ This project intends to support the latest version of JRuby on Windows once
403
+ the [process_executer](https://github.com/main-branch/process_executer) gem properly
404
+ supports subprocess status reporting on JRuby for Windows (see
405
+ [main-branch/process_executer#156](https://github.com/main-branch/process_executer/issues/156)).
357
406
 
358
- Options:
359
- :a | :annotate
360
- :d
361
- :f
362
- :m | :message
363
- :s
407
+ ### Git version support policy
364
408
 
365
- g.delete_tag('tag_name')
409
+ This gem requires git version 2.28.0 or greater as specified in the gemspec. This
410
+ requirement reflects:
366
411
 
367
- g.repack
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
368
416
 
369
- g.push
370
- g.push(g.remote('name'))
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.
371
420
 
372
- # delete remote branch
373
- g.push('origin', 'remote_branch_name', force: true, delete: true)
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.
374
424
 
375
- # push all branches to remote at one time
376
- g.push('origin', all: true)
425
+ ### Deprecation policy
377
426
 
378
- g.worktree('/tmp/new_worktree').add
379
- g.worktree('/tmp/new_worktree', 'branch1').add
380
- g.worktree('/tmp/new_worktree').remove
381
- g.worktrees.prune
382
- ```
427
+ This gem removes an API only in a major release, and only after a normal release
428
+ deprecated it with a runtime warning and documented its replacement in
429
+ [UPGRADING.md](UPGRADING.md). A normal release is one that is not a pre-release. The
430
+ warning names the major release that removes the API once that is decided. Until then
431
+ it says the API will be removed in a future major release.
432
+
433
+ The recommended way to upgrade across a major version:
434
+
435
+ 1. Upgrade to the latest release of the major series you are on.
436
+ 2. Set `GIT_DEPRECATION_BEHAVIOR=raise` (or `Git::Deprecation.behavior = :raise`) in
437
+ your test suite and, if possible, staging.
438
+ 3. Fix each deprecation using the entries in [UPGRADING.md](UPGRADING.md) until the
439
+ suite is clean.
440
+ 4. Upgrade to the next major release.
441
+
442
+ 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.
446
+
447
+ ### Release support policy
448
+
449
+ All development happens on `main`, which releases the next version of the gem,
450
+ including the next major version. The next release from `main` is v6.0.0. Every
451
+ further v5.x release is cut from `5.x`.
452
+
453
+ Each supported previous major series is maintained on a branch named for that
454
+ series, currently `5.x` and `4.x`. These branches receive bug fixes and security
455
+ fixes, and backward-compatible features at the maintainers' discretion. Fixes land on
456
+ `main` first and are backported, except a fix for a problem that exists only in a
457
+ maintenance branch, which targets that branch directly.
458
+
459
+ Support for a major series ends when the second major after it is released. v4.x is
460
+ supported until v6.0.0 ships, and v5.x until v7.0.0.
461
+
462
+ ## Project announcements
463
+
464
+ ### 2026-08-23: v5.x deprecations and the v6.0.0 roadmap
465
+
466
+ The road to v6.0.0 is now planned and public. The remaining ActiveRecord-style
467
+ classes (`Git::Branch`, `Git::Remote`, `Git::Stash`, `Git::Worktree`,
468
+ `Git::Object::Tag`, `Git::Status`, `Git::Author`, and their collections) will be
469
+ deprecated during the v5.x series in favor of the immutable `*Info` value-object
470
+ APIs. v6.0.0 will remove each deprecated class once a normal v5.x release has carried
471
+ its deprecation warning and UPGRADING.md entry, per the
472
+ [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.
475
+
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
479
+ [UPGRADING.md](UPGRADING.md) carries the migration guide as releases ship.
480
+
481
+ ### 2026-07-28: v5.0.0 released
482
+
483
+ We have published [`git v5.0.0`](https://rubygems.org/gems/git/versions/5.0.0), the
484
+ first stable release of the v5.x series, after five public beta releases in June and
485
+ July 2026.
383
486
 
384
- Some examples of more low-level index and tree operations
487
+ **v5.0.0 is a major release with breaking changes.** See
488
+ [UPGRADING.md](UPGRADING.md) for the complete migration guide.
489
+
490
+ To install:
385
491
 
386
492
  ```ruby
387
- g.with_temp_index do
493
+ gem 'git', '~> 5.0'
494
+ ```
388
495
 
389
- g.read_tree(tree3) # calls self.index.read_tree
390
- g.read_tree(tree1, :prefix => 'hi/')
496
+ Or:
391
497
 
392
- c = g.commit_tree('message')
393
- # or #
394
- t = g.write_tree
395
- c = g.commit_tree(t, :message => 'message', :parents => [sha1, sha2])
498
+ ```sh
499
+ gem install git
500
+ ```
396
501
 
397
- g.branch('branch_name').update_ref(c)
398
- g.update_ref(branch, c)
502
+ Most v4.x code requires no changes. Compatibility shims keep the old API working
503
+ while emitting deprecation warnings that tell you what to migrate before v6.0.0.
399
504
 
400
- g.with_temp_working do # new blank working directory
401
- g.checkout
402
- g.checkout(another_index)
403
- g.commit # commits to temp_index
404
- end
405
- end
505
+ ### 2026-01-07: AI policy introduced
406
506
 
407
- g.set_index('/path/to/index')
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.
408
511
 
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.
409
514
 
410
- g.with_index(path) do
411
- # calls set_index, then switches back after
412
- end
515
+ ### 2025-07-09: Architectural redesign
413
516
 
414
- g.with_working(dir) do
415
- # calls set_working, then switches back after
416
- end
517
+ 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.
417
521
 
418
- g.with_temp_working(dir) do
419
- g.checkout_index(:prefix => dir, :path_limiter => path)
420
- # do file work
421
- g.commit # commits to index
422
- end
522
+ **The redesign shipped in v5.0.0 and is complete.** `Git::Base` and `Git::Lib` are
523
+ gone, along with the `g.lib` accessor. See [UPGRADING.md](UPGRADING.md) for what
524
+ changed and how to migrate.
525
+
526
+ The three documents written to plan it are kept as a historical record in
527
+ [`archive/v5-redesign/`](archive/v5-redesign/). They describe the state of the code
528
+ before and during the migration and are not current policy. The standards that apply
529
+ to new code live in [`.github/skills/`](.github/skills/).
530
+
531
+ 1. [Analysis of the Current Architecture](archive/v5-redesign/1_architecture_existing.md):
532
+ a breakdown of the v4.x design and its challenges.
533
+ 2. [The Proposed Redesign](archive/v5-redesign/2_architecture_redesign.md): an overview
534
+ of the three-layer architecture.
535
+ 3. [Implementation Plan](archive/v5-redesign/3_architecture_implementation.md): the
536
+ step-by-step plan that was followed.
537
+
538
+ ### 2025-07-07: We now use RuboCop
539
+
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.
544
+
545
+ Run RuboCop from the project's Rakefile:
546
+
547
+ ```shell
548
+ rake rubocop
423
549
  ```
424
550
 
425
- ## License
551
+ RuboCop also runs as part of the default rake task, which our continuous integration
552
+ workflow runs.
553
+
554
+ PRs with RuboCop offenses will not be merged. In rare cases, it might be acceptable
555
+ to disable a RuboCop check for the most limited scope possible.
556
+
557
+ If you have a problem fixing a RuboCop offense, don't be afraid to ask a
558
+ contributor.
559
+
560
+ ### 2025-06-06: Default branch rename
561
+
562
+ On June 6, 2025, we renamed the default branch from `master` to `main`.
563
+
564
+ Instructions for renaming your local or forked branch to match are in the gist
565
+ [Default Branch Name
566
+ Change](https://gist.github.com/jcouball/580a10e395f7fdfaaa4297bbe816cc7d).
567
+
568
+ ### 2025-05-15: We've switched to Conventional Commits
569
+
570
+ The `ruby-git` project has adopted the [Conventional Commits
571
+ standard](https://www.conventionalcommits.org/en/v1.0.0/) for all commit messages.
572
+ This enables automated changelog generation and is a step toward continuous
573
+ delivery.
574
+
575
+ All commits to this repository must follow the Conventional Commits standard.
576
+ Commits that do not follow it will fail the CI build, and PRs that include them will
577
+ not be merged.
578
+
579
+ To validate your commit messages locally before pushing them to GitHub, install the
580
+ git `commit-msg` hook by running `bin/setup` in the project root.
426
581
 
427
- licensed under MIT License Copyright (c) 2008 Scott Chacon. See LICENSE for further details.
582
+ Read more about this change in the [Commit Message Guidelines section of
583
+ CONTRIBUTING.md](CONTRIBUTING.md#commit-message-guidelines).