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.
- checksums.yaml +4 -4
- data/.yardopts +5 -1
- data/AI_POLICY.md +24 -0
- data/CHANGELOG.md +689 -0
- data/CODE_OF_CONDUCT.md +25 -0
- data/CONTRIBUTING.md +1175 -97
- data/GOVERNANCE.md +106 -0
- data/LICENSE +1 -1
- data/MAINTAINERS.md +17 -4
- data/README.md +476 -320
- data/UPGRADING.md +1138 -0
- data/git.gemspec +124 -36
- data/lib/git/author.rb +39 -7
- data/lib/git/author_info.rb +66 -0
- data/lib/git/branch.rb +615 -65
- data/lib/git/branch_delete_failure.rb +34 -0
- data/lib/git/branch_delete_result.rb +66 -0
- data/lib/git/branch_info.rb +237 -0
- data/lib/git/branches.rb +167 -44
- data/lib/git/command_line/base.rb +247 -0
- data/lib/git/command_line/capturing.rb +308 -0
- data/lib/git/command_line/result.rb +88 -0
- data/lib/git/command_line/streaming.rb +236 -0
- data/lib/git/command_line.rb +52 -0
- data/lib/git/commands/add.rb +139 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +263 -0
- data/lib/git/commands/am/continue.rb +43 -0
- data/lib/git/commands/am/quit.rb +43 -0
- data/lib/git/commands/am/retry.rb +49 -0
- data/lib/git/commands/am/show_current_patch.rb +64 -0
- data/lib/git/commands/am/skip.rb +42 -0
- data/lib/git/commands/am.rb +33 -0
- data/lib/git/commands/apply.rb +242 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +145 -0
- data/lib/git/commands/arguments.rb +4521 -0
- data/lib/git/commands/base.rb +502 -0
- data/lib/git/commands/branch/copy.rb +102 -0
- data/lib/git/commands/branch/create.rb +177 -0
- data/lib/git/commands/branch/delete.rb +88 -0
- data/lib/git/commands/branch/list.rb +178 -0
- data/lib/git/commands/branch/move.rb +102 -0
- data/lib/git/commands/branch/set_upstream.rb +86 -0
- data/lib/git/commands/branch/show_current.rb +49 -0
- data/lib/git/commands/branch/unset_upstream.rb +53 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +385 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +271 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +153 -0
- data/lib/git/commands/checkout/files.rb +116 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +106 -0
- data/lib/git/commands/clean.rb +102 -0
- data/lib/git/commands/clone.rb +241 -0
- data/lib/git/commands/commit.rb +273 -0
- data/lib/git/commands/commit_tree.rb +101 -0
- data/lib/git/commands/config_option_syntax/add.rb +86 -0
- data/lib/git/commands/config_option_syntax/get.rb +121 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
- data/lib/git/commands/config_option_syntax/list.rb +111 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
- data/lib/git/commands/config_option_syntax/set.rb +119 -0
- data/lib/git/commands/config_option_syntax/unset.rb +92 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +156 -0
- data/lib/git/commands/diff.rb +657 -0
- data/lib/git/commands/diff_files.rb +519 -0
- data/lib/git/commands/diff_index.rb +499 -0
- data/lib/git/commands/fetch.rb +354 -0
- data/lib/git/commands/fsck.rb +138 -0
- data/lib/git/commands/gc.rb +134 -0
- data/lib/git/commands/grep.rb +339 -0
- data/lib/git/commands/init.rb +101 -0
- data/lib/git/commands/log.rb +634 -0
- data/lib/git/commands/ls_files.rb +195 -0
- data/lib/git/commands/ls_remote.rb +161 -0
- data/lib/git/commands/ls_tree.rb +135 -0
- data/lib/git/commands/maintenance/register.rb +77 -0
- data/lib/git/commands/maintenance/run.rb +109 -0
- data/lib/git/commands/maintenance/start.rb +71 -0
- data/lib/git/commands/maintenance/stop.rb +60 -0
- data/lib/git/commands/maintenance/unregister.rb +84 -0
- data/lib/git/commands/maintenance.rb +31 -0
- data/lib/git/commands/merge/abort.rb +44 -0
- data/lib/git/commands/merge/continue.rb +44 -0
- data/lib/git/commands/merge/quit.rb +46 -0
- data/lib/git/commands/merge/start.rb +250 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +91 -0
- data/lib/git/commands/mv.rb +82 -0
- data/lib/git/commands/name_rev.rb +119 -0
- data/lib/git/commands/pull.rb +382 -0
- data/lib/git/commands/push.rb +251 -0
- data/lib/git/commands/read_tree.rb +154 -0
- data/lib/git/commands/remote/add.rb +96 -0
- data/lib/git/commands/remote/get_url.rb +68 -0
- data/lib/git/commands/remote/list.rb +56 -0
- data/lib/git/commands/remote/prune.rb +63 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +76 -0
- data/lib/git/commands/remote/set_branches.rb +70 -0
- data/lib/git/commands/remote/set_head.rb +89 -0
- data/lib/git/commands/remote/set_url.rb +78 -0
- data/lib/git/commands/remote/set_url_add.rb +70 -0
- data/lib/git/commands/remote/set_url_delete.rb +71 -0
- data/lib/git/commands/remote/show.rb +77 -0
- data/lib/git/commands/remote/update.rb +79 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +281 -0
- data/lib/git/commands/reset.rb +154 -0
- data/lib/git/commands/rev_parse.rb +304 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +62 -0
- data/lib/git/commands/revert/quit.rb +47 -0
- data/lib/git/commands/revert/skip.rb +44 -0
- data/lib/git/commands/revert/start.rb +158 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +113 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
- data/lib/git/commands/show_ref/exists.rb +80 -0
- data/lib/git/commands/show_ref/list.rb +149 -0
- data/lib/git/commands/show_ref/verify.rb +122 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +81 -0
- data/lib/git/commands/stash/branch.rb +67 -0
- data/lib/git/commands/stash/clear.rb +43 -0
- data/lib/git/commands/stash/create.rb +60 -0
- data/lib/git/commands/stash/drop.rb +73 -0
- data/lib/git/commands/stash/list.rb +43 -0
- data/lib/git/commands/stash/pop.rb +87 -0
- data/lib/git/commands/stash/push.rb +112 -0
- data/lib/git/commands/stash/show.rb +158 -0
- data/lib/git/commands/stash/store.rb +72 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +174 -0
- data/lib/git/commands/symbolic_ref/delete.rb +72 -0
- data/lib/git/commands/symbolic_ref/read.rb +99 -0
- data/lib/git/commands/symbolic_ref/update.rb +79 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +142 -0
- data/lib/git/commands/tag/delete.rb +57 -0
- data/lib/git/commands/tag/list.rb +146 -0
- data/lib/git/commands/tag/verify.rb +71 -0
- data/lib/git/commands/tag.rb +26 -0
- data/lib/git/commands/update_ref/batch.rb +145 -0
- data/lib/git/commands/update_ref/delete.rb +90 -0
- data/lib/git/commands/update_ref/update.rb +103 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +60 -0
- data/lib/git/commands/worktree/add.rb +139 -0
- data/lib/git/commands/worktree/list.rb +64 -0
- data/lib/git/commands/worktree/lock.rb +58 -0
- data/lib/git/commands/worktree/management_base.rb +51 -0
- data/lib/git/commands/worktree/move.rb +66 -0
- data/lib/git/commands/worktree/prune.rb +67 -0
- data/lib/git/commands/worktree/remove.rb +63 -0
- data/lib/git/commands/worktree/repair.rb +76 -0
- data/lib/git/commands/worktree/unlock.rb +47 -0
- data/lib/git/commands/worktree.rb +43 -0
- data/lib/git/commands/write_tree.rb +68 -0
- data/lib/git/commands.rb +88 -0
- data/lib/git/config.rb +72 -5
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +795 -0
- data/lib/git/detached_head_info.rb +57 -0
- data/lib/git/diff.rb +437 -86
- data/lib/git/diff_file_numstat_info.rb +31 -0
- data/lib/git/diff_file_patch_info.rb +136 -0
- data/lib/git/diff_file_raw_info.rb +129 -0
- data/lib/git/diff_info.rb +162 -0
- data/lib/git/diff_path_status.rb +107 -0
- data/lib/git/diff_result.rb +34 -0
- data/lib/git/diff_stats.rb +111 -0
- data/lib/git/dirstat_info.rb +102 -0
- data/lib/git/encoding_utils.rb +32 -1
- data/lib/git/errors.rb +285 -0
- data/lib/git/escaped_path.rb +57 -5
- data/lib/git/execution_context/global.rb +31 -0
- data/lib/git/execution_context/repository.rb +151 -0
- data/lib/git/execution_context.rb +559 -0
- data/lib/git/factories.rb +813 -0
- data/lib/git/file_ref.rb +77 -0
- data/lib/git/fsck_object.rb +56 -0
- data/lib/git/fsck_result.rb +132 -0
- data/lib/git/log.rb +306 -90
- data/lib/git/object.rb +563 -141
- data/lib/git/parsers/branch.rb +240 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/config_entry.rb +110 -0
- data/lib/git/parsers/diff.rb +792 -0
- data/lib/git/parsers/fsck.rb +144 -0
- data/lib/git/parsers/grep.rb +42 -0
- data/lib/git/parsers/ls_remote.rb +79 -0
- data/lib/git/parsers/ls_tree.rb +58 -0
- data/lib/git/parsers/remote.rb +162 -0
- data/lib/git/parsers/stash.rb +292 -0
- data/lib/git/parsers/status.rb +251 -0
- data/lib/git/parsers/tag.rb +341 -0
- data/lib/git/parsers/worktree.rb +185 -0
- data/lib/git/path_resolver.rb +206 -0
- data/lib/git/remote.rb +165 -12
- data/lib/git/remote_info.rb +203 -0
- data/lib/git/repository/branching.rb +964 -0
- data/lib/git/repository/committing.rb +246 -0
- data/lib/git/repository/context_helpers.rb +293 -0
- data/lib/git/repository/diffing.rb +785 -0
- data/lib/git/repository/inspecting.rb +252 -0
- data/lib/git/repository/logging.rb +410 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +451 -0
- data/lib/git/repository/object_operations.rb +1551 -0
- data/lib/git/repository/remote_operations.rb +984 -0
- data/lib/git/repository/shared_private.rb +120 -0
- data/lib/git/repository/staging.rb +587 -0
- data/lib/git/repository/stashing.rb +623 -0
- data/lib/git/repository/status_operations.rb +249 -0
- data/lib/git/repository/worktree_operations.rb +339 -0
- data/lib/git/repository.rb +484 -2
- data/lib/git/stash.rb +109 -12
- data/lib/git/stash_info.rb +102 -0
- data/lib/git/stashes.rb +169 -26
- data/lib/git/status.rb +308 -122
- data/lib/git/status_file_info.rb +258 -0
- data/lib/git/status_info.rb +189 -0
- data/lib/git/tag_delete_failure.rb +34 -0
- data/lib/git/tag_delete_result.rb +66 -0
- data/lib/git/tag_info.rb +99 -0
- data/lib/git/url.rb +15 -8
- data/lib/git/version.rb +113 -2
- data/lib/git/version_constraint.rb +85 -0
- data/lib/git/worktree.rb +150 -8
- data/lib/git/worktree_info.rb +128 -0
- data/lib/git/worktrees.rb +118 -13
- data/lib/git.rb +632 -234
- metadata +369 -54
- data/.github/stale.yml +0 -25
- data/.github/workflows/continuous_integration.yml +0 -49
- data/.gitignore +0 -10
- data/Dockerfile.changelog-rs +0 -12
- data/Gemfile +0 -5
- data/ISSUE_TEMPLATE.md +0 -15
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/RELEASING.md +0 -70
- data/Rakefile +0 -60
- data/lib/git/base/factory.rb +0 -99
- data/lib/git/base.rb +0 -711
- data/lib/git/command_line_result.rb +0 -86
- data/lib/git/failed_error.rb +0 -53
- data/lib/git/git_execute_error.rb +0 -7
- data/lib/git/index.rb +0 -5
- data/lib/git/lib.rb +0 -1328
- data/lib/git/path.rb +0 -31
- data/lib/git/signaled_error.rb +0 -50
- data/lib/git/working_directory.rb +0 -4
data/UPGRADING.md
ADDED
|
@@ -0,0 +1,1138 @@
|
|
|
1
|
+
# Upgrading the `git` Gem
|
|
2
|
+
|
|
3
|
+
This document covers breaking changes and migration steps when upgrading the
|
|
4
|
+
`git` gem to a new major version. Each section describes what changed and how
|
|
5
|
+
to update your code when upgrading from the preceding major version.
|
|
6
|
+
|
|
7
|
+
- [Upgrading to v6.0.0](#upgrading-to-v600)
|
|
8
|
+
- [Upgrading to v5.x](#upgrading-to-v5x)
|
|
9
|
+
- [Overview](#overview)
|
|
10
|
+
- [Breaking changes](#breaking-changes)
|
|
11
|
+
- [`Git::Base` removed](#gitbase-removed)
|
|
12
|
+
- [Return type of `Git.open`, `Git.clone`, `Git.init`, `Git.bare`](#return-type-of-gitopen-gitclone-gitinit-gitbare)
|
|
13
|
+
- [Unsupported options raise `ArgumentError`](#unsupported-options-raise-argumenterror)
|
|
14
|
+
- [`Git::Lib` removed](#gitlib-removed)
|
|
15
|
+
- [`Git::Log#object` is not a path limiter](#gitlogobject-is-not-a-path-limiter)
|
|
16
|
+
- [`Git::CommandLineResult` deprecated](#gitcommandlineresult-deprecated)
|
|
17
|
+
- [Deprecated methods](#deprecated-methods)
|
|
18
|
+
- [Facade method renames](#facade-method-renames)
|
|
19
|
+
- [`Git::Repository` method renames](#gitrepository-method-renames)
|
|
20
|
+
- [`Git::Repository` option renames](#gitrepository-option-renames)
|
|
21
|
+
- [v4.x-style configuration methods](#v4x-style-configuration-methods)
|
|
22
|
+
- [`Git` module mixin deprecations](#git-module-mixin-deprecations)
|
|
23
|
+
- [Module-level `Git` function deprecations](#module-level-git-function-deprecations)
|
|
24
|
+
- [`Git::Author` deprecated](#gitauthor-deprecated)
|
|
25
|
+
- [`Git::Branch#stashes` deprecated](#gitbranchstashes-deprecated)
|
|
26
|
+
- [Legacy stash API deprecated](#legacy-stash-api-deprecated)
|
|
27
|
+
- [`Git::Repository#remotes` deprecated](#gitrepositoryremotes-deprecated)
|
|
28
|
+
- [`Git::Remote` deprecated](#gitremote-deprecated)
|
|
29
|
+
- [`Git::Commands::CatFile::Raw` `allow_unknown_type` option deprecated](#gitcommandscatfileraw-allow_unknown_type-option-deprecated)
|
|
30
|
+
- [`Git::Branch` and `Git::Branches` deprecated](#gitbranch-and-gitbranches-deprecated)
|
|
31
|
+
- [`Git::Object::Tag` deprecated](#gitobjecttag-deprecated)
|
|
32
|
+
- [`Git::Status` deprecated](#gitstatus-deprecated)
|
|
33
|
+
- [`Git::Worktree` and `Git::Worktrees` deprecated](#gitworktree-and-gitworktrees-deprecated)
|
|
34
|
+
- [`Git.clone` option renames](#gitclone-option-renames)
|
|
35
|
+
- [`Git::Log` Enumerable interface deprecated](#gitlog-enumerable-interface-deprecated)
|
|
36
|
+
- [`Git::Object::Commit#set_commit` deprecated](#gitobjectcommitset_commit-deprecated)
|
|
37
|
+
- [`Git.export` `:remote` option deprecated](#gitexport-remote-option-deprecated)
|
|
38
|
+
|
|
39
|
+
## Upgrading to v6.0.0
|
|
40
|
+
|
|
41
|
+
v6.0.0 is not yet released. This section will be completed when it ships.
|
|
42
|
+
|
|
43
|
+
v6.0.0 removes the APIs deprecated during v5.x under the project's
|
|
44
|
+
[deprecation policy](README.md#deprecation-policy).
|
|
45
|
+
[Issue 1717](https://github.com/ruby-git/ruby-git/issues/1717) tracks its scope.
|
|
46
|
+
|
|
47
|
+
To prepare:
|
|
48
|
+
|
|
49
|
+
1. Upgrade to the latest v5.x release.
|
|
50
|
+
2. Set `GIT_DEPRECATION_BEHAVIOR=raise` (or `Git::Deprecation.behavior = :raise`) in
|
|
51
|
+
your test suite and, if possible, staging.
|
|
52
|
+
3. Fix each deprecation using the entries under
|
|
53
|
+
[Deprecated methods](#deprecated-methods) until the suite is clean.
|
|
54
|
+
4. Upgrade to v6.0.0.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Upgrading to v5.x
|
|
59
|
+
|
|
60
|
+
### Overview
|
|
61
|
+
|
|
62
|
+
v5.0.0 delivers a new internal architecture while keeping the v4.x API working
|
|
63
|
+
for the vast majority of users. Most v4.x code requires **no changes** to run on
|
|
64
|
+
v5.x.
|
|
65
|
+
|
|
66
|
+
The new architecture introduces a layered design (`Git::Commands`,
|
|
67
|
+
`Git::Repository`, and associated parsers). Compatibility shims — deprecated
|
|
68
|
+
forwarding methods that map old call patterns to the new API — ensure that v4.x
|
|
69
|
+
code continues to work. These shims emit deprecation warnings that tell you
|
|
70
|
+
exactly what to change and what will be eliminated in v6.0.0.
|
|
71
|
+
|
|
72
|
+
Hard breaks are limited to a small number of things that had no safe migration
|
|
73
|
+
path. These are described in the [Breaking changes](#breaking-changes) section,
|
|
74
|
+
followed by [Deprecated methods](#deprecated-methods) that still work in v5.x
|
|
75
|
+
but are removed in v6.0.0.
|
|
76
|
+
|
|
77
|
+
For information on how to suppress or configure deprecation warnings, see the
|
|
78
|
+
[Deprecations](README.md#deprecations) section of the README.
|
|
79
|
+
|
|
80
|
+
**Changes at a glance:**
|
|
81
|
+
|
|
82
|
+
| Change | Type | Impact | Action required |
|
|
83
|
+
|--------|------|--------|-----------------|
|
|
84
|
+
| `Git::Base` removed | Hard break | High for code that references it by name | Replace with `Git::Repository` (returned by `Git.open` etc.) |
|
|
85
|
+
| `Git::Lib` removed | Hard break | High for `.lib.*` callers | Use the equivalent method directly on the repo object (see table below) |
|
|
86
|
+
| `Git.open` etc. return `Git::Repository` (not `Git::Base`) | Hard break | Low for most callers; breaks `is_a?(Git::Base)` | Update type checks and update `be_a(Git::Base)` in tests |
|
|
87
|
+
| Unsupported options now raise `ArgumentError` | Behavior change | Medium for code passing unknown or misspelled options | Check option names against the documented API |
|
|
88
|
+
| `Git::Log#object` is not a path limiter | Behavior change | Medium for code that used `object(path)` to filter logs by path | Use `Git::Log#path` for path filtering |
|
|
89
|
+
| `Git::CommandLineResult` deprecated | Deprecation (removed in v6.0.0) | Low; only affects code that references the constant by name | Use `Git::CommandLine::Result` instead |
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Breaking changes
|
|
94
|
+
|
|
95
|
+
#### `Git::Base` removed
|
|
96
|
+
|
|
97
|
+
`Git::Base` — the class previously returned by `Git.open`, `Git.clone`,
|
|
98
|
+
`Git.init`, and `Git.bare` — is removed in v5.0.0. The replacement is
|
|
99
|
+
`Git::Repository`, which is returned by all four entry points and exposes the
|
|
100
|
+
same public API.
|
|
101
|
+
|
|
102
|
+
**Code that must be updated:**
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
# v4.x — explicit Git::Base reference (raises NameError in v5.x)
|
|
106
|
+
repo = Git::Base.new(working_directory: '/path/to/repo')
|
|
107
|
+
|
|
108
|
+
# v5.x — use the entry-point methods; do not construct Git::Repository directly
|
|
109
|
+
repo = Git.open('/path/to/repo')
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
# v4.x — type-checking against Git::Base (raises NameError in v5.x because Git::Base is removed)
|
|
114
|
+
raise unless repo.is_a?(Git::Base)
|
|
115
|
+
|
|
116
|
+
# v5.x — check against Git::Repository
|
|
117
|
+
raise unless repo.is_a?(Git::Repository)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
# v4.x — requiring the internal file (raises LoadError in v5.x)
|
|
122
|
+
require 'git/base'
|
|
123
|
+
|
|
124
|
+
# v5.x — the public entry point is git itself; no internal require needed
|
|
125
|
+
require 'git'
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Public API is preserved:** `Git::Repository` provides every method that
|
|
129
|
+
`Git::Base` did. Code that simply calls methods on the object returned by
|
|
130
|
+
`Git.open` (e.g., `repo.commit`, `repo.status`, `repo.add`) requires no
|
|
131
|
+
changes.
|
|
132
|
+
|
|
133
|
+
**Monkeypatching `Git::Base` is deprecated:** v5.x includes a temporary
|
|
134
|
+
compatibility shim for applications that define instance methods on `Git::Base`.
|
|
135
|
+
Those methods are made available on `Git::Repository` instances, but each method
|
|
136
|
+
definition emits a deprecation warning and this shim will be removed in v6.0.0.
|
|
137
|
+
|
|
138
|
+
Move custom repository helpers to an application-owned extension module and
|
|
139
|
+
include or prepend that module into `Git::Repository` during application setup:
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
# Deprecated in v5.x and will be removed in v6.0.0
|
|
143
|
+
module Git::Base
|
|
144
|
+
def worktree_clean?
|
|
145
|
+
status.changed.empty?
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# v5.x — keep the extension in application-owned code
|
|
150
|
+
module MyAppGitRepositoryExtensions
|
|
151
|
+
def worktree_clean?
|
|
152
|
+
status.changed.empty?
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
Git::Repository.include(MyAppGitRepositoryExtensions)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
#### Return type of `Git.open`, `Git.clone`, `Git.init`, `Git.bare`
|
|
162
|
+
|
|
163
|
+
`Git.open`, `Git.clone`, `Git.init`, and `Git.bare` now return
|
|
164
|
+
`Git::Repository` instead of `Git::Base`.
|
|
165
|
+
|
|
166
|
+
For most callers this is transparent — the returned object responds to the same
|
|
167
|
+
methods. Code that explicitly checks `is_a?(Git::Base)` or `be_a(Git::Base)` in
|
|
168
|
+
tests must be updated:
|
|
169
|
+
|
|
170
|
+
```ruby
|
|
171
|
+
# v4.x
|
|
172
|
+
expect(Git.open(repo_path)).to be_a(Git::Base)
|
|
173
|
+
|
|
174
|
+
# v5.x
|
|
175
|
+
expect(Git.open(repo_path)).to be_a(Git::Repository)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`Git::Repository` does not define `.open`, `.bare`, `.clone`, or `.init` class
|
|
179
|
+
methods. Always use `Git.open`, `Git.bare`, `Git.clone`, and `Git.init` to
|
|
180
|
+
construct a repository object.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
#### Unsupported options raise `ArgumentError`
|
|
185
|
+
|
|
186
|
+
v5.x validates options more strictly for factory methods and command APIs.
|
|
187
|
+
Unknown options that were silently ignored in v4.x may now raise
|
|
188
|
+
`ArgumentError`. Check option names against the documented API when upgrading,
|
|
189
|
+
especially for calls that pass keyword options through helper methods or shared
|
|
190
|
+
option hashes.
|
|
191
|
+
|
|
192
|
+
For example, `Git.clone` supports `log:`, not `logger:`. A misspelled or
|
|
193
|
+
unsupported option that v4.x ignored must be corrected:
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
# v4.x — silently ignored; did not configure clone logging
|
|
197
|
+
Git.clone(url, path, logger: logger)
|
|
198
|
+
|
|
199
|
+
# v5.x — use the documented option name
|
|
200
|
+
Git.clone(url, path, log: logger)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
#### `Git::Lib` removed
|
|
206
|
+
|
|
207
|
+
The object returned by `Git.open`, `Git.clone`, `Git.init`, and `Git.bare` previously
|
|
208
|
+
exposed a `#lib` method that gave access to `Git::Lib`, the gem's internal
|
|
209
|
+
implementation class. `Git::Lib` is removed in v5.0.0.
|
|
210
|
+
|
|
211
|
+
In v5.x, calling `#lib` on a repo object returns `self` with a deprecation
|
|
212
|
+
warning. This means `g.lib.some_method(args)` is forwarded to
|
|
213
|
+
`g.some_method(args)` — but only if `some_method` exists on `Git::Repository`.
|
|
214
|
+
Methods that were unique to `Git::Lib` and have no counterpart on
|
|
215
|
+
`Git::Repository` raise `NoMethodError` immediately. The `#lib` method itself
|
|
216
|
+
is removed in v6.0.0.
|
|
217
|
+
|
|
218
|
+
Most public behavior previously accessible via `g.lib.*` is available directly
|
|
219
|
+
on the repository object (`g.*`). See the tables below for every affected
|
|
220
|
+
method.
|
|
221
|
+
|
|
222
|
+
##### Methods that work via the `#lib` shim (with deprecation warning)
|
|
223
|
+
|
|
224
|
+
The following v4.x `g.lib.*` call shapes are forwarded to their `Git::Repository`
|
|
225
|
+
counterpart by the `#lib → self` shim. They emit a deprecation warning; migrate
|
|
226
|
+
to the replacement shown to silence it.
|
|
227
|
+
|
|
228
|
+
> **Note — config return type change:** `g.lib.config_get(name)` returned a
|
|
229
|
+
> `String`; `g.lib.config_list` returned a `Hash`.
|
|
230
|
+
> The v5.x replacements `config_get` and `config_list` return
|
|
231
|
+
> `Git::ConfigEntryInfo` and `Array<Git::ConfigEntryInfo>` respectively — richer
|
|
232
|
+
> objects that expose `.value` (the String), `.key`, `.scope`, and `.origin`.
|
|
233
|
+
>
|
|
234
|
+
> If you only need the String value:
|
|
235
|
+
> - `g.config_get(name)&.value` → replaces `g.lib.config_get(name)`
|
|
236
|
+
> - `g.config_list.to_h { |e| [e.key, e.value] }` → replaces `g.lib.config_list`
|
|
237
|
+
>
|
|
238
|
+
> If your code was using the v4.x public `g.config(name)` API (not `g.lib.*`),
|
|
239
|
+
> that deprecated bridge still returns a `String` in v5.x and continues to work
|
|
240
|
+
> until v6.0.0.
|
|
241
|
+
|
|
242
|
+
| v4.x call | Replacement in v5.x |
|
|
243
|
+
|-----------|---------------------|
|
|
244
|
+
| `g.lib.config_get(name)` | `g.config_get(name)` — returns `Git::ConfigEntryInfo`; use `.value` for the String |
|
|
245
|
+
| `g.lib.config_list` | `g.config_list` — returns `Array<Git::ConfigEntryInfo>` |
|
|
246
|
+
| `g.lib.config_set(name, value)` | `g.config_set(name, value)` |
|
|
247
|
+
| `g.lib.git_version` | `g.git_version` |
|
|
248
|
+
| `g.lib.stash_list` | `g.stash_infos` — returns `Array<Git::StashInfo>`, newest first |
|
|
249
|
+
| `g.lib.unmerged` | `g.unmerged` |
|
|
250
|
+
| `g.lib.change_head_branch(name)` | `g.change_head_branch(name)` |
|
|
251
|
+
| `g.lib.ls_remote(location, opts)` | `g.ls_remote(location, opts)` |
|
|
252
|
+
| `g.lib.current_branch_state` | `g.current_branch_state` |
|
|
253
|
+
|
|
254
|
+
> **Note — `current_branch_state` return type change:** `g.lib.current_branch_state`
|
|
255
|
+
> returned a `Git::Lib::HeadState` (a mutable `Struct`). `g.current_branch_state`
|
|
256
|
+
> returns a `Git::Repository::Branching::HeadState` (an immutable `Data` object).
|
|
257
|
+
> Both expose `.state` (`:active`, `:unborn`, or `:detached`) and `.name`. If your
|
|
258
|
+
> code relies on the struct being mutable or uses positional construction
|
|
259
|
+
> (`Git::Lib::HeadState.new(:active, 'main')`), update to keyword construction:
|
|
260
|
+
> `Git::Repository::Branching::HeadState.new(state: :active, name: 'main')`.
|
|
261
|
+
|
|
262
|
+
##### Methods that raise `NoMethodError` in v5.x
|
|
263
|
+
|
|
264
|
+
These `Git::Lib` method names have no counterpart on `Git::Repository`, so
|
|
265
|
+
`g.lib.method_name` raises `NoMethodError` even in v5.x (the `#lib → self`
|
|
266
|
+
shim cannot forward them). Update call sites directly:
|
|
267
|
+
|
|
268
|
+
| v4.x call | Replacement in v5.x |
|
|
269
|
+
|-----------|---------------------|
|
|
270
|
+
| `g.lib.global_config_get(name)` | `g.config_get(name, global: true)` |
|
|
271
|
+
| `g.lib.global_config_list` | `g.config_list(global: true)` |
|
|
272
|
+
| `g.lib.global_config_set(name, value)` | `g.config_set(name, value, global: true)` |
|
|
273
|
+
| `g.lib.branch_current` | `g.current_branch` |
|
|
274
|
+
| `g.lib.parse_config(file)` | `g.config_list(file: file)` |
|
|
275
|
+
|
|
276
|
+
##### Methods with no replacement
|
|
277
|
+
|
|
278
|
+
| v4.x call | Notes |
|
|
279
|
+
|-----------|-------|
|
|
280
|
+
| `g.lib.list_files(ref_dir)` | Walked `.git/refs/` directly. Use `g.branch_list`, `g.tag_list`, or `g.remote_list` instead. |
|
|
281
|
+
|
|
282
|
+
##### Internal plumbing methods (no replacement)
|
|
283
|
+
|
|
284
|
+
The following methods were technically public on `Git::Lib` but are internal
|
|
285
|
+
helpers with no plausible external use. They have no replacement in v5.0.0:
|
|
286
|
+
|
|
287
|
+
- `assert_args_are_not_options`
|
|
288
|
+
- `assert_valid_opts`
|
|
289
|
+
- `cat_file_object_meta`
|
|
290
|
+
- `command_capturing`
|
|
291
|
+
- `command_streaming`
|
|
292
|
+
- `each_cat_file_header`
|
|
293
|
+
- `handle_deprecated_path_option`
|
|
294
|
+
- `normalize_pathspecs`
|
|
295
|
+
- `parse_cat_file_meta`
|
|
296
|
+
- `parse_config_list`
|
|
297
|
+
- `process_commit_data`
|
|
298
|
+
- `validate_pathspec_types`
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
#### `Git::Log#object` is not a path limiter
|
|
303
|
+
|
|
304
|
+
In previous 4.x releases, some uses of `Git::Log#object(path)` could appear to
|
|
305
|
+
filter log output by path when combined with `#between` or other revision range
|
|
306
|
+
options. This relied on ambiguous `git log` argument handling and was not the
|
|
307
|
+
intended API for path filtering.
|
|
308
|
+
|
|
309
|
+
In v5.x, `Git::Log#object` should be treated as a revision expression. When both
|
|
310
|
+
`#object` and `#between` are specified, `#between` takes precedence. Code that
|
|
311
|
+
used `#object` to limit commits to a path should use `#path` instead.
|
|
312
|
+
|
|
313
|
+
```ruby
|
|
314
|
+
# v4.x — ambiguous; could appear to filter commits touching this path
|
|
315
|
+
git.log(500).object('cookbooks/mycookbook').between('1.0.0', 'HEAD').execute
|
|
316
|
+
|
|
317
|
+
# v5.x — use #path for path filtering
|
|
318
|
+
git.log(500).path('cookbooks/mycookbook').between('1.0.0', 'HEAD').execute
|
|
319
|
+
|
|
320
|
+
# #object remains appropriate for revision expressions
|
|
321
|
+
git.log.object('HEAD~10..HEAD').execute
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
#### `Git::CommandLineResult` deprecated
|
|
327
|
+
|
|
328
|
+
`Git::CommandLineResult` was an alias for `Git::CommandLine::Result` introduced
|
|
329
|
+
for backward compatibility. It is deprecated in v5.0.0 and removed in v6.0.0.
|
|
330
|
+
Accessing `Git::CommandLineResult` emits a deprecation warning.
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
# v4.x
|
|
334
|
+
result.is_a?(Git::CommandLineResult)
|
|
335
|
+
|
|
336
|
+
# v5.x
|
|
337
|
+
result.is_a?(Git::CommandLine::Result)
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
This change is only relevant if your code references `Git::CommandLineResult`
|
|
341
|
+
by name (typically in type checks or documentation). Code that simply uses the
|
|
342
|
+
result object returned by git commands is unaffected.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
### Deprecated methods
|
|
347
|
+
|
|
348
|
+
The following methods are available in v5.x with deprecation warnings and are
|
|
349
|
+
removed in v6.0.0. Migrate to the replacement shown to silence the warnings.
|
|
350
|
+
|
|
351
|
+
#### Facade method renames
|
|
352
|
+
|
|
353
|
+
Five methods were renamed to follow the project's `noun_verb` naming convention.
|
|
354
|
+
The old names continue to work but emit deprecation warnings:
|
|
355
|
+
|
|
356
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
357
|
+
|-----------------------------------------------------|-------------|
|
|
358
|
+
| `g.add_remote(name, url, opts)` | `g.remote_add(name, url, opts)` |
|
|
359
|
+
| `g.remove_remote(name)` | `g.remote_remove(name)` |
|
|
360
|
+
| `g.set_remote_url(name, url)` | `g.remote_set_url(name, url)` |
|
|
361
|
+
| `g.add_tag(name, ...)` | `g.tag_add(name, ...)` |
|
|
362
|
+
| `g.delete_tag(name)` | `g.tag_delete(name)` |
|
|
363
|
+
|
|
364
|
+
#### `Git::Repository` method renames
|
|
365
|
+
|
|
366
|
+
Seven more `Git::Repository` methods were renamed in v5.x. The old names continue
|
|
367
|
+
to work but emit deprecation warnings. Each old name returns exactly what its
|
|
368
|
+
replacement returns, except `branches_all`.
|
|
369
|
+
|
|
370
|
+
> **Return shape change:** `g.branches_all` returns an `Array` of 4-element
|
|
371
|
+
> tuples `[refname, current, worktree, symref]`, where `refname` is the short
|
|
372
|
+
> form (`main` or `remotes/origin/main`), `current` and `worktree` are booleans,
|
|
373
|
+
> and `symref` is the symbolic-ref target or `nil`. `g.branch_list` returns
|
|
374
|
+
> `Array<Git::BranchInfo>` with `refname` (always the full ref: `refs/heads/main`
|
|
375
|
+
> or `refs/remotes/origin/main`), `short_name`, `remote_name`, `remote?`,
|
|
376
|
+
> `current?`, `other_worktree?`, `symref`, `target_oid`, and `upstream`. This
|
|
377
|
+
> expression reproduces the legacy tuples:
|
|
378
|
+
>
|
|
379
|
+
> ```ruby
|
|
380
|
+
> g.branch_list.map do |i|
|
|
381
|
+
> refname = i.remote? ? "remotes/#{i.remote_name}/#{i.short_name}" : i.short_name
|
|
382
|
+
> [refname, i.current?, i.other_worktree?, i.symref]
|
|
383
|
+
> end
|
|
384
|
+
> ```
|
|
385
|
+
|
|
386
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
387
|
+
|-----------------------------------------------------|-------------|
|
|
388
|
+
| `g.empty?` | `g.no_commits?` — `true` when the repository has no commits |
|
|
389
|
+
| `g.reset_hard` | `g.reset(nil, hard: true)` — `reset` takes the commitish positionally, so pass `nil` before the options; returns git's stdout, as `reset_hard` did |
|
|
390
|
+
| `g.reset_hard(commitish)` | `g.reset(commitish, hard: true)` — `reset_hard` ignored any `:hard` option passed to it and always reset with `--hard` |
|
|
391
|
+
| `g.conflicts { \|file, yours, theirs\| ... }` | `g.each_conflict { \|file, yours, theirs\| ... }` — same block arguments; returns the unmerged paths |
|
|
392
|
+
| `g.is_local_branch?(name)` | `g.local_branch?(name)` |
|
|
393
|
+
| `g.is_remote_branch?(name)` | `g.remote_branch?(name)` |
|
|
394
|
+
| `g.is_branch?(name)` | `g.branch?(name)` |
|
|
395
|
+
| `g.branches_all` | `g.branch_list` — returns `Array<Git::BranchInfo>`; see the return shape change above |
|
|
396
|
+
|
|
397
|
+
#### `Git::Repository` option renames
|
|
398
|
+
|
|
399
|
+
Five methods accept a v4.x option or positional argument under its old name.
|
|
400
|
+
The old form still works in v5.x but emits a deprecation warning and is
|
|
401
|
+
translated to the v5.x form shown below.
|
|
402
|
+
|
|
403
|
+
> **`clean`:** `force: 2` runs `git clean -ff`, which also removes untracked
|
|
404
|
+
> nested git repositories. A `false` or `nil` value for `:ff` or `:force_force`
|
|
405
|
+
> still warns and has no effect; a value other than `true`, `false`, or `nil`
|
|
406
|
+
> raises `ArgumentError`. When the deprecated key is `true` and a valid
|
|
407
|
+
> `:force` is also given, `:force` is raised to `2` (a `:force` already at `2`
|
|
408
|
+
> is unchanged). An invalid `:force` value such as `0` is passed through
|
|
409
|
+
> unchanged and still raises `ArgumentError`; the deprecated key does not mask
|
|
410
|
+
> it.
|
|
411
|
+
|
|
412
|
+
> **`diff_path_status`:** `:path_limiter` accepts the same values as `:path`
|
|
413
|
+
> (a `String`, a `Pathname`, or an `Array` of them). When both keys are given,
|
|
414
|
+
> `:path_limiter` wins and no warning is emitted.
|
|
415
|
+
|
|
416
|
+
> **`set_working` and `set_index`:** `must_exist:` defaults to `true`. When
|
|
417
|
+
> both the positional argument and `must_exist:` are given, they are OR'ed so
|
|
418
|
+
> the more restrictive value wins.
|
|
419
|
+
|
|
420
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
421
|
+
|-----------------------------------------------------|-------------|
|
|
422
|
+
| `g.clean(ff: true)` | `g.clean(force: 2)` |
|
|
423
|
+
| `g.clean(force_force: true)` | `g.clean(force: 2)` |
|
|
424
|
+
| `g.diff_path_status(ref1, ref2, path: p)` | `g.diff_path_status(ref1, ref2, path_limiter: p)` |
|
|
425
|
+
| `g.commit(message, add_all: true)` | `g.commit(message, all: true)` — runs `git commit -a` |
|
|
426
|
+
| `g.set_working(dir, check)` | `g.set_working(dir, must_exist: check)` |
|
|
427
|
+
| `g.set_index(file, check)` | `g.set_index(file, must_exist: check)` |
|
|
428
|
+
|
|
429
|
+
#### v4.x-style configuration methods
|
|
430
|
+
|
|
431
|
+
The v4.x `config` and `global_config` methods accepted varying argument shapes
|
|
432
|
+
to read, write, or list configuration. These are replaced by separate,
|
|
433
|
+
purpose-named methods. The same applies to the module-level
|
|
434
|
+
`Git.global_config`, which is replaced by `Git.config_get`, `Git.config_set`,
|
|
435
|
+
and `Git.config_list` called with `global: true`.
|
|
436
|
+
|
|
437
|
+
> **Return type change:** The v4.x `g.config(name)` and `Git.global_config(name)`
|
|
438
|
+
> returned a `String`; `g.config` and `Git.global_config` returned a `Hash`. The
|
|
439
|
+
> v5.x replacements `config_get` and `config_list` return `Git::ConfigEntryInfo`
|
|
440
|
+
> (or `nil` when the key is not set) and `Array<Git::ConfigEntryInfo>`
|
|
441
|
+
> respectively. Use `.value` to get the String value:
|
|
442
|
+
> - `g.config_get(name)&.value` → String or nil
|
|
443
|
+
> - `g.config_list.to_h { |e| [e.key, e.value] }` → Hash (key → value)
|
|
444
|
+
>
|
|
445
|
+
> The setters `g.config(name, value)` and `Git.global_config(name, value)`
|
|
446
|
+
> returned the raw command result; `config_set` returns `nil`.
|
|
447
|
+
|
|
448
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
449
|
+
|-----------------------------------------------------|-------------|
|
|
450
|
+
| `g.config(name)` | `g.config_get(name)` — returns `Git::ConfigEntryInfo`; use `.value` for the String |
|
|
451
|
+
| `g.config` | `g.config_list` — returns `Array<Git::ConfigEntryInfo>` |
|
|
452
|
+
| `g.config(name, value)` | `g.config_set(name, value)` |
|
|
453
|
+
| `g.global_config(name)` | `g.config_get(name, global: true)` |
|
|
454
|
+
| `g.global_config` | `g.config_list(global: true)` |
|
|
455
|
+
| `g.global_config(name, value)` | `g.config_set(name, value, global: true)` |
|
|
456
|
+
| `Git.global_config(name)` | `Git.config_get(name, global: true)` — returns `Git::ConfigEntryInfo` or `nil`; use `.value` for the String |
|
|
457
|
+
| `Git.global_config` | `Git.config_list(global: true)` — returns `Array<Git::ConfigEntryInfo>` |
|
|
458
|
+
| `Git.global_config(name, value)` | `Git.config_set(name, value, global: true)` |
|
|
459
|
+
|
|
460
|
+
#### `Git` module mixin deprecations
|
|
461
|
+
|
|
462
|
+
Extending or including the `Git` module to call `config` and `global_config`
|
|
463
|
+
as bare methods is deprecated:
|
|
464
|
+
|
|
465
|
+
| Deprecated usage | Replacement |
|
|
466
|
+
|-----------------|-------------|
|
|
467
|
+
| `include Git; config(name)` | `Git.config_get(name)` |
|
|
468
|
+
| `include Git; config(name, value)` | `Git.config_set(name, value)` |
|
|
469
|
+
| `include Git; config` | `Git.config_list` |
|
|
470
|
+
| `include Git; global_config(name)` | `Git.config_get(name, global: true)` |
|
|
471
|
+
| `include Git; global_config(name, value)` | `Git.config_set(name, value, global: true)` |
|
|
472
|
+
| `include Git; global_config` | `Git.config_list(global: true)` |
|
|
473
|
+
|
|
474
|
+
`Git.config_get`, `Git.config_set`, and `Git.config_list` run `git config` in
|
|
475
|
+
the current directory, which is what the mixin `config` method did. The
|
|
476
|
+
return types differ as described under
|
|
477
|
+
[v4.x-style configuration methods](#v4x-style-configuration-methods).
|
|
478
|
+
|
|
479
|
+
#### Module-level `Git` function deprecations
|
|
480
|
+
|
|
481
|
+
Two module-level functions on `Git` accept a legacy call shape or return a
|
|
482
|
+
legacy type that is deprecated:
|
|
483
|
+
|
|
484
|
+
- `Git.ls_remote` defaults its repository argument to `'.'`. Passing `nil`
|
|
485
|
+
explicitly still works but warns; omit the argument or pass `'.'`. The
|
|
486
|
+
options hash is positional, so when you pass options you must also pass the
|
|
487
|
+
repository: `Git.ls_remote('.', opts)`, not `Git.ls_remote(opts)`.
|
|
488
|
+
- `Git.binary_version` is replaced by `Git.git_version`, which keeps the
|
|
489
|
+
optional binary path argument.
|
|
490
|
+
|
|
491
|
+
> **Return type change:** `Git.binary_version` returned an `Array<Integer>` of
|
|
492
|
+
> `[major, minor, patch]`. `Git.git_version` returns a `Git::Version`, which
|
|
493
|
+
> supports comparison and exposes `major`, `minor`, and `patch`.
|
|
494
|
+
> `Git.git_version.to_a` reproduces the legacy array. The return value of
|
|
495
|
+
> `Git.ls_remote` is unchanged.
|
|
496
|
+
|
|
497
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
498
|
+
|-----------------------------------------------------|-------------|
|
|
499
|
+
| `Git.ls_remote(nil)` | `Git.ls_remote` or `Git.ls_remote('.')` |
|
|
500
|
+
| `Git.ls_remote(nil, opts)` | `Git.ls_remote('.', opts)` |
|
|
501
|
+
| `Git.binary_version` | `Git.git_version` — returns `Git::Version`; use `.to_a` for the `[major, minor, patch]` Array |
|
|
502
|
+
| `Git.binary_version(binary_path)` | `Git.git_version(binary_path)` |
|
|
503
|
+
|
|
504
|
+
#### `Git::Author` deprecated
|
|
505
|
+
|
|
506
|
+
Starting in v5.3.0, methods that return author, committer, or tagger data —
|
|
507
|
+
`Git::Object::Commit#author`, `Git::Object::Commit#committer`,
|
|
508
|
+
`Git::Object::Tag#tagger`, and `Git::TagInfo#tagger` — return an immutable
|
|
509
|
+
`Git::AuthorInfo` value object instead of the mutable `Git::Author`.
|
|
510
|
+
|
|
511
|
+
`Git::AuthorInfo` exposes the same `name`, `email`, and `date` readers, so code
|
|
512
|
+
that only reads these attributes needs no changes. Code that mutated a
|
|
513
|
+
`Git::Author` (via `name=`, `email=`, or `date=`) must be updated:
|
|
514
|
+
`Git::AuthorInfo` is frozen, and `#with` returns a modified copy rather than
|
|
515
|
+
updating in place (e.g. `info = info.with(name: 'New Name')`).
|
|
516
|
+
|
|
517
|
+
Constructing `Git::Author` directly emits a deprecation warning naming
|
|
518
|
+
`Git::AuthorInfo` as the replacement. The class is removed in v6.0.0.
|
|
519
|
+
|
|
520
|
+
| Deprecated usage | Replacement |
|
|
521
|
+
|-----------------|-------------|
|
|
522
|
+
| `Git::Author.new('Name <email> 1627849923 +0200')` | `Git::AuthorInfo.parse('Name <email> 1627849923 +0200')` |
|
|
523
|
+
| `author.name = 'New Name'` | `author = author.with(name: 'New Name')` (returns a new object) |
|
|
524
|
+
|
|
525
|
+
#### `Git::Branch#stashes` deprecated
|
|
526
|
+
|
|
527
|
+
`Git::Branch#stashes` ignores the branch it is called on and returns every stash
|
|
528
|
+
in the repository, so `g.branch('feature').stashes` and `g.branch('main').stashes`
|
|
529
|
+
return the same entries. Call `Git::Repository#stash_infos` instead; it is the
|
|
530
|
+
query `Git::Branch#stashes` was already running.
|
|
531
|
+
|
|
532
|
+
> **Return type change:** `Git::Branch#stashes` returns a `Git::Stashes`
|
|
533
|
+
> collection of `Git::Stash` objects. `g.stash_infos` returns an array of
|
|
534
|
+
> `Git::StashInfo` values. Both are newest first, so indexes carry over unchanged.
|
|
535
|
+
> `Git::Stash#message` strips the `WIP on <branch>:` or `On <branch>:` prefix;
|
|
536
|
+
> `Git::StashInfo#message` keeps the full message and exposes the branch name as
|
|
537
|
+
> `Git::StashInfo#branch`.
|
|
538
|
+
|
|
539
|
+
`Git::Stashes` also exposes `save`, `apply`, and `clear`. Those map to the
|
|
540
|
+
repository's `stash_push`, `stash_apply`, and `stash_clear`. `Git::Stashes#apply(i)`
|
|
541
|
+
already passed `i` to git as `stash@{i}` (`0` = newest), and `g.stash_apply(i)` does
|
|
542
|
+
the same, so that index needs no conversion. The `Git::Stashes` class is deprecated
|
|
543
|
+
as well; [Legacy stash API deprecated](#legacy-stash-api-deprecated) maps each of
|
|
544
|
+
its methods.
|
|
545
|
+
|
|
546
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
547
|
+
|-----------------------------------------------------|-------------|
|
|
548
|
+
| `g.branch(name).stashes` | `g.stash_infos` — returns `Array<Git::StashInfo>`, newest first |
|
|
549
|
+
| `g.branch(name).stashes.each { \|s\| puts s.message }` | `g.stash_infos.each { \|info\| puts info.message }` |
|
|
550
|
+
| `g.branch(name).stashes.all` (`[index, message]` pairs, oldest first) | `g.stash_infos.reverse` — see the ordering note in [Legacy stash API deprecated](#legacy-stash-api-deprecated) |
|
|
551
|
+
| `g.branch(name).stashes.size` | `g.stash_infos.size` |
|
|
552
|
+
| `g.branch(name).stashes[i].message` (`0` = newest, `i` coerced with `to_i`) | `g.stash_infos[i.to_i].message` |
|
|
553
|
+
| `g.branch(name).stashes.save(message)` | `g.stash_push(message: message)` |
|
|
554
|
+
| `g.branch(name).stashes.apply` | `g.stash_apply` |
|
|
555
|
+
| `g.branch(name).stashes.apply(i)` (`0` = newest) | `g.stash_apply(i)` |
|
|
556
|
+
| `g.branch(name).stashes.clear` | `g.stash_clear` — returns git's stdout (normally `""`, which is truthy) where `Git::Stashes#clear` returned `nil` |
|
|
557
|
+
|
|
558
|
+
#### Legacy stash API deprecated
|
|
559
|
+
|
|
560
|
+
Starting in v5.4.0, the stash methods on `Git::Repository` are built around the
|
|
561
|
+
immutable `Git::StashInfo` value object. `g.stash_infos` returns every entry as a
|
|
562
|
+
`Git::StashInfo`, and `stash_push`, `stash_pop`, `stash_drop`, `stash_show`,
|
|
563
|
+
`stash_branch`, `stash_create`, and `stash_store` each map onto the `git stash`
|
|
564
|
+
subcommand of the same name. Every method that takes a stash (`stash_apply`,
|
|
565
|
+
`stash_pop`, `stash_drop`, `stash_show`, `stash_branch`) accepts a `Git::StashInfo`,
|
|
566
|
+
a `stash@{N}` name, an Integer index (`0` = newest), or `nil` for the newest entry.
|
|
567
|
+
|
|
568
|
+
The legacy methods and classes are deprecated and removed in v6.0.0:
|
|
569
|
+
`Git::Repository#stashes_all`, `Git::Repository#stash_save`,
|
|
570
|
+
`Git::Repository#stash_list`, `Git::Stash`, and `Git::Stashes`. Constructing a
|
|
571
|
+
`Git::Stash` or `Git::Stashes` emits one warning per object.
|
|
572
|
+
|
|
573
|
+
> **Ordering flip:** `g.stashes_all` returns entries **oldest first** with a
|
|
574
|
+
> sequential index of its own (`0` is the oldest). `g.stash_infos` returns entries
|
|
575
|
+
> **newest first**, the order `git stash list` uses, and `Git::StashInfo#index` is
|
|
576
|
+
> git's own `stash@{N}` number (`0` is the newest). `g.stashes_all.first` is
|
|
577
|
+
> `g.stash_infos.last`. Code that reads an entry by position must reverse the
|
|
578
|
+
> array or the index.
|
|
579
|
+
|
|
580
|
+
> **Message difference:** `g.stashes_all` strips the `WIP on <branch>:` or
|
|
581
|
+
> `On <branch>:` prefix from each message. `Git::StashInfo#message` keeps the full
|
|
582
|
+
> message git stores, and `Git::StashInfo#branch` holds the branch name. A stash
|
|
583
|
+
> created from a detached HEAD has the branch `"(no branch)"`, the label git writes
|
|
584
|
+
> in its message. `branch` is `nil` only when the message has no branch prefix at
|
|
585
|
+
> all, as for a `stash_store` entry with a custom message.
|
|
586
|
+
|
|
587
|
+
`g.stash_save(message)` returned `true` when it created a stash and `false` when
|
|
588
|
+
there were no local changes to save. `g.stash_push(message: message)` returns the
|
|
589
|
+
new `Git::StashInfo`, or `nil` when there were no local changes, so a truthiness
|
|
590
|
+
check such as `if g.stash_push(message: 'WIP')` still works.
|
|
591
|
+
|
|
592
|
+
`g.stash_list` returned the `git stash list` text as a String. Build that text from
|
|
593
|
+
`g.stash_infos` if you need it. In v6.0.0, `stash_list` returns
|
|
594
|
+
`Array<Git::StashInfo>`, the same value as `stash_infos`, and `stash_infos` stays as
|
|
595
|
+
a permanent alias. Move String callers of `stash_list` to `stash_infos` before
|
|
596
|
+
upgrading so the return type change cannot go unnoticed.
|
|
597
|
+
|
|
598
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
599
|
+
|-----------------------------------------------------|-------------|
|
|
600
|
+
| `g.stashes_all` | `g.stash_infos` — returns `Array<Git::StashInfo>`, newest first |
|
|
601
|
+
| `g.stashes_all.each { \|index, message\| ... }` | `g.stash_infos.reverse_each.with_index { \|info, index\| ... info.message }` |
|
|
602
|
+
| `g.stashes_all[i]` (`0` = oldest) | `g.stash_infos.reverse[i]` |
|
|
603
|
+
| `g.stashes_all.last` | `g.stash_infos.first` |
|
|
604
|
+
| `g.stash_save(message)` | `g.stash_push(message: message)` — returns `Git::StashInfo` or `nil` |
|
|
605
|
+
| `g.stash_list` (String) | `g.stash_infos.map { \|s\| "#{s.name}: #{s.message}" }.join("\n")` |
|
|
606
|
+
| `Git::Stash.new(g, message)` | `info = g.stash_push(message: message)` |
|
|
607
|
+
| `Git::Stash.new(g, message, existing: true)` | `message` — `existing: true` only wrapped the String and never looked an entry up; code that needs a real entry picks one from `g.stash_infos` by index or name |
|
|
608
|
+
| `stash.save` | `info = g.stash_push(message: message)` |
|
|
609
|
+
| `stash.saved?` | `!info.nil?` — check the value `stash_push` returned rather than pushing again |
|
|
610
|
+
| `stash.message` / `stash.to_s` | `info.message` — keeps the branch prefix; see the note above |
|
|
611
|
+
| `Git::Stashes.new(g)` | `g.stash_infos` |
|
|
612
|
+
| `stashes.all` (`[index, message]` pairs, oldest first) | `g.stash_infos.reverse` — see the ordering note above |
|
|
613
|
+
| `stashes.each { \|s\| ... }` (newest first) | `g.stash_infos.each { \|info\| ... }` |
|
|
614
|
+
| `stashes[i]` (`0` = newest, `i` coerced with `to_i`) | `g.stash_infos[i.to_i]` |
|
|
615
|
+
| `stashes.size` | `g.stash_infos.size` |
|
|
616
|
+
| `stashes.save(message)` | `g.stash_push(message: message)` |
|
|
617
|
+
| `stashes.apply` / `stashes.apply(i)` | `g.stash_apply` / `g.stash_apply(i)` |
|
|
618
|
+
| `stashes.clear` | `g.stash_clear` — returns git's stdout (normally `""`, which is truthy) where `Git::Stashes#clear` returned `nil` |
|
|
619
|
+
|
|
620
|
+
#### `Git::Repository#remotes` deprecated
|
|
621
|
+
|
|
622
|
+
`Git::Repository#remotes` is deprecated in favor of `Git::Repository#remote_list`
|
|
623
|
+
and is removed in v6.0.0. Its return value is unchanged. Calling `remotes` emits
|
|
624
|
+
one deprecation warning for itself plus one `Git::Remote` constructor warning for
|
|
625
|
+
each remote it returns (see the `Git::Remote` deprecation below), so a repository
|
|
626
|
+
with N remotes produces N + 1 warnings per call.
|
|
627
|
+
|
|
628
|
+
> **Return type change:** `remotes` returns `Array<Git::Remote>` — mutable
|
|
629
|
+
> objects with `name`, `url`, and `fetch_opts` accessors and `fetch`, `merge`,
|
|
630
|
+
> `branch`, and `remove` operations. `remote_list` returns
|
|
631
|
+
> `Array<Git::RemoteInfo>` — immutable value objects read from the repository's
|
|
632
|
+
> git config, with fields such as `name`, `url`, `push_url`, `fetch`, and `push`.
|
|
633
|
+
> Because a remote may carry more than one URL or refspec, `url`, `push_url`,
|
|
634
|
+
> `fetch`, and `push` are always frozen `Array<String>`. When a remote has more
|
|
635
|
+
> than one URL, git fetches from the first; the legacy `Git::Remote#url` returned
|
|
636
|
+
> the last one configured, so use `r.url.last` to reproduce that exact value.
|
|
637
|
+
> Likewise, `Git::Remote#fetch_opts` returned only the last configured fetch
|
|
638
|
+
> refspec, while `fetch` holds all of them. Operations that lived on
|
|
639
|
+
> `Git::Remote` are called on the repository with the remote name instead.
|
|
640
|
+
>
|
|
641
|
+
> **Order change:** `remotes` lists remotes in the order `git remote` prints
|
|
642
|
+
> them, while `remote_list` keeps the order in which remotes first appear in the
|
|
643
|
+
> config. When the legacy order matters, iterate `g.remote_names` (the same
|
|
644
|
+
> `git remote` order) or sort `g.remote_list` explicitly.
|
|
645
|
+
|
|
646
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
647
|
+
|-----------------------------------------------------|-------------|
|
|
648
|
+
| `g.remotes` | `g.remote_list` — returns `Array<Git::RemoteInfo>` |
|
|
649
|
+
| `g.remotes.map(&:name)` | `g.remote_list.map(&:name)` or `g.remote_names` |
|
|
650
|
+
| `g.remotes.map(&:to_s)` | `g.remote_list.map(&:name)` — `Git::RemoteInfo#to_s` is not the name |
|
|
651
|
+
| `g.remotes.map(&:url)` | `g.remote_list.map { \|r\| r.url.first }` — `url` is an `Array<String>` |
|
|
652
|
+
| `g.remotes.map(&:fetch_opts)` | `g.remote_list.map { \|r\| r.fetch.last }` — `fetch` holds every refspec |
|
|
653
|
+
| `g.remotes.each(&:fetch)` | `g.remote_names.each { \|name\| g.fetch(name) }` — same order as `remotes` |
|
|
654
|
+
| `remote.fetch` | `g.fetch(remote.name)` |
|
|
655
|
+
| `remote.fetch(opts)` | `g.fetch(remote.name, opts)` — same options hash |
|
|
656
|
+
| `remote.merge` | `g.merge("#{remote.name}/#{g.current_branch}")` |
|
|
657
|
+
| `remote.merge(branch)` | `g.merge("#{remote.name}/#{branch}")` |
|
|
658
|
+
| `remote.branch` | `g.branch_list("#{remote.name}/#{g.current_branch}").first` — returns a `Git::BranchInfo` |
|
|
659
|
+
| `remote.branch(name)` | `g.branch_list("#{remote.name}/#{name}").first` — returns a `Git::BranchInfo` |
|
|
660
|
+
| `remote.remove` | `g.remote_remove(remote.name)` |
|
|
661
|
+
|
|
662
|
+
#### `Git::Remote` deprecated
|
|
663
|
+
|
|
664
|
+
`Git::Remote`, `Git::Repository#remote`, and `Git::Repository#config_remote` are
|
|
665
|
+
deprecated and are removed in v6.0.0. Read a remote's configuration through
|
|
666
|
+
`Git::Repository#remote_list`, which returns one `Git::RemoteInfo` value object per
|
|
667
|
+
remote, and call the repository-level operations (`fetch`, `merge`, `branch_list`,
|
|
668
|
+
`remote_remove`) with the remote name. Return values are unchanged. Constructing a
|
|
669
|
+
`Git::Remote` directly emits one deprecation warning, and so does calling
|
|
670
|
+
`g.config_remote`. Calling `g.remote` emits two: one for `Git::Repository#remote`
|
|
671
|
+
and one for the `Git::Remote` it constructs. Likewise `g.remotes` emits one warning
|
|
672
|
+
for itself plus one per `Git::Remote` it returns (N + 1 for N remotes). The extra
|
|
673
|
+
warnings from `g.remote` and `g.remotes` are expected, not a bug.
|
|
674
|
+
|
|
675
|
+
> **Return type changes:** `Git::RemoteInfo#url` and `Git::RemoteInfo#fetch` are
|
|
676
|
+
> frozen `Array<String>` because a remote may carry more than one URL or fetch
|
|
677
|
+
> refspec. The legacy `Git::Remote#url` and `Git::Remote#fetch_opts` returned only
|
|
678
|
+
> the last configured value, so `r.url.last` and `r.fetch.last` reproduce them
|
|
679
|
+
> exactly; `r.url.first` is the URL git actually fetches from.
|
|
680
|
+
> `config_remote` returned a flat `Hash{String => String}` in which a repeated
|
|
681
|
+
> `url` or `fetch` key overwrote the earlier value, so it could not report every
|
|
682
|
+
> configured URL or refspec; `remote_list` keeps all of them. In the other
|
|
683
|
+
> direction, `Git::RemoteInfo` models only the remote variables git defines and
|
|
684
|
+
> drops any other `remote.<name>.*` key, while `config_remote` returned every key.
|
|
685
|
+
> Code that reads custom keys should filter `g.config_list` instead (see the
|
|
686
|
+
> table); that yields the same `Hash{String => String}` as `config_remote`.
|
|
687
|
+
> `Git::Remote#branch` returned a `Git::Branch`. Its replacement,
|
|
688
|
+
> `g.branch_list("#{name}/#{branch}").first`, returns a `Git::BranchInfo` value
|
|
689
|
+
> object, or `nil` when the remote-tracking branch does not exist.
|
|
690
|
+
|
|
691
|
+
In the table, `name` is the remote name (`g.remote` defaults it to `'origin'`).
|
|
692
|
+
|
|
693
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
694
|
+
|-----------------------------------------------------|-------------|
|
|
695
|
+
| `g.remote` | `g.remote_list.find { \|r\| r.name == 'origin' }` — returns a `Git::RemoteInfo`; the deprecated call emits two warnings |
|
|
696
|
+
| `g.remote(name)` | `g.remote_list.find { \|r\| r.name == name }` — returns a `Git::RemoteInfo`; the deprecated call emits two warnings |
|
|
697
|
+
| `g.config_remote(name)` for `url`, `fetch`, and the other modeled fields | `g.remote_list.find { \|r\| r.name == name }` — a `Git::RemoteInfo`, not a `Hash` |
|
|
698
|
+
| `g.config_remote(name)` for every key, including custom ones | `g.config_list.select { \|e\| e.key.start_with?("remote.#{name}.") }.to_h { \|e\| [e.key.delete_prefix("remote.#{name}."), e.value] }` — the same `Hash{String => String}` |
|
|
699
|
+
| `remote.name`, `remote.to_s` | `g.remote_list.find { \|r\| r.name == name }.name` or `g.remote_names` |
|
|
700
|
+
| `remote.url` | `g.remote_list.find { \|r\| r.name == name }.url` — `Array<String>`; `.first` for the single-URL case |
|
|
701
|
+
| `remote.fetch_opts` | `g.remote_list.find { \|r\| r.name == name }.fetch` — `Array<String>` of refspecs |
|
|
702
|
+
| `remote.fetch` | `g.fetch(name)` |
|
|
703
|
+
| `remote.fetch(opts)` | `g.fetch(name, opts)` — same option keys |
|
|
704
|
+
| `remote.merge` | `g.merge("#{name}/#{g.current_branch}")` |
|
|
705
|
+
| `remote.merge(branch)` | `g.merge("#{name}/#{branch}")` |
|
|
706
|
+
| `remote.branch` | `g.branch_list("#{name}/#{g.current_branch}").first` — returns a `Git::BranchInfo` |
|
|
707
|
+
| `remote.branch(branch)` | `g.branch_list("#{name}/#{branch}").first` — returns a `Git::BranchInfo` |
|
|
708
|
+
| `remote.remove` | `g.remote_remove(name)` |
|
|
709
|
+
|
|
710
|
+
#### `Git::Commands::CatFile::Raw` `allow_unknown_type` option deprecated
|
|
711
|
+
|
|
712
|
+
The `allow_unknown_type:` option of `Git::Commands::CatFile::Raw` is deprecated
|
|
713
|
+
and is removed in v6.0.0. Passing it emits a deprecation warning; the
|
|
714
|
+
`--allow-unknown-type` flag still reaches git unchanged until the option is
|
|
715
|
+
removed.
|
|
716
|
+
|
|
717
|
+
There is no replacement. Git 2.50 removed the unknown-type feature, so on git
|
|
718
|
+
2.50 and later `--allow-unknown-type` is an accepted no-op and the option has no
|
|
719
|
+
effect. On git 2.28 through 2.49 the flag still lets `t: true` and `s: true`
|
|
720
|
+
report the type and size of an object whose type git does not recognize, but
|
|
721
|
+
that behavior is dropped together with the option. The class is internal
|
|
722
|
+
(`@api private`) and no `Git::Repository` method passes the option, so only code
|
|
723
|
+
that constructs the command class directly is affected.
|
|
724
|
+
|
|
725
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
726
|
+
|-----------------------------------------------------|-------------|
|
|
727
|
+
| `Git::Commands::CatFile::Raw.new(ctx).call(sha, t: true, allow_unknown_type: true)` | `Git::Commands::CatFile::Raw.new(ctx).call(sha, t: true)` |
|
|
728
|
+
| `Git::Commands::CatFile::Raw.new(ctx).call(sha, s: true, allow_unknown_type: true)` | `Git::Commands::CatFile::Raw.new(ctx).call(sha, s: true)` |
|
|
729
|
+
|
|
730
|
+
#### `Git::Branch` and `Git::Branches` deprecated
|
|
731
|
+
|
|
732
|
+
`Git::Branch`, `Git::Branches`, `Git::Repository#branch`, and
|
|
733
|
+
`Git::Repository#branches` are deprecated and are removed in v6.0.0. Read branch
|
|
734
|
+
data through `Git::Repository#branch_list`, which returns one `Git::BranchInfo`
|
|
735
|
+
value object per local and remote-tracking branch, and call the repository-level
|
|
736
|
+
operations (`checkout`, `branch_new`, `branch_delete`, `merge`, `merge_into`,
|
|
737
|
+
`in_branch`, and so on) with the branch name. Calling `g.branch` or `g.branches`,
|
|
738
|
+
constructing a `Git::Branches`, and calling any operation on a `Git::Branch` each
|
|
739
|
+
emit a deprecation warning; their return values are unchanged. The `full`,
|
|
740
|
+
`name`, `remote`, `to_s`, and `to_a` readers on `Git::Branch` do not warn.
|
|
741
|
+
|
|
742
|
+
> **Return shape change:** `Git::Branch` exposes `full` (`main` or
|
|
743
|
+
> `remotes/origin/main`), `name`, and `remote` (a `Git::Remote`, or `nil`).
|
|
744
|
+
> `Git::BranchInfo` exposes `refname` (always the full ref: `refs/heads/main` or
|
|
745
|
+
> `refs/remotes/origin/main`), `short_name` (`main` for both), `remote_name` (a
|
|
746
|
+
> `String`, or `nil`), `remote?`, `current?`, `target_oid`, `upstream`,
|
|
747
|
+
> `worktree_path`, and `symref`. `Git::BranchInfo#to_s` is the full ref, not the
|
|
748
|
+
> `remotes/origin/main` form `Git::Branch#to_s` returned. `branch_list` takes
|
|
749
|
+
> `git branch --list` patterns: `'main'` matches the local branch and
|
|
750
|
+
> `'origin/main'` matches the remote-tracking branch. The `remotes/origin/main`
|
|
751
|
+
> and `refs/...` forms that `g.branches[...]` accepted match nothing.
|
|
752
|
+
>
|
|
753
|
+
> **`checkout` no longer creates the branch:** `g.branch('x').checkout` created
|
|
754
|
+
> `x` when it did not exist, ignoring any error from that attempt, and then
|
|
755
|
+
> checked it out. `g.checkout('x')` does not create a missing local branch,
|
|
756
|
+
> with one exception that is git's own: when exactly one remote has a branch
|
|
757
|
+
> named `x`, git creates a local tracking branch from it (its default guess
|
|
758
|
+
> behavior). Otherwise the checkout fails. To reproduce create-or-checkout,
|
|
759
|
+
> call `g.branch_new('x') unless g.local_branch?('x')` and then
|
|
760
|
+
> `g.checkout('x')`. Use `g.checkout('x', new_branch: true)` only when `x` is
|
|
761
|
+
> known not to exist; like `g.branch_new('x')`, it fails when `x` already
|
|
762
|
+
> exists. Likewise `g.branch('x').create` ignored every error, while
|
|
763
|
+
> `g.branch_new('x')` raises `Git::FailedError` when `x` already exists.
|
|
764
|
+
>
|
|
765
|
+
> **`in_branch` and `merge_into` differences:**
|
|
766
|
+
>
|
|
767
|
+
> 1. **Branch creation.** `g.branch('x').in_branch { ... }` created `x` if it did
|
|
768
|
+
> not exist. `g.in_branch('x') { ... }` raises `ArgumentError` unless `x` is an
|
|
769
|
+
> existing local branch, so call `g.branch_new('x')` first. A commit SHA, tag,
|
|
770
|
+
> or remote-tracking name is also rejected before any checkout.
|
|
771
|
+
> 2. **Detached HEAD.** `Git::Branch#in_branch` recorded the literal `HEAD` and
|
|
772
|
+
> could not restore a detached HEAD to its original commit. `g.in_branch` and
|
|
773
|
+
> `g.merge_into` record the SHA and restore it.
|
|
774
|
+
> 3. **Unborn HEAD.** Both new methods raise `Git::Error` before checking anything
|
|
775
|
+
> out when HEAD is on a branch with no commits. The old methods failed later,
|
|
776
|
+
> mid-flow.
|
|
777
|
+
> 4. **Merge overload.** `g.branch('main').merge('feature')` returned stdout from
|
|
778
|
+
> the final restore checkout and ran a hard reset after the merge.
|
|
779
|
+
> `g.merge_into('main', 'feature')` returns the merge's stdout and does no
|
|
780
|
+
> reset. It also rejects the `:no_commit` option; callers who need
|
|
781
|
+
> `--no-commit` use `checkout` and `merge` directly.
|
|
782
|
+
> 5. **Remote-tracking receivers.** Called on a remote-tracking `Git::Branch`,
|
|
783
|
+
> `in_branch` and `merge(branch)` checked out the remote-tracking ref,
|
|
784
|
+
> detaching HEAD, and any commit made there was left dangling. `g.in_branch`
|
|
785
|
+
> and `g.merge_into` take an existing local branch only. Create one from the
|
|
786
|
+
> remote-tracking ref first, with
|
|
787
|
+
> `g.branch_new(name, "remotes/#{remote}/#{name}")`, and pass that branch.
|
|
788
|
+
|
|
789
|
+
In the table, `name` is the branch name (`g.branch` defaults it to the current
|
|
790
|
+
branch), `remote` is the remote name of a remote-tracking branch, `b` is a
|
|
791
|
+
`Git::Branch`, and `info` is the `Git::BranchInfo` that replaces it. Where a
|
|
792
|
+
row says to pass `info.refname` for a remote-tracking branch, `b.full` (the
|
|
793
|
+
`remotes/<remote>/<name>` form) works too; the shorter `"#{remote}/#{name}"`
|
|
794
|
+
can resolve a local branch of that name and is only used where git expects it
|
|
795
|
+
(`branch_delete` with `remotes: true`).
|
|
796
|
+
|
|
797
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
798
|
+
|-----------------------------------------------------|-------------|
|
|
799
|
+
| `g.branch(name)` | `g.branch_list(name).first` for a local branch, or `g.branch_list("#{remote}/#{name}").find(&:remote?)` for a remote-tracking one — a `Git::BranchInfo`, or `nil` when the branch does not exist; the `remotes/` and `refs/` forms match nothing |
|
|
800
|
+
| `g.branch` | `g.branch_list(g.current_branch).first` — `nil` when HEAD is detached or unborn; use `g.current_branch_state` there |
|
|
801
|
+
| `g.branches` | `g.branch_list` — returns `Array<Git::BranchInfo>` |
|
|
802
|
+
| `g.branches[name]` | `g.branch_list(name).first`, or `g.branch_list("#{remote}/#{name}").find(&:remote?)` for a remote-tracking branch |
|
|
803
|
+
| `g.branches.local` | `g.branch_list.reject(&:remote?)` |
|
|
804
|
+
| `g.branches.remote` | `g.branch_list.select(&:remote?)` |
|
|
805
|
+
| `g.branches.size` | `g.branch_list.size` |
|
|
806
|
+
| `g.branches.each { \|b\| ... }` | `g.branch_list.each { \|info\| ... }` |
|
|
807
|
+
| `g.branches.to_s` | `g.branch_list.map { \|i\| "#{i.current? ? '* ' : ' '}#{i.refname}\n" }.join` — full refs, not `remotes/...` |
|
|
808
|
+
| `b.full`, `b.to_s` | `info.refname` — `refs/remotes/origin/main` rather than `remotes/origin/main` |
|
|
809
|
+
| `b.to_a` | `[info.refname]` |
|
|
810
|
+
| `b.name` | `info.short_name` |
|
|
811
|
+
| `b.remote` | `info.remote_name` — a `String`, or `nil` for a local branch |
|
|
812
|
+
| `b.gcommit` | `g.gcommit(name)` — pass `info.refname` for a remote-tracking branch |
|
|
813
|
+
| `b.checkout` | `g.checkout(name)` — does not create the branch (see above); pass `info.refname` for a remote-tracking branch |
|
|
814
|
+
| `b.create` | `g.branch_new(name)` — raises when the branch already exists |
|
|
815
|
+
| `b.delete` (local) | `g.branch_delete(name)` |
|
|
816
|
+
| `b.delete` (remote-tracking) | `g.branch_delete("#{remote}/#{name}", remotes: true)` |
|
|
817
|
+
| `b.current` | `g.current_branch == name` |
|
|
818
|
+
| `b.contains?(commit)` | `!g.branch_contains(commit, name).empty?` |
|
|
819
|
+
| `b.merge` | `g.merge(name)` |
|
|
820
|
+
| `b.merge(branch, message)` | `g.merge_into(name, branch, message)` — local `b` only; see the differences above |
|
|
821
|
+
| `b.update_ref(commit)` (local) | `g.update_ref(name, commit)` |
|
|
822
|
+
| `b.update_ref(commit)` (remote-tracking) | `g.update_ref("remotes/#{remote}/#{name}", commit)` |
|
|
823
|
+
| `b.archive(file, opts)` | `g.archive(name, file, opts)` — pass `info.refname` for a remote-tracking branch |
|
|
824
|
+
| `b.in_branch(message) { ... }` | `g.in_branch(name, message) { ... }` — local `b` only; see the differences above |
|
|
825
|
+
| `b.stashes` | `g.stash_infos` — see [`Git::Branch#stashes` deprecated](#gitbranchstashes-deprecated) |
|
|
826
|
+
|
|
827
|
+
#### `Git::Object::Tag` deprecated
|
|
828
|
+
|
|
829
|
+
`Git::Object::Tag`, `Git::Repository#tag`, `Git::Repository#tags`, and
|
|
830
|
+
`Git::Repository#tag_add` are deprecated and are removed in v6.0.0. Read tag data
|
|
831
|
+
through `Git::Repository#tag_list`, which returns one `Git::TagInfo` value object per
|
|
832
|
+
tag, create tags with `Git::Repository#tag_create`, which returns the new tag's
|
|
833
|
+
`Git::TagInfo`, and call the repository-level operations (`archive`, `log`, `diff`,
|
|
834
|
+
`cat_file_contents`, and so on) with the tag's object ID,
|
|
835
|
+
`info.oid || info.target_oid`, which is the object a `Git::Object::Tag` pinned when
|
|
836
|
+
it was constructed. Calling `g.tag`, `g.tags`, or
|
|
837
|
+
`g.tag_add`, and constructing a `Git::Object::Tag`, each emit one deprecation
|
|
838
|
+
warning; their return values are unchanged. `g.add_tag` already warned, pointing at
|
|
839
|
+
`g.tag_add`, and now emits two warnings for a creation call, one for itself and one
|
|
840
|
+
for the `g.tag_add` it calls; `g.add_tag(name, d: true)` emits three, adding the
|
|
841
|
+
`:d`/`:delete` warning described below. The readers on a `Git::Object::Tag` do not
|
|
842
|
+
warn.
|
|
843
|
+
|
|
844
|
+
> **Return shape change:** `Git::Object::Tag` exposes `name`, `sha`, `objectish`,
|
|
845
|
+
> `annotated?`, `message`, and `tagger`. `Git::TagInfo` exposes `name`, `oid`,
|
|
846
|
+
> `target_oid`, `objecttype`, `annotated?`, `lightweight?`, `message`, and
|
|
847
|
+
> `tagger`. `name` and `annotated?` are unchanged. `tagger` keeps the same `name`
|
|
848
|
+
> and `email`, but `tagger.date` differs: `t.tagger.date` is a `Time` in the
|
|
849
|
+
> process's local zone, while `info.tagger.date` keeps the UTC offset recorded in
|
|
850
|
+
> the tag object. Both name the same instant. `message` differs for an annotated
|
|
851
|
+
> tag created with an empty message (`message: ''`): `t.message` returns `""` and
|
|
852
|
+
> `info.message` returns `nil`, the same value a lightweight tag has. `t.sha` and
|
|
853
|
+
> `t.objectish` are the tag object's ID for an annotated tag and
|
|
854
|
+
> the tagged object's ID for a lightweight tag. `Git::TagInfo` separates the two:
|
|
855
|
+
> `oid` is the tag object's ID (`nil` for a lightweight tag) and `target_oid` is
|
|
856
|
+
> the ID of the object the tag points to (set for both kinds), so
|
|
857
|
+
> `info.oid || info.target_oid` reproduces `t.sha`. The target is usually a
|
|
858
|
+
> commit, but a tag can point at any git object, and `info.objecttype` reports
|
|
859
|
+
> which kind (`tag` for an annotated tag, or the target's own type such as
|
|
860
|
+
> `commit` or `blob` for a lightweight one).
|
|
861
|
+
>
|
|
862
|
+
> **Missing tags:** `g.tag(name)` raises `Git::UnexpectedResultError` when no tag
|
|
863
|
+
> has that name. `g.tag_list(name).first` returns `nil`.
|
|
864
|
+
>
|
|
865
|
+
> **Deleting through `tag_add`:** `g.tag_add(name, d: true)`, which was already
|
|
866
|
+
> deprecated, deletes the tag and emits a second warning pointing at
|
|
867
|
+
> `g.tag_delete`. `g.tag_create` rejects `:d` and `:delete` with `ArgumentError`.
|
|
868
|
+
>
|
|
869
|
+
> **Extra positional arguments:** `g.tag_add(name, target, extra)` ignores
|
|
870
|
+
> `extra` and tags `target`. `g.tag_create` raises `ArgumentError` when more than
|
|
871
|
+
> one positional argument follows the name.
|
|
872
|
+
>
|
|
873
|
+
> **Object identity:** every `Git::Object::Tag` resolves its tag to an object ID
|
|
874
|
+
> when it is constructed and runs `size`, `contents`, `grep`, `diff`, `log`, and
|
|
875
|
+
> `archive` against that ID, so moving or deleting the tag afterwards does not
|
|
876
|
+
> redirect an existing object. `Git::Object::Tag.new(g, sha, name)` uses the
|
|
877
|
+
> supplied `sha` as that ID; the other forms look it up from the ref. `annotated?`,
|
|
878
|
+
> `message`, and `tagger` always read the ref `name`. `Git::TagInfo` describes the
|
|
879
|
+
> ref only: `g.tag_list(name).first` returns whatever `name` points at now, or
|
|
880
|
+
> `nil` once the tag is deleted. Keep the same identity by passing `id` (see the
|
|
881
|
+
> table) rather than `name` to the operation replacements; they accept any object.
|
|
882
|
+
> To read an annotated tag object by ID without going through its ref, use
|
|
883
|
+
> `g.cat_file_tag(id)`, which returns the tag object's `object`, `type`, `tag`,
|
|
884
|
+
> `tagger`, and `message`.
|
|
885
|
+
|
|
886
|
+
In the table, `name` is the tag name, `t` is a `Git::Object::Tag`, `info` is the
|
|
887
|
+
`Git::TagInfo` that replaces it, and `id` is `info.oid || info.target_oid` (or the
|
|
888
|
+
`sha` given to the three-argument constructor), the object `t` pinned.
|
|
889
|
+
|
|
890
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
891
|
+
|-----------------------------------------------------|-------------|
|
|
892
|
+
| `g.tag(name)` | `g.tag_list(name).first` — a `Git::TagInfo`, or `nil` when the tag does not exist |
|
|
893
|
+
| `g.tags` | `g.tag_list` — returns `Array<Git::TagInfo>` |
|
|
894
|
+
| `g.tags.map(&:name)` | `g.tag_list.map(&:name)` |
|
|
895
|
+
| `g.tag_add(name, opts)` | `g.tag_create(name, opts)` — returns a `Git::TagInfo` |
|
|
896
|
+
| `g.tag_add(name, target, opts)` | `g.tag_create(name, target, opts)` |
|
|
897
|
+
| `g.tag_add(name, d: true)` | `g.tag_delete(name)` |
|
|
898
|
+
| `g.add_tag(name, opts)`, `g.add_tag(name, target, opts)` | `g.tag_create(name, ...)` — its warning names `g.tag_add`, which is deprecated too; go straight to `g.tag_create` |
|
|
899
|
+
| `g.add_tag(name, d: true)` | `g.tag_delete(name)` — `g.tag_create` rejects `:d`; see the deletion note above |
|
|
900
|
+
| `Git::Object::Tag.new(g, name)` | `g.tag_list(name).first` |
|
|
901
|
+
| `Git::Object::Tag.new(g, sha, name)` | `g.tag_list(name).first` — reads the ref rather than `sha`; use `sha` as `id` for the operations below, or read the object with `g.cat_file_tag(sha)`; see the object identity note above |
|
|
902
|
+
| `Git::Object.new(g, name, nil, true)` | `g.tag_list(name).first` — its warning names `Git::Object::Tag.new`, which is deprecated too |
|
|
903
|
+
| `t.name` | `info.name` |
|
|
904
|
+
| `t.sha`, `t.objectish`, `t.to_s` | `info.oid \|\| info.target_oid` — see the return shape change above |
|
|
905
|
+
| `t.annotated?` | `info.annotated?` |
|
|
906
|
+
| `t.message` | `info.message` — `nil` rather than `""` for an annotated tag with an empty message |
|
|
907
|
+
| `t.tagger` | `info.tagger` — `date` keeps the recorded UTC offset; see the return shape change above |
|
|
908
|
+
| `t.tag?` | not needed; every `Git::TagInfo` is a tag |
|
|
909
|
+
| `t.size` | `g.cat_file_size(id)` — `id` rather than `name` keeps this and the operations below on the object `t` pinned; see the object identity note above |
|
|
910
|
+
| `t.contents` | `g.cat_file_contents(id)` |
|
|
911
|
+
| `t.contents { \|file\| ... }` | `g.cat_file_contents(id) { \|file\| ... }` — streams to a temporary file instead of buffering the object |
|
|
912
|
+
| `t.contents_array` | `g.cat_file_contents(id).split("\n")` |
|
|
913
|
+
| `t.grep(string, path, opts)` | `g.grep(string, path, opts.merge(object: id))` |
|
|
914
|
+
| `t.diff(other)` | `g.diff(id, other)` |
|
|
915
|
+
| `t.log(count)` | `g.log(count).object(id)` |
|
|
916
|
+
| `t.archive(file, opts)` | `g.archive(id, file, opts)` |
|
|
917
|
+
|
|
918
|
+
#### `Git::Status` deprecated
|
|
919
|
+
|
|
920
|
+
Starting in v5.4.0, `Git::Status`, `Git::Status::StatusFile`, and
|
|
921
|
+
`Git::Repository#status` are deprecated and will be removed in v6.0.0. Read the
|
|
922
|
+
index and working tree state through `Git::Repository#status_info`, which
|
|
923
|
+
returns an immutable `Git::StatusInfo` holding one `Git::StatusFileInfo` per
|
|
924
|
+
path that `git status --porcelain=v2` reports. Calling `g.status` emits one
|
|
925
|
+
deprecation warning, and so does constructing a `Git::Status` directly.
|
|
926
|
+
|
|
927
|
+
`Git::StatusInfo` keeps the `changed`, `added`, `deleted`, and `untracked`
|
|
928
|
+
readers and the `changed?`, `added?`, `deleted?`, and `untracked?` predicates,
|
|
929
|
+
so code that only uses those can change `status` to `status_info` and needs
|
|
930
|
+
no other edit, subject to the category differences below. The readers now
|
|
931
|
+
return `Hash{String => Git::StatusFileInfo}`, and a new `unmerged` reader
|
|
932
|
+
lists conflicted paths, which `Git::Status` did not report. The predicates
|
|
933
|
+
still compare paths case-insensitively when `core.ignoreCase` is `true`.
|
|
934
|
+
`Git::StatusInfo` is not `Enumerable`; iterate `status_info.files`, an
|
|
935
|
+
`Array<Git::StatusFileInfo>` in git's output order.
|
|
936
|
+
|
|
937
|
+
The categories are derived differently. `Git::Status` gave each file one
|
|
938
|
+
`type`, and `changed` held only files whose type was `M`, so `changed`,
|
|
939
|
+
`added`, and `deleted` were disjoint: a file staged as new and then modified
|
|
940
|
+
in the working tree was only `added`. `Git::StatusInfo` derives the
|
|
941
|
+
categories from both status characters, so `changed` also includes type
|
|
942
|
+
changes (`T`), and one path can be in more than one category: that same file
|
|
943
|
+
(`AM`) is in both `added` and `changed`, and a file modified in the index and
|
|
944
|
+
then deleted from the working tree (`MD`) is in both `changed` and `deleted`.
|
|
945
|
+
Code that relied on the sets being disjoint should test `index_status` and
|
|
946
|
+
`worktree_status` directly.
|
|
947
|
+
|
|
948
|
+
`Git::StatusInfo` holds only the paths `git status` reports. `Git::Status`
|
|
949
|
+
also held an entry for every clean tracked file, seeded from `git ls-files`,
|
|
950
|
+
so `status[path]` returned a `Git::Status::StatusFile` with a `nil` type for an
|
|
951
|
+
unchanged path and `status.each` yielded one. `status_info[path]` returns `nil`
|
|
952
|
+
for a clean path and `status_info.files` omits it. Code that inspected clean
|
|
953
|
+
files should read `g.ls_files`, which still returns the index mode and SHA of
|
|
954
|
+
every tracked path.
|
|
955
|
+
|
|
956
|
+
`Git::StatusFileInfo` replaces the single `type` character with the two status
|
|
957
|
+
characters of the porcelain v2 format, `index_status` (HEAD versus index) and
|
|
958
|
+
`worktree_status` (index versus working tree), plus the `changed?`, `added?`,
|
|
959
|
+
`deleted?`, `renamed?`, `unmerged?`, `untracked?`, and `ignored?` predicates:
|
|
960
|
+
`added?` is true when `index_status` is `A`, `deleted?` when either status is
|
|
961
|
+
`D`, and `changed?` when either status is `M` or `T`. It holds no repository
|
|
962
|
+
reference, so `blob` is gone; fetch the object through the repository instead.
|
|
963
|
+
`stage` is gone too: an unmerged entry carries its stage 1, 2, and 3 modes and
|
|
964
|
+
SHAs in `unmerged_stages`, and every other entry is at stage 0.
|
|
965
|
+
|
|
966
|
+
> **Field renames:** the legacy mode and SHA readers were named for the wrong
|
|
967
|
+
> sides. `sha_index` and `mode_index` held the working-tree side of the diff:
|
|
968
|
+
> the index blob when the working tree matched the index, and an all-zero SHA
|
|
969
|
+
> when it did not. `sha_repo` and `mode_repo` held the side git compared the
|
|
970
|
+
> working tree against: the index in a repository with no commits, and HEAD
|
|
971
|
+
> once a commit exists (the factory applied `git diff-index HEAD` last). The
|
|
972
|
+
> new names follow git: `sha_head` and `mode_head` are the HEAD side,
|
|
973
|
+
> `sha_index` and `mode_index` are the index (staged) side, and
|
|
974
|
+
> `mode_worktree` is the working-tree mode. There is no working-tree SHA
|
|
975
|
+
> because `git status` does not compute one; `worktree_status` says whether
|
|
976
|
+
> the working tree differs from the index.
|
|
977
|
+
|
|
978
|
+
In the table, `g` is a `Git::Repository`, `status` is the `Git::Status` from
|
|
979
|
+
`g.status`, `file` is a `Git::Status::StatusFile`, and `info` is the
|
|
980
|
+
`Git::StatusFileInfo` that replaces it.
|
|
981
|
+
|
|
982
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
983
|
+
|-----------------------------------------------------|-------------|
|
|
984
|
+
| `g.status` | `g.status_info` — returns a `Git::StatusInfo` |
|
|
985
|
+
| `Git::Status.new(g)` | `g.status_info` |
|
|
986
|
+
| `status.changed`, `status.added`, `status.deleted`, `status.untracked` | same names on `g.status_info` — now `Hash{String => Git::StatusFileInfo}` keyed by path |
|
|
987
|
+
| `status.changed?(path)`, `status.added?(path)`, `status.deleted?(path)`, `status.untracked?(path)` | same names on `g.status_info` |
|
|
988
|
+
| `status[path]` | `g.status_info[path]` — a `Git::StatusFileInfo`, or `nil`; `nil` for a clean tracked path, which `status[path]` reported (see above) |
|
|
989
|
+
| `status.each { \|file\| ... }` | `g.status_info.files.each { \|info\| ... }` — does not yield clean tracked paths (see above) |
|
|
990
|
+
| `status.pretty` | no replacement; format `g.status_info.files` yourself |
|
|
991
|
+
| `file.path` | `info.path` |
|
|
992
|
+
| `file.type` | `info.index_status` and `info.worktree_status`, or the `info.changed?`, `info.added?`, and `info.deleted?` predicates |
|
|
993
|
+
| `file.untracked` | `info.untracked?` |
|
|
994
|
+
| `file.stage` | gone; `info.unmerged?` and `info.unmerged_stages` describe conflicted entries |
|
|
995
|
+
| `file.sha_repo` | `info.sha_head`, or `info.sha_index` in a repository with no commits |
|
|
996
|
+
| `file.mode_repo` | `info.mode_head`, or `info.mode_index` in a repository with no commits |
|
|
997
|
+
| `file.sha_index` | `info.sha_index` for the staged blob; `info.worktree_status` says whether the working tree differs from it |
|
|
998
|
+
| `file.mode_index` | `info.mode_worktree` |
|
|
999
|
+
| `file.blob` | `g.object(info.sha_index)` when `info.sha_index` is set and not all zeros — it is `nil` for untracked, ignored, and unmerged entries and all zeros when the path is not in the index; legacy `blob` returned `nil` without a lookup when no SHA was available and fell back to `sha_repo` when `sha_index` was `nil`. For an unmerged entry read a stage instead: `g.object(info.unmerged_stages[2][:sha])` |
|
|
1000
|
+
| `file.blob(:repo)` | `g.object(info.sha_head)` when `info.sha_head` is set and not all zeros — it is `nil` for untracked, ignored, and unmerged entries and all zeros when the path is not in HEAD |
|
|
1001
|
+
|
|
1002
|
+
#### `Git::Worktree` and `Git::Worktrees` deprecated
|
|
1003
|
+
|
|
1004
|
+
`Git::Worktree`, `Git::Worktrees`, `Git::Repository#worktree`,
|
|
1005
|
+
`Git::Repository#worktrees`, and `Git::Repository#worktrees_all` are deprecated
|
|
1006
|
+
and are removed in v6.0.0. Read worktree data through
|
|
1007
|
+
`Git::Repository#worktree_list`, which returns one `Git::WorktreeInfo` value
|
|
1008
|
+
object per worktree, and call the repository-level operations (`worktree_add`,
|
|
1009
|
+
`worktree_remove`, `worktree_move`, `worktree_lock`, `worktree_unlock`,
|
|
1010
|
+
`worktree_repair`, and `worktree_prune`) with the worktree path or its
|
|
1011
|
+
`Git::WorktreeInfo`. Return values are unchanged. Calling `g.worktree`,
|
|
1012
|
+
`g.worktrees`, or `g.worktrees_all`, constructing a `Git::Worktrees`, and calling
|
|
1013
|
+
`gcommit`, `add`, or `remove` on a `Git::Worktree` each emit a deprecation
|
|
1014
|
+
warning; the `dir`, `full`, `to_s`, and `to_a` readers on `Git::Worktree` do not.
|
|
1015
|
+
`g.worktrees` emits two warnings, one for itself and one for the `Git::Worktrees`
|
|
1016
|
+
it constructs, and `g.worktree(dir).add` emits one for `g.worktree` and one for
|
|
1017
|
+
`add`.
|
|
1018
|
+
|
|
1019
|
+
> **Return shape change:** `worktrees_all` returns `[directory, sha]` pairs and
|
|
1020
|
+
> omits the main worktree of a bare repository, which has no checked-out commit.
|
|
1021
|
+
> `worktree_list` returns `Git::WorktreeInfo` objects with `path`, `head`,
|
|
1022
|
+
> `branch` (the full refname, such as `refs/heads/main`, or `nil` when detached
|
|
1023
|
+
> or bare), `bare?`, `detached?`, `locked?` with `lock_reason`, and `prunable?`
|
|
1024
|
+
> with `prune_reason`. It includes the bare main worktree, with `head` and
|
|
1025
|
+
> `branch` set to `nil`. `Git::WorktreeInfo#to_s` is the path, so an entry can be
|
|
1026
|
+
> passed to any method that takes a worktree path.
|
|
1027
|
+
>
|
|
1028
|
+
> **`gcommit` return type:** `Git::Worktree#gcommit` returned a
|
|
1029
|
+
> `Git::Object::Commit` for a worktree obtained from `g.worktree(dir)` and a raw
|
|
1030
|
+
> SHA `String` for one obtained from `g.worktrees`. `info.head` is always a
|
|
1031
|
+
> `String` (or `nil` for a bare main worktree); call `g.gcommit(info.head)` for
|
|
1032
|
+
> the commit object.
|
|
1033
|
+
>
|
|
1034
|
+
> **`full` and `to_s`:** `Git::Worktree#full` and `#to_s` append the commitish
|
|
1035
|
+
> given at construction to the path, so entries from `g.worktrees` read
|
|
1036
|
+
> `"/path/to/wt <sha>"`. `Git::WorktreeInfo#to_s` is the path alone.
|
|
1037
|
+
|
|
1038
|
+
In the table, `dir` is the worktree path, `wt` is a `Git::Worktree`, and `info`
|
|
1039
|
+
is the `Git::WorktreeInfo` that replaces it.
|
|
1040
|
+
|
|
1041
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
1042
|
+
|-----------------------------------------------------|-------------|
|
|
1043
|
+
| `g.worktrees_all` | `g.worktree_list.map { \|w\| [w.path, w.head] }` — includes a bare main worktree as `[path, nil]`; add `.reject(&:bare?)` before `map` to omit it as `worktrees_all` did |
|
|
1044
|
+
| `g.worktrees` | `g.worktree_list` — returns `Array<Git::WorktreeInfo>`; the deprecated call emits two warnings |
|
|
1045
|
+
| `g.worktrees[dir]` | `g.worktree_list.find { \|w\| w.path == dir }` — `nil` when not found; `dir` is the path as git reports it (absolute, with symlinks resolved), as before |
|
|
1046
|
+
| `g.worktrees.size` | `g.worktree_list.size` |
|
|
1047
|
+
| `g.worktrees.each { \|wt\| ... }` | `g.worktree_list.each { \|info\| ... }` |
|
|
1048
|
+
| `g.worktrees.to_s` | `g.worktree_list.map { \|w\| "#{w.path} #{w.head}\n" }.join` |
|
|
1049
|
+
| `g.worktrees.prune` | `g.worktree_prune` |
|
|
1050
|
+
| `g.worktree(dir).add` | `g.worktree_add(dir)` |
|
|
1051
|
+
| `g.worktree(dir, commitish).add` | `g.worktree_add(dir, commitish)` |
|
|
1052
|
+
| `g.worktree(dir).remove` | `g.worktree_remove(dir)` — or `g.worktree_remove(info)` |
|
|
1053
|
+
| `wt.gcommit` | `info.head` — always a `String`, or `nil` for a bare main worktree; `g.gcommit(info.head)` for the commit object |
|
|
1054
|
+
| `wt.dir` | `info.path` |
|
|
1055
|
+
| `wt.full`, `wt.to_s` | `info.path` — or `"#{info.path} #{info.head}"` for the descriptor that entries from `g.worktrees` produced |
|
|
1056
|
+
| `wt.to_a` | `[info.path]` |
|
|
1057
|
+
|
|
1058
|
+
#### `Git.clone` option renames
|
|
1059
|
+
|
|
1060
|
+
Three `Git.clone` options were renamed in v5.x. The v4.x names still work. Each
|
|
1061
|
+
deprecated option present on a call emits its own deprecation warning, so a call
|
|
1062
|
+
that uses two of them warns twice. Each value is passed through to the
|
|
1063
|
+
replacement option, except that `:path` is dropped when `:chdir` is also given.
|
|
1064
|
+
|
|
1065
|
+
> **Precedence and value notes:**
|
|
1066
|
+
> - `:path` and `:chdir` both run `git clone` from inside the given directory.
|
|
1067
|
+
> When both are given, `:chdir` wins and `:path` is dropped.
|
|
1068
|
+
> - `:recursive` carries its value over to `:recurse_submodules` unchanged.
|
|
1069
|
+
> `:recurse_submodules` also accepts a pathspec `String` or `Array<String>`
|
|
1070
|
+
> to initialize only a subset of submodules, which `:recursive` never did.
|
|
1071
|
+
> - `:remote` and `:origin` have the same effect (`git clone --origin name`).
|
|
1072
|
+
|
|
1073
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
1074
|
+
|-----------------------------------------------------|-------------|
|
|
1075
|
+
| `Git.clone(url, dir, path: p)` | `Git.clone(url, dir, chdir: p)` |
|
|
1076
|
+
| `Git.clone(url, dir, recursive: true)` | `Git.clone(url, dir, recurse_submodules: true)` — or a pathspec `String` or `Array<String>` for a subset of submodules |
|
|
1077
|
+
| `Git.clone(url, dir, remote: name)` | `Git.clone(url, dir, origin: name)` |
|
|
1078
|
+
|
|
1079
|
+
#### `Git::Log` Enumerable interface deprecated
|
|
1080
|
+
|
|
1081
|
+
`Git::Log` is a query builder. Calling `each`, `size`, `to_s`, `first`, `last`, or
|
|
1082
|
+
`[]` directly on it runs the query and emits a deprecation warning; those methods
|
|
1083
|
+
are removed in v6.0.0. Call `Git::Log#execute` instead. It runs the query and
|
|
1084
|
+
returns a `Git::Log::Result`, which includes `Enumerable` and provides the same
|
|
1085
|
+
six methods. The chainable query methods on `Git::Log` (`since`, `author`,
|
|
1086
|
+
`between`, `path`, `max_count`, and so on) are unchanged.
|
|
1087
|
+
|
|
1088
|
+
`Git::Log` includes `Enumerable`, so every `Enumerable` method called on the
|
|
1089
|
+
builder (`map`, `select`, `count`, `to_a`, `include?`, and so on) goes through the
|
|
1090
|
+
deprecated `each` and emits its warning. Move those calls to the result as well,
|
|
1091
|
+
not only the six named methods.
|
|
1092
|
+
|
|
1093
|
+
> **Snapshot results:** `execute` returns a snapshot. The builder re-runs
|
|
1094
|
+
> `git log` only when a query method (`since`, `max_count`, and so on) has been
|
|
1095
|
+
> called since the last run, even with the same value as before, so calling
|
|
1096
|
+
> `execute` twice on an untouched builder returns equal results without a second
|
|
1097
|
+
> `git log`. Keep the result object when a chain of operations needs the same
|
|
1098
|
+
> commits rather than calling `g.log` again, which builds a new query.
|
|
1099
|
+
|
|
1100
|
+
In the table, `g` is a `Git::Repository`.
|
|
1101
|
+
|
|
1102
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
1103
|
+
|-----------------------------------------------------|-------------|
|
|
1104
|
+
| `g.log.each { \|c\| ... }` | `g.log.execute.each { \|c\| ... }` |
|
|
1105
|
+
| `g.log.size` | `g.log.execute.size` |
|
|
1106
|
+
| `g.log.to_s` | `g.log.execute.to_s` — commits joined with newlines, as before |
|
|
1107
|
+
| `g.log.first`, `g.log.last` | `g.log.execute.first`, `g.log.execute.last` |
|
|
1108
|
+
| `g.log[i]`, `g.log[range]` | `g.log.execute[i]`, `g.log.execute[range]` |
|
|
1109
|
+
| any other `Enumerable` method on the log (`map`, `select`, `count`, `to_a`, `include?`, ...) | the same method on `g.log.execute` |
|
|
1110
|
+
|
|
1111
|
+
#### `Git::Object::Commit#set_commit` deprecated
|
|
1112
|
+
|
|
1113
|
+
`Git::Object::Commit#set_commit` is deprecated and is removed in v6.0.0. Call
|
|
1114
|
+
`from_data` instead; it takes the same parsed commit data hash and has the same
|
|
1115
|
+
effect.
|
|
1116
|
+
|
|
1117
|
+
| Deprecated call (works in v5.x, removed in v6.0.0) | Replacement |
|
|
1118
|
+
|-----------------------------------------------------|-------------|
|
|
1119
|
+
| `commit.set_commit(data)` | `commit.from_data(data)` |
|
|
1120
|
+
|
|
1121
|
+
#### `Git.export` `:remote` option deprecated
|
|
1122
|
+
|
|
1123
|
+
`Git.export` has always dropped a `:remote` option before calling `Git.clone`
|
|
1124
|
+
without telling the caller. Passing it now emits a deprecation warning. The option
|
|
1125
|
+
is still dropped, so the export itself is unchanged, and it will be removed in a
|
|
1126
|
+
future major release. Once it is removed, passing `:remote` raises `ArgumentError`
|
|
1127
|
+
like any other unsupported option (see [Unsupported options raise
|
|
1128
|
+
`ArgumentError`](#unsupported-options-raise-argumenterror)).
|
|
1129
|
+
|
|
1130
|
+
There is no replacement option. `:remote` renamed the clone's remote, and
|
|
1131
|
+
`Git.export` deletes the `.git` directory before returning, so the name was never
|
|
1132
|
+
observable in the result. Delete the option from the call.
|
|
1133
|
+
|
|
1134
|
+
| Deprecated call (works in v5.x, removed in a future major release) | Replacement |
|
|
1135
|
+
|--------------------------------------------------------------------|-------------|
|
|
1136
|
+
| `Git.export(url, dir, remote: name)` | `Git.export(url, dir)` |
|
|
1137
|
+
|
|
1138
|
+
---
|