git 1.19.1 → 2.1.1
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/.github/pull_request_template.md +8 -0
- data/.github/workflows/continuous_integration.yml +14 -20
- data/.github/workflows/experimental_continuous_integration.yml +43 -0
- data/CHANGELOG.md +88 -0
- data/CONTRIBUTING.md +22 -67
- data/README.md +166 -52
- data/RELEASING.md +49 -34
- data/git.gemspec +8 -8
- data/lib/git/base.rb +173 -47
- data/lib/git/command_line.rb +377 -0
- data/lib/git/config.rb +5 -1
- data/lib/git/errors.rb +206 -0
- data/lib/git/escaped_path.rb +1 -1
- data/lib/git/lib.rb +244 -177
- data/lib/git/log.rb +65 -4
- data/lib/git/object.rb +69 -67
- data/lib/git/status.rb +132 -24
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +8 -7
- metadata +41 -30
- data/.github/stale.yml +0 -25
- data/Dockerfile.changelog-rs +0 -12
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/lib/git/base/factory.rb +0 -99
- data/lib/git/failed_error.rb +0 -53
- data/lib/git/git_execute_error.rb +0 -7
- data/lib/git/signaled_error.rb +0 -50
- /data/{ISSUE_TEMPLATE.md → .github/issue_template.md} +0 -0
data/RELEASING.md
CHANGED
@@ -7,64 +7,79 @@
|
|
7
7
|
|
8
8
|
Releasing a new version of the `git` gem requires these steps:
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
These instructions use an example where:
|
17
|
-
|
18
|
-
- The default branch is `master`
|
19
|
-
- The current release version is `1.5.0`
|
20
|
-
- You want to create a new *minor* release, `1.6.0`
|
10
|
+
* [Install Prerequisites](#install-prerequisites)
|
11
|
+
* [Determine the SemVer release type](#determine-the-semver-release-type)
|
12
|
+
* [Create the release](#create-the-release)
|
13
|
+
* [Review the CHANGELOG and release PR](#review-the-changelog-and-release-pr)
|
14
|
+
* [Manually merge the release PR](#manually-merge-the-release-pr)
|
15
|
+
* [Publish the git gem to RubyGems.org](#publish-the-git-gem-to-rubygemsorg)
|
21
16
|
|
22
17
|
## Install Prerequisites
|
23
18
|
|
24
19
|
The following tools need to be installed in order to create the release:
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
* [create_githhub_release](https://github.com/main-branch/create_github_release) is used to create the release
|
22
|
+
* [git](https://git-scm.com) is used by `create-github-release` to interact with the local and remote repositories
|
23
|
+
* [gh](https://cli.github.com) is used by `create-github-release` to create the release and PR in GitHub
|
29
24
|
|
30
|
-
On a Mac, these tools can be installed using [brew](https://brew.sh):
|
25
|
+
On a Mac, these tools can be installed using [gem](https://guides.rubygems.org/rubygems-basics/) and [brew](https://brew.sh):
|
31
26
|
|
32
27
|
```shell
|
28
|
+
$ gem install create_github_release
|
29
|
+
...
|
33
30
|
$ brew install git
|
34
31
|
...
|
35
32
|
$ brew install gh
|
36
33
|
...
|
37
|
-
$ brew install --cask docker
|
38
|
-
...
|
39
34
|
$
|
40
35
|
```
|
41
36
|
|
42
|
-
##
|
37
|
+
## Determine the SemVer release type
|
43
38
|
|
44
|
-
|
39
|
+
Determine the SemVer version increment that should be applied for the new release:
|
45
40
|
|
46
|
-
|
41
|
+
* `major`: when the release includes incompatible API or functional changes.
|
42
|
+
* `minor`: when the release adds functionality in a backward-compatible manner
|
43
|
+
* `patch`: when the release includes small user-facing changes that are
|
44
|
+
backward-compatible and do not introduce new functionality.
|
47
45
|
|
48
|
-
|
49
|
-
- Install development dependencies using bundle `bundle install`
|
50
|
-
- Based upon the nature of the changes, decide on the type of release: `major`, `minor`, or `patch` (in this example we will use `minor`)
|
51
|
-
- Run the release script `bundle exec create-github-release minor`
|
46
|
+
## Create the release
|
52
47
|
|
53
|
-
|
48
|
+
Create the release using the `create-github-release` command. If the release type
|
49
|
+
is `major`, the command is:
|
54
50
|
|
55
|
-
|
51
|
+
```shell
|
52
|
+
create-github-release major
|
53
|
+
```
|
56
54
|
|
57
|
-
|
55
|
+
Follow the directions given by the `create-github-release` command to finish the
|
56
|
+
release. Where the instructions given by the command differ than the instructions
|
57
|
+
below, follow the instructions given by the command.
|
58
58
|
|
59
|
-
|
59
|
+
## Review the CHANGELOG and release PR
|
60
60
|
|
61
|
-
-
|
62
|
-
|
61
|
+
The `create-github-release` command will output a link to the CHANGELOG and the PR
|
62
|
+
it created for the release. Review the CHANGELOG and have someone review and approve
|
63
|
+
the release PR.
|
63
64
|
|
64
|
-
##
|
65
|
+
## Manually merge the release PR
|
65
66
|
|
66
|
-
|
67
|
+
It is important to manually merge the PR so a separate merge commit can be avoided.
|
68
|
+
Use the commands output by the `create-github-release` which will looks like this
|
69
|
+
if you are creating a 2.0.0 release:
|
67
70
|
|
68
|
-
|
71
|
+
```shell
|
72
|
+
git checkout master
|
73
|
+
git merge --ff-only release-v2.0.0
|
74
|
+
git push
|
75
|
+
```
|
76
|
+
|
77
|
+
This will automatically close the release PR.
|
78
|
+
|
79
|
+
## Publish the git gem to RubyGems.org
|
69
80
|
|
70
|
-
|
81
|
+
Finally, publish the git gem to RubyGems.org using the following command:
|
82
|
+
|
83
|
+
```shell
|
84
|
+
rake release:rubygem_push
|
85
|
+
```
|
data/git.gemspec
CHANGED
@@ -24,22 +24,22 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}"
|
25
25
|
|
26
26
|
s.require_paths = ['lib']
|
27
|
-
s.required_ruby_version = '>=
|
28
|
-
s.
|
29
|
-
s.requirements = ['git 1.6.0.0, or greater']
|
27
|
+
s.required_ruby_version = '>= 3.0.0'
|
28
|
+
s.requirements = ['git 2.28.0 or greater']
|
30
29
|
|
30
|
+
s.add_runtime_dependency 'activesupport', '>= 5.0'
|
31
31
|
s.add_runtime_dependency 'addressable', '~> 2.8'
|
32
|
+
s.add_runtime_dependency 'process_executer', '~> 1.1'
|
32
33
|
s.add_runtime_dependency 'rchardet', '~> 1.8'
|
33
34
|
|
34
|
-
s.add_development_dependency '
|
35
|
-
s.add_development_dependency 'create_github_release', '~> 0.2'
|
35
|
+
s.add_development_dependency 'create_github_release', '~> 1.4'
|
36
36
|
s.add_development_dependency 'minitar', '~> 0.9'
|
37
37
|
s.add_development_dependency 'mocha', '~> 2.1'
|
38
|
-
s.add_development_dependency 'rake', '~> 13.
|
39
|
-
s.add_development_dependency 'test-unit', '~> 3.
|
38
|
+
s.add_development_dependency 'rake', '~> 13.1'
|
39
|
+
s.add_development_dependency 'test-unit', '~> 3.6'
|
40
40
|
|
41
41
|
unless RUBY_PLATFORM == 'java'
|
42
|
-
s.add_development_dependency 'redcarpet', '~> 3.
|
42
|
+
s.add_development_dependency 'redcarpet', '~> 3.6'
|
43
43
|
s.add_development_dependency 'yard', '~> 0.9', '>= 0.9.28'
|
44
44
|
s.add_development_dependency 'yardstick', '~> 0.9'
|
45
45
|
end
|
data/lib/git/base.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
|
-
require 'git/base/factory'
|
2
1
|
require 'logger'
|
3
2
|
require 'open3'
|
4
3
|
|
5
4
|
module Git
|
6
|
-
#
|
5
|
+
# The main public interface for interacting with Git commands
|
7
6
|
#
|
8
7
|
# Instead of creating a Git::Base directly, obtain a Git::Base instance by
|
9
8
|
# calling one of the follow {Git} class methods: {Git.open}, {Git.init},
|
10
9
|
# {Git.clone}, or {Git.bare}.
|
11
10
|
#
|
11
|
+
# @api public
|
12
|
+
#
|
12
13
|
class Base
|
13
|
-
include Git::Base::Factory
|
14
|
-
|
15
14
|
# (see Git.bare)
|
16
15
|
def self.bare(git_dir, options = {})
|
17
16
|
normalize_paths(options, default_repository: git_dir, bare: true)
|
@@ -122,6 +121,62 @@ module Git
|
|
122
121
|
@index = options[:index] ? Git::Index.new(options[:index], false) : nil
|
123
122
|
end
|
124
123
|
|
124
|
+
# Update the index from the current worktree to prepare the for the next commit
|
125
|
+
#
|
126
|
+
# @example
|
127
|
+
# lib.add('path/to/file')
|
128
|
+
# lib.add(['path/to/file1','path/to/file2'])
|
129
|
+
# lib.add(all: true)
|
130
|
+
#
|
131
|
+
# @param [String, Array<String>] paths a file or files to be added to the repository (relative to the worktree root)
|
132
|
+
# @param [Hash] options
|
133
|
+
#
|
134
|
+
# @option options [Boolean] :all Add, modify, and remove index entries to match the worktree
|
135
|
+
# @option options [Boolean] :force Allow adding otherwise ignored files
|
136
|
+
#
|
137
|
+
def add(paths = '.', **options)
|
138
|
+
self.lib.add(paths, options)
|
139
|
+
end
|
140
|
+
|
141
|
+
# adds a new remote to this repository
|
142
|
+
# url can be a git url or a Git::Base object if it's a local reference
|
143
|
+
#
|
144
|
+
# @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
|
145
|
+
# @git.fetch('scotts_git')
|
146
|
+
# @git.merge('scotts_git/master')
|
147
|
+
#
|
148
|
+
# Options:
|
149
|
+
# :fetch => true
|
150
|
+
# :track => <branch_name>
|
151
|
+
def add_remote(name, url, opts = {})
|
152
|
+
url = url.repo.path if url.is_a?(Git::Base)
|
153
|
+
self.lib.remote_add(name, url, opts)
|
154
|
+
Git::Remote.new(self, name)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Create a new git tag
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# repo.add_tag('tag_name', object_reference)
|
161
|
+
# repo.add_tag('tag_name', object_reference, {:options => 'here'})
|
162
|
+
# repo.add_tag('tag_name', {:options => 'here'})
|
163
|
+
#
|
164
|
+
# @param [String] name The name of the tag to add
|
165
|
+
# @param [Hash] options Opstions to pass to `git tag`.
|
166
|
+
# See [git-tag](https://git-scm.com/docs/git-tag) for more details.
|
167
|
+
# @option options [boolean] :annotate Make an unsigned, annotated tag object
|
168
|
+
# @option options [boolean] :a An alias for the `:annotate` option
|
169
|
+
# @option options [boolean] :d Delete existing tag with the given names.
|
170
|
+
# @option options [boolean] :f Replace an existing tag with the given name (instead of failing)
|
171
|
+
# @option options [String] :message Use the given tag message
|
172
|
+
# @option options [String] :m An alias for the `:message` option
|
173
|
+
# @option options [boolean] :s Make a GPG-signed tag.
|
174
|
+
#
|
175
|
+
def add_tag(name, *options)
|
176
|
+
self.lib.tag(name, *options)
|
177
|
+
self.tag(name)
|
178
|
+
end
|
179
|
+
|
125
180
|
# changes current working directory for a block
|
126
181
|
# to the git working directory
|
127
182
|
#
|
@@ -254,27 +309,11 @@ module Git
|
|
254
309
|
self.object('HEAD').grep(string, path_limiter, opts)
|
255
310
|
end
|
256
311
|
|
257
|
-
#
|
258
|
-
#
|
259
|
-
# @example
|
260
|
-
# git.add
|
261
|
-
# git.add('path/to/file')
|
262
|
-
# git.add(['path/to/file1','path/to/file2'])
|
263
|
-
# git.add(:all => true)
|
312
|
+
# List the files in the worktree that are ignored by git
|
313
|
+
# @return [Array<String>] the list of ignored files relative to teh root of the worktree
|
264
314
|
#
|
265
|
-
|
266
|
-
|
267
|
-
#
|
268
|
-
# @param [String,Array] paths files paths to be added (optional, default='.')
|
269
|
-
# @param [Hash] options
|
270
|
-
# @option options [boolean] :all
|
271
|
-
# Update the index not only where the working tree has a file matching
|
272
|
-
# <pathspec> but also where the index already has an entry.
|
273
|
-
# See [the --all option to git-add](https://git-scm.com/docs/git-add#Documentation/git-add.txt--A)
|
274
|
-
# for more details.
|
275
|
-
#
|
276
|
-
def add(paths = '.', **options)
|
277
|
-
self.lib.add(paths, options)
|
315
|
+
def ignored_files
|
316
|
+
self.lib.ignored_files
|
278
317
|
end
|
279
318
|
|
280
319
|
# removes file(s) from the git repository
|
@@ -409,14 +448,27 @@ module Git
|
|
409
448
|
self.lib.conflicts(&block)
|
410
449
|
end
|
411
450
|
|
412
|
-
#
|
451
|
+
# Pulls the given branch from the given remote into the current branch
|
452
|
+
#
|
453
|
+
# @param remote [String] the remote repository to pull from
|
454
|
+
# @param branch [String] the branch to pull from
|
455
|
+
# @param opts [Hash] options to pass to the pull command
|
413
456
|
#
|
414
|
-
#
|
415
|
-
#
|
416
|
-
#
|
457
|
+
# @option opts [Boolean] :allow_unrelated_histories (false) Merges histories of two projects that started their
|
458
|
+
# lives independently
|
459
|
+
# @example pulls from origin/master
|
460
|
+
# @git.pull
|
461
|
+
# @example pulls from upstream/master
|
462
|
+
# @git.pull('upstream')
|
463
|
+
# @example pulls from upstream/develop
|
464
|
+
# @git.pull('upstream', 'develop')
|
417
465
|
#
|
418
|
-
|
419
|
-
|
466
|
+
# @return [Void]
|
467
|
+
#
|
468
|
+
# @raise [Git::FailedError] if the pull fails
|
469
|
+
# @raise [ArgumentError] if a branch is given without a remote
|
470
|
+
def pull(remote = nil, branch = nil, opts = {})
|
471
|
+
self.lib.pull(remote, branch, opts)
|
420
472
|
end
|
421
473
|
|
422
474
|
# returns an array of Git:Remote objects
|
@@ -424,22 +476,6 @@ module Git
|
|
424
476
|
self.lib.remotes.map { |r| Git::Remote.new(self, r) }
|
425
477
|
end
|
426
478
|
|
427
|
-
# adds a new remote to this repository
|
428
|
-
# url can be a git url or a Git::Base object if it's a local reference
|
429
|
-
#
|
430
|
-
# @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
|
431
|
-
# @git.fetch('scotts_git')
|
432
|
-
# @git.merge('scotts_git/master')
|
433
|
-
#
|
434
|
-
# Options:
|
435
|
-
# :fetch => true
|
436
|
-
# :track => <branch_name>
|
437
|
-
def add_remote(name, url, opts = {})
|
438
|
-
url = url.repo.path if url.is_a?(Git::Base)
|
439
|
-
self.lib.remote_add(name, url, opts)
|
440
|
-
Git::Remote.new(self, name)
|
441
|
-
end
|
442
|
-
|
443
479
|
# sets the url for a remote
|
444
480
|
# url can be a git url or a Git::Base object if it's a local reference
|
445
481
|
#
|
@@ -463,7 +499,7 @@ module Git
|
|
463
499
|
self.lib.tags.map { |r| tag(r) }
|
464
500
|
end
|
465
501
|
|
466
|
-
#
|
502
|
+
# Create a new git tag
|
467
503
|
#
|
468
504
|
# @example
|
469
505
|
# repo.add_tag('tag_name', object_reference)
|
@@ -619,6 +655,96 @@ module Git
|
|
619
655
|
self.lib.branch_current
|
620
656
|
end
|
621
657
|
|
658
|
+
# @return [Git::Branch] an object for branch_name
|
659
|
+
def branch(branch_name = self.current_branch)
|
660
|
+
Git::Branch.new(self, branch_name)
|
661
|
+
end
|
662
|
+
|
663
|
+
# @return [Git::Branches] a collection of all the branches in the repository.
|
664
|
+
# Each branch is represented as a {Git::Branch}.
|
665
|
+
def branches
|
666
|
+
Git::Branches.new(self)
|
667
|
+
end
|
668
|
+
|
669
|
+
# returns a Git::Worktree object for dir, commitish
|
670
|
+
def worktree(dir, commitish = nil)
|
671
|
+
Git::Worktree.new(self, dir, commitish)
|
672
|
+
end
|
673
|
+
|
674
|
+
# returns a Git::worktrees object of all the Git::Worktrees
|
675
|
+
# objects for this repo
|
676
|
+
def worktrees
|
677
|
+
Git::Worktrees.new(self)
|
678
|
+
end
|
679
|
+
|
680
|
+
# @return [Git::Object::Commit] a commit object
|
681
|
+
def commit_tree(tree = nil, opts = {})
|
682
|
+
Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
|
683
|
+
end
|
684
|
+
|
685
|
+
# @return [Git::Diff] a Git::Diff object
|
686
|
+
def diff(objectish = 'HEAD', obj2 = nil)
|
687
|
+
Git::Diff.new(self, objectish, obj2)
|
688
|
+
end
|
689
|
+
|
690
|
+
# @return [Git::Object] a Git object
|
691
|
+
def gblob(objectish)
|
692
|
+
Git::Object.new(self, objectish, 'blob')
|
693
|
+
end
|
694
|
+
|
695
|
+
# @return [Git::Object] a Git object
|
696
|
+
def gcommit(objectish)
|
697
|
+
Git::Object.new(self, objectish, 'commit')
|
698
|
+
end
|
699
|
+
|
700
|
+
# @return [Git::Object] a Git object
|
701
|
+
def gtree(objectish)
|
702
|
+
Git::Object.new(self, objectish, 'tree')
|
703
|
+
end
|
704
|
+
|
705
|
+
# @return [Git::Log] a log with the specified number of commits
|
706
|
+
def log(count = 30)
|
707
|
+
Git::Log.new(self, count)
|
708
|
+
end
|
709
|
+
|
710
|
+
# returns a Git::Object of the appropriate type
|
711
|
+
# you can also call @git.gtree('tree'), but that's
|
712
|
+
# just for readability. If you call @git.gtree('HEAD') it will
|
713
|
+
# still return a Git::Object::Commit object.
|
714
|
+
#
|
715
|
+
# object calls a method that will run a rev-parse
|
716
|
+
# on the objectish and determine the type of the object and return
|
717
|
+
# an appropriate object for that type
|
718
|
+
#
|
719
|
+
# @return [Git::Object] an instance of the appropriate type of Git::Object
|
720
|
+
def object(objectish)
|
721
|
+
Git::Object.new(self, objectish)
|
722
|
+
end
|
723
|
+
|
724
|
+
# @return [Git::Remote] a remote of the specified name
|
725
|
+
def remote(remote_name = 'origin')
|
726
|
+
Git::Remote.new(self, remote_name)
|
727
|
+
end
|
728
|
+
|
729
|
+
# @return [Git::Status] a status object
|
730
|
+
def status
|
731
|
+
Git::Status.new(self)
|
732
|
+
end
|
733
|
+
|
734
|
+
# @return [Git::Object::Tag] a tag object
|
735
|
+
def tag(tag_name)
|
736
|
+
Git::Object.new(self, tag_name, 'tag', true)
|
737
|
+
end
|
738
|
+
|
739
|
+
# Find as good common ancestors as possible for a merge
|
740
|
+
# example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true)
|
741
|
+
#
|
742
|
+
# @return [Array<Git::Object::Commit>] a collection of common ancestors
|
743
|
+
def merge_base(*args)
|
744
|
+
shas = self.lib.merge_base(*args)
|
745
|
+
shas.map { |sha| gcommit(sha) }
|
746
|
+
end
|
747
|
+
|
622
748
|
private
|
623
749
|
|
624
750
|
# Normalize options before they are sent to Git::Base.new
|