git_commands 2.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 00a6f3b64ac568ed9a8a00e28c157015f70a5892
4
+ data.tar.gz: deeb00dac84552dd33e4f8bfde79aaae31d8ee90
5
+ SHA512:
6
+ metadata.gz: dd423813e1be43a52b56011ef9c49540b759342e04fca35981967b618166c8613a1ac4eff440b69bebaabcaa0bee6ce1edd15850220e704d239b206a47cef16a
7
+ data.tar.gz: 44a626d66746877bb03092572b74541858607a81f698d46e69887747660f6f181a48f4b36e43c16a62fcac1dc0dec6a3a55f9dafb66e2774f5d9b8590a3d00f5
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ /.vagrant/
2
+ /.bundle/
3
+ .branches
4
+ Gemfile.lock
5
+ *.gem
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - 2.1.8
8
+ - 2.2.1
9
+ - 2.3.0
10
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dacom.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Michele Costa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ ## Table of Contents
2
+ * [Workflow](#workflow)
3
+ * [Scope](#scope)
4
+ * [Installation](#installation)
5
+ * [Usage](#usage)
6
+ * [setup](#setup)
7
+ * [rebase](#rebase)
8
+ * [purge](#purge)
9
+ * [aggregate](#aggregate)
10
+
11
+ ## Workflow
12
+ This script will facilitate adopting a subset of the branch-featuring workflow characterised by:
13
+ * each **feature** will have **its own branch**
14
+ * **feature** branches **derive** directly **form master**
15
+ * **integration** of master to feature branch happens **via rebasing**
16
+ * rebasing interactively is used on feature branch to **squash commits** to get a **single one per feature** branch
17
+ * **pushing with force** on local branches is not an issue
18
+ * **release** branches are created **aggregating multiple branches** into a new one
19
+
20
+ ## Scope
21
+ The scope of this is helping out in the following cases:
22
+ * you have multiple feature branches waiting for release due to some reason (i.e. long QA time...), and need to keep them aligned with master
23
+ * you need to quickly aggregate branches for a release
24
+
25
+ ## Installation
26
+ I assume you have GIT installed ;)
27
+ You will probably use this gem standalone, since i see no use in including it into another project.
28
+ Just clone the Github repository, move to the gem directory and start using rake tasks.
29
+
30
+ ## Usage
31
+ Here are the main Rake tasks:
32
+
33
+ ### setup
34
+ The core of the library is automating multiple branches fetching, this action happens in two concurrent ways:
35
+ * from the command line, by splitting a comma separated list
36
+ * by reading a file where names are listed on each line
37
+ In case **no branches** are fetched the **script halts**.
38
+
39
+ Is also assumed you're pointing to a project directory somewhere, so the script could move in and execute the GIT commands for you.
40
+
41
+ To call this task with arguments call it like that:
42
+ ```ruby
43
+ rake git_commands:setup repo=git_repository base_dir=repo_path branches_file=file_listing_branches branches=list,of,branches,separated,by,comma
44
+ ```
45
+ Here are the arguments list:
46
+ * **repo**: the repository name you want to automate git commant to
47
+ * **base_dir**: the base path to your GIT repo, excluding its name (specified eralier). It defaults to HOME/Sites
48
+ * **branches_file**: the path to the file, if any, listing the branches names. It defaults to the **.branches** file inside of your repo path (you need to add it to the .gitignore then)
49
+ * **branches**: a list of branches separated by comma (optional), if specified it has precedence over the branches_file
50
+
51
+ ### rebase
52
+ This is probably the most useful command in case you have several branch to rebase with _origin/master_ frequently.
53
+ Consider after the rebase the branch is pushed to origin with force, so be aware in case more than one programmer access the same branch from different computers.
54
+ A confirmation is asked to continue.
55
+
56
+ As the other tasks, it depends on the setup one, so it accepts the same arguments:
57
+ ```ruby
58
+ # loads branches from the repo .branches file, repo si located at HOME/Sites/my_repo
59
+ rake git_commands:rebase repo=my_repo
60
+ ```
61
+
62
+ ### purge
63
+ This command remove the specified branches locally and remotely.
64
+ A confirmation is asked before each removal.
65
+ It uses the same arguments as setup:
66
+ ```ruby
67
+ # purge old branches specified at the command line, repo is located at HOME/Sites/my_repo
68
+ rake git_commands:purge repo=my_repo branches=old_branch,older_branch,oldest_branch
69
+ ```
70
+
71
+ ### aggregate
72
+ It should be useful to aggregate your branches into a single one in case you want to create a release branch.
73
+ It uses the following naming convention: rb_yyyy_mm_dd
74
+ A confirmation is asked to continue.
75
+ It uses the same arguments as setup:
76
+ ```ruby
77
+ # aggregate branches listed in the /tmp/to_release file, repo si located at HOME/Sites/my_repo
78
+ rake git_commands:aggregate repo=my_repo branches_file=/tmp/to_release
79
+ ```
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ import 'lib/tasks/git_commands.rake'
4
+
5
+ Rake::TestTask.new(:spec) do |t|
6
+ t.libs << 'lib'
7
+ t.libs << 'spec'
8
+ t.test_files = FileList['spec/*_spec.rb']
9
+ end
10
+
11
+ task :default => :spec
data/Vagrantfile ADDED
@@ -0,0 +1,80 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # All Vagrant configuration is done below. The "2" in Vagrant.configure
5
+ # configures the configuration version (we support older styles for
6
+ # backwards compatibility). Please don't change it unless you know what
7
+ # you're doing.
8
+ Vagrant.configure(2) do |config|
9
+ # The most common configuration options are documented and commented below.
10
+ # For a complete reference, please see the online documentation at
11
+ # https://docs.vagrantup.com.
12
+
13
+ # Every Vagrant development environment requires a box. You can search for
14
+ # boxes at https://atlas.hashicorp.com/search.
15
+ config.vm.box = "ubuntu/trusty64"
16
+
17
+ # Disable automatic box update checking. If you disable this, then
18
+ # boxes will only be checked for updates when the user runs
19
+ # `vagrant box outdated`. This is not recommended.
20
+ config.vm.box_check_update = false
21
+
22
+ # Create a forwarded port mapping which allows access to a specific port
23
+ # within the machine from a port on the host machine. In the example below,
24
+ # accessing "localhost:8080" will access port 80 on the guest machine.
25
+ # config.vm.network "forwarded_port", guest: 80, host: 8080
26
+
27
+ # Create a private network, which allows host-only access to the machine
28
+ # using a specific IP.
29
+ config.vm.network "private_network", ip: "192.168.33.22"
30
+
31
+ # Create a public network, which generally matched to bridged network.
32
+ # Bridged networks make the machine appear as another physical device on
33
+ # your network.
34
+ # config.vm.network "public_network"
35
+
36
+ # Share an additional folder to the guest VM. The first argument is
37
+ # the path on the host to the actual folder. The second argument is
38
+ # the path on the guest to mount the folder. And the optional third
39
+ # argument is a set of non-required options.
40
+ # config.vm.synced_folder "../data", "/vagrant_data"
41
+
42
+ # Provider-specific configuration so you can fine-tune various
43
+ # backing providers for Vagrant. These expose provider-specific options.
44
+ # Example for VirtualBox:
45
+ #
46
+ config.vm.provider "virtualbox" do |vb|
47
+ # Display the VirtualBox GUI when booting the machine
48
+ #vb.gui = true
49
+
50
+ # Customize the amount of memory on the VM:
51
+ vb.memory = "6144"
52
+ vb.cpus = 3
53
+ end
54
+ #
55
+ # View the documentation for the provider you are using for more
56
+ # information on available options.
57
+
58
+ # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
59
+ # such as FTP and Heroku are also available. See the documentation at
60
+ # https://docs.vagrantup.com/v2/push/atlas.html for more information.
61
+ # config.push.define "atlas" do |push|
62
+ # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
63
+ # end
64
+
65
+ # Enable provisioning with a shell script. Additional provisioners such as
66
+ # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
67
+ # documentation for more information about their specific syntax and use.
68
+ # config.vm.provision "shell", inline: <<-SHELL
69
+ # sudo apt-get update
70
+ # sudo apt-get install -y apache2
71
+ # SHELL
72
+ $script = [
73
+ "sudo apt-add-repository ppa:brightbox/ruby-ng",
74
+ "sudo apt-get update",
75
+ "sudo apt-get -y -q install build-essential libssl-dev git",
76
+ "sudo apt-get -y -q install ruby2.2 ruby2.2-dev",
77
+ "sudo gem install bundler"]
78
+
79
+ config.vm.provision "shell", inline: $script.join(" && ")
80
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "git_utils"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'git_commands/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "git_commands"
8
+ s.version = GitCommands::VERSION
9
+ s.authors = ["costajob"]
10
+ s.email = ["costajob@gmail.com"]
11
+ s.summary = "Utility library to rebase and aggregate your project branches"
12
+ s.homepage = "https://github.com/costajob/git_commands.git"
13
+ s.license = "MIT"
14
+ s.required_ruby_version = ">= 1.9.2"
15
+
16
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|s|features)/}) }
17
+ s.bindir = "exe"
18
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "bundler", "~> 1.11"
22
+ s.add_development_dependency "rake", "~> 10.0"
23
+ s.add_development_dependency "minitest", "~> 5.0"
24
+ s.add_development_dependency "rr", "~> 1.2"
25
+ end
@@ -0,0 +1 @@
1
+ require 'git_commands/command'
@@ -0,0 +1,22 @@
1
+ module GitCommands
2
+ module Colorize
3
+ CODES = {
4
+ :red => 31,
5
+ :green => 32,
6
+ :yellow => 33,
7
+ :blue => 34,
8
+ :magenta => 35,
9
+ :cyan => 36,
10
+ :grey => 37
11
+ }
12
+
13
+ end
14
+ end
15
+
16
+ String.instance_eval do
17
+ GitCommands::Colorize::CODES.each do |message, code|
18
+ define_method(message) do
19
+ "\e[#{code}m#{self}\e[0m"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,135 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+ require 'net/http'
4
+ require 'git_commands/prompt'
5
+
6
+ module GitCommands
7
+ class Command
8
+ include Prompt
9
+
10
+ class GitError < StandardError; end
11
+ class NoBranchesError < StandardError; end
12
+
13
+ GITHUB_HOST = 'github.com'
14
+ BASE_DIR = File.join(ENV['HOME'], 'Sites')
15
+ UNFINISHED_REBASE_FILES = %w(rebase-merge rebase-apply)
16
+
17
+ def self.check_connection
18
+ !!Net::HTTP.new(GITHUB_HOST).head('/')
19
+ rescue Errno::ENETUNREACH => e
20
+ raise e, 'There is no connection!'
21
+ end
22
+
23
+ def initialize(options = {})
24
+ self.class.check_connection
25
+ @repo = options[:repo] || error('Please specify a valid repository name!', ArgumentError)
26
+ @base_dir = options[:base_dir] || BASE_DIR
27
+ @branches_file = options[:branches_file] || repo_path.join('.branches')
28
+ @branches = options[:branches].to_s.split(',')
29
+ fetch_branches
30
+ check_branches
31
+ end
32
+
33
+ def purge
34
+ enter_repo do
35
+ @branches.each do |branch|
36
+ error('Trying ro remove master!', GitError) if branch == 'master'
37
+ warning("Removing branch: #{branch}")
38
+ confirm('Remove local branch') do
39
+ `git branch -D #{branch}`
40
+ end
41
+ confirm('Remove remote branch') do
42
+ `git push origin :#{branch}`
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def rebase
49
+ confirm('Proceed rebasing these branches') do
50
+ enter_repo do
51
+ @branches.each do |branch|
52
+ warning("Rebasing branch: #{branch}")
53
+ `git checkout #{branch}`
54
+ `git pull origin #{branch}`
55
+ rebase_with_master
56
+ `git push origin #{branch} -f`
57
+ `git checkout master`
58
+ `git branch -D #{branch}`
59
+ success 'Rebased successfully!'
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def aggregate
66
+ temp = "temp_#{aggregate_name}"
67
+ confirm("Aggregate branches into #{aggregate_name}") do
68
+ enter_repo do
69
+ `git branch #{aggregate_name}`
70
+ @branches.each do |branch|
71
+ warning("Merging branch: #{branch}")
72
+ `git checkout -b #{temp} origin/#{branch} --no-track`
73
+ rebase_with_master
74
+ `git rebase #{aggregate_name}`
75
+ `git checkout #{aggregate_name}`
76
+ `git merge #{temp}`
77
+ `git branch -d #{temp}`
78
+ end
79
+ end
80
+ success 'Aggregate branch created'
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def repo_path
87
+ @repo_path ||= Pathname::new(File.join(@base_dir, @repo))
88
+ end
89
+
90
+ def fetch_branches
91
+ return unless @branches.empty? && File.exist?(@branches_file)
92
+ warning('Loading branches file')
93
+ @branches = File.foreach(@branches_file).map(&:strip)
94
+ end
95
+
96
+ def check_branches
97
+ error('No branches have been loaded!', NoBranchesError) if @branches.empty?
98
+ print_branches
99
+ end
100
+
101
+ def print_branches
102
+ size = @branches.to_a.size
103
+ plural = size > 1 ? 'es' : ''
104
+ success "Successfully loaded #{size} branch#{plural}:"
105
+ puts @branches.each_with_index.map { |branch, i| "#{(i+1).to_s.rjust(2, '0')}. #{branch}" } + ['']
106
+ end
107
+
108
+ def pull_master
109
+ `git checkout master`
110
+ `git pull`
111
+ end
112
+
113
+ def rebase_with_master
114
+ `git rebase origin/master`
115
+ error('Halting unfinished rebase!', GitError) { `git rebase --abort` } if unfinished_rebase?
116
+ end
117
+
118
+ def enter_repo
119
+ Dir.chdir repo_path do
120
+ pull_master
121
+ yield
122
+ end
123
+ end
124
+
125
+ def unfinished_rebase?
126
+ UNFINISHED_REBASE_FILES.any? do |name|
127
+ File.exists?(repo_path.join('.git', name))
128
+ end
129
+ end
130
+
131
+ def aggregate_name
132
+ @aggregate_name ||= Time.new.strftime("rb_%Y-%m-%d")
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,47 @@
1
+ require 'git_commands/colorize'
2
+
3
+ module GitCommands
4
+ module Prompt
5
+ VALID_ANSWERS = %w[Y y N n]
6
+
7
+ class AbortError < StandardError; end
8
+
9
+ def warning(message, char = '*')
10
+ spacer = (char * (message.size + 4)).grey
11
+ puts "\n", spacer, "#{char} #{message.to_s.yellow} #{char}", spacer, "\n"
12
+ end
13
+
14
+ def error(message, error = StandardError)
15
+ puts message.to_s.red
16
+ yield if block_given?
17
+ fail error, message
18
+ end
19
+
20
+ def success(message)
21
+ puts message.to_s.green
22
+ end
23
+
24
+ def confirm(message)
25
+ res = begin
26
+ ask "#{message} (Y/N)?"
27
+ end until VALID_ANSWERS.include?(res)
28
+ case res
29
+ when /y/i
30
+ yield
31
+ else
32
+ error('Aborted operation!', AbortError)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def ask(message)
39
+ print message.cyan
40
+ input
41
+ end
42
+
43
+ def input
44
+ STDIN.gets.chomp
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module GitCommands
2
+ VERSION = "2.1.0"
3
+ end
@@ -0,0 +1,29 @@
1
+ require 'git_commands/command'
2
+
3
+ namespace :git_commands do
4
+ desc <<END
5
+ Setup the command instance:
6
+ > rake git_utils:setup repo=git_repository base_dir=repo_path branches_file=file_listing_branches branches=list,of,branches,separated,by,comma
7
+ END
8
+ task :setup do
9
+ @command = GitCommands::Command::new(:repo => ENV['repo'],
10
+ :base_dir => ENV['base_dir'],
11
+ :branches_file => ENV['branches_file'],
12
+ :branches => ENV['branches'])
13
+ end
14
+
15
+ desc 'Purge specified branches locally and from origin'
16
+ task :purge => :setup do
17
+ @command.purge
18
+ end
19
+
20
+ desc 'Rebase specified branches with master'
21
+ task :rebase => :setup do
22
+ @command.rebase
23
+ end
24
+
25
+ desc 'Aggregate specified branches into a single one'
26
+ task :aggregate => :setup do
27
+ @command.aggregate
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git_commands
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.1.0
5
+ platform: ruby
6
+ authors:
7
+ - costajob
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
69
+ description:
70
+ email:
71
+ - costajob@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - Vagrantfile
83
+ - bin/console
84
+ - bin/setup
85
+ - git_commands.gemspec
86
+ - lib/git_commands.rb
87
+ - lib/git_commands/colorize.rb
88
+ - lib/git_commands/command.rb
89
+ - lib/git_commands/prompt.rb
90
+ - lib/git_commands/version.rb
91
+ - lib/tasks/git_commands.rake
92
+ homepage: https://github.com/costajob/git_commands.git
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 1.9.2
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.5.1
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Utility library to rebase and aggregate your project branches
116
+ test_files: []