git-utils 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +23 -0
- data/README.md +85 -0
- data/Rakefile +1 -0
- data/bin/git-amend +4 -0
- data/bin/git-anal +4 -0
- data/bin/git-cleanup +9 -0
- data/bin/git-delete-remote-branch +6 -0
- data/bin/git-merge-branch +11 -0
- data/bin/git-open +6 -0
- data/bin/git-polish +4 -0
- data/bin/git-pull-request +6 -0
- data/bin/git-push-branch +7 -0
- data/bin/git-switch +7 -0
- data/bin/git-sync +6 -0
- data/bin/git-undo +4 -0
- data/git-utils.gemspec +20 -0
- data/lib/git-utils.rb +10 -0
- data/lib/git-utils/command.rb +100 -0
- data/lib/git-utils/delete_remote_branch.rb +41 -0
- data/lib/git-utils/merge_branch.rb +35 -0
- data/lib/git-utils/open.rb +40 -0
- data/lib/git-utils/options.rb +39 -0
- data/lib/git-utils/pull_request.rb +46 -0
- data/lib/git-utils/push_branch.rb +20 -0
- data/lib/git-utils/switch.rb +33 -0
- data/lib/git-utils/sync.rb +22 -0
- data/lib/git-utils/version.rb +5 -0
- data/spec/commands/command_spec.rb +11 -0
- data/spec/commands/delete_remote_branch_spec.rb +18 -0
- data/spec/commands/merge_branch_spec.rb +38 -0
- data/spec/commands/open_spec.rb +37 -0
- data/spec/commands/pull_request_spec.rb +38 -0
- data/spec/commands/push_branch_spec.rb +17 -0
- data/spec/commands/switch_spec.rb +18 -0
- data/spec/commands/sync_spec.rb +19 -0
- data/spec/spec_helper.rb +12 -0
- data/test-open-pr.sh +71 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2faeb0fba87e36f531addf4afed6971f1edf3aca
|
4
|
+
data.tar.gz: c74f6c8870f6f05b34976ebf29ce7803afebf1f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2bb21163ca18e41b1695b00da352c8d259cd1f3b0e2db93feed285021ef44607c2b63f25063643cd601708356dbd140f651a92cbe9c4ad26da807c6acfe2541b
|
7
|
+
data.tar.gz: c0efe25871d671007427bf3cb2d28427f16a03d59b7086d768b046b2d513e1f7b0358a7be08d9847f8135b2927bcf22872f48f4a7597088701260e615fd18cb9
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.rvmrc
|
19
|
+
.DS_Store
|
20
|
+
.api_token
|
21
|
+
.project_id
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pivotal-github
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2013 Michael Hartl
|
2
|
+
Copyright (c) 2013 Aleksandar Simic
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Git utilities
|
2
|
+
|
3
|
+
This repo contains some Git utility scripts. The highlights are `git open`, `git pull-request`, `git push-branch`, and `git undo`, which you'll never understand how you did without.
|
4
|
+
|
5
|
+
The commands are especially useful when combined with [`pivotal-github`](https://github.com/mhartl/git-utils) gem (which, despite its name, also works with Bitbucket).
|
6
|
+
|
7
|
+
The `git-utils` used to be pure Bash scripts, but they are now available as a Ruby gem, both because Ruby is more powerful than bash and because now `git-utils` can be included more easily as a dependency for the [`pivotal-github`](https://github.com/mhartl/pivotal-github/) gem. As a result, installation is easy if you have RubyGems installed:
|
8
|
+
|
9
|
+
gem install git-utils
|
10
|
+
|
11
|
+
## Commands
|
12
|
+
|
13
|
+
* `git amend`: alias for `git commit --amend`
|
14
|
+
* `git anal` (use with caution): makes a commit with the message "Make anal changes"
|
15
|
+
* `git cleanup`: deletes every branch already merged into current branch (apart from `master`, `staging`, and `development`)
|
16
|
+
* `git merge-branch [branch]`: merges current branch into given branch (defaults to `master`)
|
17
|
+
* `git open`: opens the remote page for the repo (OS X only)
|
18
|
+
* `git polish`: makes a commit with the message "Polish"
|
19
|
+
* `git pull-request`: opens the remote page for issuing a new a pull request (OS X only)
|
20
|
+
* `git push-branch`: pushes the current branch up to origin
|
21
|
+
* `git delete-remote-branch <branch>`: deletes the remote branch if it is safe to do so
|
22
|
+
* `git switch <pattern>`: switches to the first branch matching the given pattern
|
23
|
+
* `git sync`: syncs the local master with remote
|
24
|
+
* `git undo`: undoes the last commit
|
25
|
+
|
26
|
+
## Aliases
|
27
|
+
|
28
|
+
Here are some suggested aliases:
|
29
|
+
|
30
|
+
git config --global alias.mb merge-branch
|
31
|
+
git config --global alias.pr pull-request
|
32
|
+
git config --global alias.pb push-branch
|
33
|
+
|
34
|
+
## Further details
|
35
|
+
|
36
|
+
Some of these commands deserve further explanation.
|
37
|
+
|
38
|
+
### git merge-branch
|
39
|
+
|
40
|
+
`git merge-branch [target]` merges the current branch into the target branch (defaults to `master`). On a branch called `add-markdown-support`, `git merge-branch` is equivalent to the following:
|
41
|
+
|
42
|
+
$ git checkout master
|
43
|
+
$ git merge --no-ff --log add-markdown-support
|
44
|
+
|
45
|
+
Note that this effectively changes the default merge behavior from fast-forward to no-fast-forward, which makes it possible to use `git log` to see which of the commit objects together have implemented a feature on a particular branch. As noted in [A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/),
|
46
|
+
|
47
|
+
> The `--no-ff` flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature… Yes, it will create a few more (empty) commit objects, but the gain is much bigger than that cost.
|
48
|
+
|
49
|
+
In addition, the `--log` option puts the commit messages from the individual commits in the merge message, which is especially useful for viewing the full diff represented by the commit.
|
50
|
+
|
51
|
+
These options can be overriden (and thus restored to their defaults) by passing the options `-ff` or `--no-log`. `git merge-branch` accepts any options valid for `git merge`.
|
52
|
+
|
53
|
+
### git push-branch
|
54
|
+
|
55
|
+
`git push-branch` creates a remote branch at `origin` with the name of the current branch:
|
56
|
+
|
57
|
+
$ git branch-push
|
58
|
+
* [new branch] add-markdown-support -> add-markdown-support
|
59
|
+
|
60
|
+
`git push-branch` accepts any options valid for `git push`.
|
61
|
+
|
62
|
+
|
63
|
+
### git sync
|
64
|
+
|
65
|
+
`git sync` syncs the local `master` with the remote `master`. On a branch called `add-markdown-support`, `git sync` is equivalent to the following:
|
66
|
+
|
67
|
+
$ git checkout master
|
68
|
+
$ git pull
|
69
|
+
$ git checkout add-markdown-support
|
70
|
+
|
71
|
+
The purpose of `git sync` is to prepare the current branch for rebasing against `master`:
|
72
|
+
|
73
|
+
$ git sync
|
74
|
+
$ git rebase master
|
75
|
+
|
76
|
+
(This is essentially equivalent to
|
77
|
+
|
78
|
+
$ git fetch
|
79
|
+
$ git rebase origin/master
|
80
|
+
|
81
|
+
but I don't like having `master` and `origin/master` be different since that means you have to remember to run `git pull` on `master` some time down the line.)
|
82
|
+
|
83
|
+
## Installation
|
84
|
+
|
85
|
+
gem install git-utils
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/git-amend
ADDED
data/bin/git-anal
ADDED
data/bin/git-cleanup
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Deletes (almost) every branch already merged into current branch.
|
4
|
+
# Exceptions are `master`, `staging`, and `development`, and the current
|
5
|
+
# branch, which are preserved.
|
6
|
+
preserved = "(master|staging|development)"
|
7
|
+
cmd = %(git branch --merged | grep -v "\*" | egrep -v "#{preserved}" | )
|
8
|
+
cmd += 'xargs -n 1 git branch -d'
|
9
|
+
system cmd
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'git-utils/merge_branch'
|
4
|
+
|
5
|
+
# Merges the current branch into the given branch (defaults to master).
|
6
|
+
# E.g., 'git merge-branch foobar' merges the current branch into foobar.
|
7
|
+
# 'git merge-branch', merges the current branch into master.
|
8
|
+
# git merge-branch uses the --no-ff --log options to ensure that the
|
9
|
+
# merge creates a new commit object and that the individual commits appear
|
10
|
+
# in the log file.
|
11
|
+
exit Command.run!(MergeBranch, ARGV.dup)
|
data/bin/git-open
ADDED
data/bin/git-polish
ADDED
data/bin/git-push-branch
ADDED
data/bin/git-switch
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'git-utils/switch'
|
4
|
+
|
5
|
+
# Switches to the first branch matching the given pattern.
|
6
|
+
# E.g., 'git switch foobar' switches to 'the-foobar-branch'.
|
7
|
+
exit Command.run!(Switch, ARGV.dup)
|
data/bin/git-sync
ADDED
data/bin/git-undo
ADDED
data/git-utils.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'git-utils/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "git-utils"
|
8
|
+
gem.version = Git::Utils::VERSION
|
9
|
+
gem.authors = ["Michael Hartl"]
|
10
|
+
gem.email = ["michael@michaelhartl.com"]
|
11
|
+
gem.description = %q{Add some Git utilities}
|
12
|
+
gem.summary = %q{See the README for full documentation}
|
13
|
+
gem.homepage = "https://github.com/mhartl/git-utils"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
end
|
data/lib/git-utils.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "git-utils/version"
|
2
|
+
require "git-utils/options"
|
3
|
+
require "git-utils/command"
|
4
|
+
require "git-utils/merge_branch"
|
5
|
+
require "git-utils/open"
|
6
|
+
require "git-utils/delete_remote_branch"
|
7
|
+
require "git-utils/push_branch"
|
8
|
+
require "git-utils/switch"
|
9
|
+
require "git-utils/sync"
|
10
|
+
require "git-utils/pull_request"
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'git-utils/options'
|
4
|
+
|
5
|
+
class Command
|
6
|
+
attr_accessor :args, :cmd, :options, :known_options, :unknown_options
|
7
|
+
|
8
|
+
def initialize(args = [])
|
9
|
+
self.args = args
|
10
|
+
self.options = OpenStruct.new
|
11
|
+
parse
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse
|
15
|
+
self.known_options = Options::known_options(parser, args)
|
16
|
+
self.unknown_options = Options::unknown_options(parser, args)
|
17
|
+
parser.parse!(known_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def parser
|
21
|
+
OptionParser.new
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the current Git branch.
|
25
|
+
def current_branch
|
26
|
+
@current_branch ||= `git rev-parse --abbrev-ref HEAD`.strip
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the URL for the remote origin.
|
30
|
+
def origin_url
|
31
|
+
@origin_url ||= `git config --get remote.origin.url`.strip
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
# Returns the name of the repository service.
|
37
|
+
# It's currently GitHub, Bitbucket, or Stash.
|
38
|
+
# We return blank for an unknown service; the command will still
|
39
|
+
# often work in that case.
|
40
|
+
def service
|
41
|
+
if origin_url =~ /github/i
|
42
|
+
'github'
|
43
|
+
elsif origin_url =~ /bitbucket/i
|
44
|
+
'bitbucket'
|
45
|
+
elsif origin_url =~ /stash/i
|
46
|
+
'stash'
|
47
|
+
else
|
48
|
+
''
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the protocol of the origin URL (defaults to ssh).
|
53
|
+
def protocol
|
54
|
+
if origin_url =~ /https?:\/\//
|
55
|
+
'http'
|
56
|
+
else
|
57
|
+
'ssh'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Runs a command.
|
62
|
+
# If the argument array contains '--debug', returns the command that would
|
63
|
+
# have been run.
|
64
|
+
def self.run!(command_class, args)
|
65
|
+
debug = args.delete('--debug')
|
66
|
+
command = command_class.new(args)
|
67
|
+
if debug
|
68
|
+
puts command.cmd
|
69
|
+
return 1
|
70
|
+
else
|
71
|
+
command.run!
|
72
|
+
return 0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def run!
|
77
|
+
system cmd
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Returns an argument string based on given arguments.
|
83
|
+
# The main trick is to add in quotes for option
|
84
|
+
# arguments when necessary.
|
85
|
+
# For example, ['-a', '-m', 'foo bar'] becomes
|
86
|
+
# '-a -m "foo bar"'
|
87
|
+
def argument_string(args)
|
88
|
+
args.inject([]) do |opts, opt|
|
89
|
+
opts << (opt =~ /^-/ ? opt : opt.inspect)
|
90
|
+
end.join(' ')
|
91
|
+
end
|
92
|
+
|
93
|
+
def finish?
|
94
|
+
options.finish
|
95
|
+
end
|
96
|
+
|
97
|
+
def deliver?
|
98
|
+
options.deliver
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class DeleteRemoteBranch < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git delete-remote-branch <branch>"
|
8
|
+
opts.on("-o", "--override", "override unsafe delete") do |opt|
|
9
|
+
self.options.override = opt
|
10
|
+
end
|
11
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
12
|
+
puts opts.to_s; exit 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete_safely?
|
18
|
+
command = "git log ..origin/#{target_branch} 2> /dev/null"
|
19
|
+
system(command) && !`#{command}`.strip.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a command appropriate for executing at the command line
|
23
|
+
def cmd
|
24
|
+
if delete_safely? || options.override
|
25
|
+
c = ["git push origin :#{target_branch}"]
|
26
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
27
|
+
c.join("\n")
|
28
|
+
else
|
29
|
+
$stderr.puts "Target branch contains unmerged commits."
|
30
|
+
$stderr.puts "Please cherry-pick the commits or merge the branch again."
|
31
|
+
$stderr.puts "Use -o or --override to override."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Returns the name of the branch to be deleted.
|
38
|
+
def target_branch
|
39
|
+
self.known_options.first
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class MergeBranch < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git merge-branch [branch] [options]"
|
8
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
9
|
+
puts opts.to_s; exit 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns a command appropriate for executing at the command line
|
15
|
+
# For example:
|
16
|
+
# git checkout master
|
17
|
+
# git merge --no-ff --log <branch>
|
18
|
+
def cmd
|
19
|
+
lines = ["git checkout #{target_branch}"]
|
20
|
+
c = ["git merge --no-ff --log"]
|
21
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
22
|
+
c << current_branch
|
23
|
+
lines << c.join(' ')
|
24
|
+
lines.join("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Returns the name of the branch to be merged into.
|
30
|
+
# If there is anything left in the known options after parsing,
|
31
|
+
# that's the merge branch. Otherwise, it's master.
|
32
|
+
def target_branch
|
33
|
+
self.known_options.first || 'master'
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class Open < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git open"
|
8
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
9
|
+
puts opts.to_s; exit 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the URL for the repository page.
|
15
|
+
def page_url
|
16
|
+
if service == 'stash' && protocol == 'ssh'
|
17
|
+
pattern = /(.*)@([^:]*):?([^\/]*)\/([^\/]*)\/(.*)\.git/
|
18
|
+
replacement = 'https://\2/projects/\4/repos/\5/browse?at=' +
|
19
|
+
current_branch
|
20
|
+
elsif service == 'stash' && protocol == 'http'
|
21
|
+
pattern = /(.*)@([^:\/]*)(:?[^\/]*)\/(.*)scm\/([^\/]*)\/(.*)\.git/
|
22
|
+
replacement = 'https://\2\3/\4projects/\5/repos/\6/browse?at=' +
|
23
|
+
current_branch
|
24
|
+
elsif protocol == 'ssh'
|
25
|
+
pattern = /(.*)@(.*):(.*)\.git/
|
26
|
+
replacement = 'https://\2/\3/'
|
27
|
+
elsif protocol == 'http'
|
28
|
+
pattern = /https?\:\/\/(([^@]*)@)?(.*)\.git/
|
29
|
+
replacement = 'https://\3/'
|
30
|
+
end
|
31
|
+
origin_url.sub(pattern, replacement)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a command appropriate for executing at the command line
|
35
|
+
def cmd
|
36
|
+
c = ["open #{page_url}"]
|
37
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
38
|
+
c.join("\n")
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Options
|
4
|
+
|
5
|
+
# Returns a list of options unknown to a particular options parser
|
6
|
+
# For example, if '-a' is a known option but '-b' and '-c' are not,
|
7
|
+
# unknown_options(parser, ['-a', '-b', '-c']) returns ['-b', '-c'].
|
8
|
+
# It also preserves arguments, so
|
9
|
+
# unknown_options(parser, ['-a', '-b', '-c', 'foo bar']) returns
|
10
|
+
# ['-b', '-c', 'foo bar'].
|
11
|
+
def self.unknown_options(parser, args)
|
12
|
+
unknown = []
|
13
|
+
recursive_parse = Proc.new do |arg_list|
|
14
|
+
begin
|
15
|
+
# Hack to handle an unknown '-ff' argument
|
16
|
+
# The issue here is that OptParse interprets '-ff' as a '-f' option
|
17
|
+
# applied twice. This is sort-of a feature, as it allows, e.g., '-am'
|
18
|
+
# to set both the '-a' and '-m' options, but it interacts badly
|
19
|
+
# with '-ff' (as used by 'git merge') when '-f' is one of the options.
|
20
|
+
unknown << arg_list.delete('-ff') if arg_list.include?('-ff')
|
21
|
+
parser.parse!(arg_list)
|
22
|
+
rescue OptionParser::InvalidOption => e
|
23
|
+
unknown.concat(e.args)
|
24
|
+
while !arg_list.empty? && arg_list.first[0] != "-"
|
25
|
+
unknown << arg_list.shift
|
26
|
+
end
|
27
|
+
recursive_parse.call(arg_list)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
recursive_parse.call(args.dup)
|
31
|
+
unknown
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a list of options with unknown options removed
|
35
|
+
def self.known_options(parser, args)
|
36
|
+
unknown = unknown_options(parser, args)
|
37
|
+
args.reject { |arg| unknown.include?(arg) }
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class PullRequest < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git pull-request"
|
8
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
9
|
+
puts opts.to_s; exit 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the URL for a new pull request.
|
15
|
+
def new_pr_url
|
16
|
+
if service == 'stash' && protocol == 'ssh'
|
17
|
+
pattern = /(.*)@([^:]*):?([^\/]*)\/([^\/]*)\/(.*)\.git/
|
18
|
+
replacement = 'https://\2/projects/\4/repos/\5/pull-requests?create&sourceBranch=' +
|
19
|
+
current_branch
|
20
|
+
elsif service == 'stash' && protocol == 'http'
|
21
|
+
pattern = /(.*)@([^:\/]*)(:?[^\/]*)\/(.*)scm\/([^\/]*)\/(.*)\.git/
|
22
|
+
replacement = 'https://\2\3/\4projects/\5/repos/\6/pull-requests?create&sourceBranch=' +
|
23
|
+
current_branch
|
24
|
+
elsif service == 'github' && protocol == 'ssh'
|
25
|
+
pattern = /(.*)@(.*):(.*)\.git/
|
26
|
+
replacement = 'https://\2/\3/pull/new/' + current_branch
|
27
|
+
elsif service == 'github' && protocol == 'http'
|
28
|
+
pattern = /https?\:\/\/(([^@]*)@)?(.*)\.git/
|
29
|
+
replacement = 'https://\3/pull/new/' + current_branch
|
30
|
+
elsif service == 'bitbucket' && protocol == 'ssh'
|
31
|
+
pattern = /(.*)@(.*):(.*)\.git/
|
32
|
+
replacement = 'https://\2/\3/pull-request/new/'
|
33
|
+
elsif service == 'bitbucket' && protocol == 'http'
|
34
|
+
pattern = /https?\:\/\/(([^@]*)@)?(.*)\.git/
|
35
|
+
replacement = 'https://\3/pull-request/new/'
|
36
|
+
end
|
37
|
+
origin_url.sub(pattern, replacement)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a command appropriate for executing at the command line
|
41
|
+
def cmd
|
42
|
+
c = ["open #{new_pr_url}"]
|
43
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
44
|
+
c.join("\n")
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class PushBranch < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git push-branch"
|
8
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
9
|
+
puts opts.to_s; exit 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns a command appropriate for executing at the command line
|
15
|
+
def cmd
|
16
|
+
c = ["git push origin #{current_branch}"]
|
17
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
18
|
+
c.join("\n")
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class Switch < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git switch <pattern>"
|
8
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
9
|
+
puts opts.to_s; exit 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the branch to switch to.
|
15
|
+
def other_branch
|
16
|
+
@other_branch ||= `git branch | grep #{pattern}`.strip
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a command appropriate for executing at the command line
|
20
|
+
def cmd
|
21
|
+
c = ["git checkout #{other_branch}"]
|
22
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
23
|
+
c.join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Returns the pattern of the branch to switch to.
|
29
|
+
def pattern
|
30
|
+
self.known_options.first
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'git-utils/command'
|
2
|
+
|
3
|
+
class Sync < Command
|
4
|
+
|
5
|
+
def parser
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: git sync"
|
8
|
+
opts.on_tail("-h", "--help", "this usage guide") do
|
9
|
+
puts opts.to_s; exit 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns a command appropriate for executing at the command line
|
15
|
+
def cmd
|
16
|
+
c = ["git checkout master"]
|
17
|
+
c << "git pull"
|
18
|
+
c << "git checkout #{current_branch}"
|
19
|
+
c << argument_string(unknown_options) unless unknown_options.empty?
|
20
|
+
c.join("\n")
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DeleteRemoteBranch do
|
4
|
+
|
5
|
+
let(:command) { DeleteRemoteBranch.new(['remote_branch']) }
|
6
|
+
before do
|
7
|
+
command.stub(:current_branch).and_return('test-br')
|
8
|
+
command.stub(:delete_safely?).and_return(true)
|
9
|
+
end
|
10
|
+
subject { command }
|
11
|
+
|
12
|
+
its(:cmd) { should match /git push origin :remote_branch/ }
|
13
|
+
|
14
|
+
describe "command-line command" do
|
15
|
+
subject { `bin/git-delete-remote-branch foobar -o --debug` }
|
16
|
+
it { should match /git push origin/ }
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MergeBranch do
|
4
|
+
|
5
|
+
let(:command) { MergeBranch.new }
|
6
|
+
before { command.stub(:current_branch).and_return('tau-manifesto') }
|
7
|
+
subject { command }
|
8
|
+
|
9
|
+
its(:cmd) { should match /git merge/ }
|
10
|
+
|
11
|
+
shared_examples "merge-branch with known options" do
|
12
|
+
subject { command }
|
13
|
+
it "should not raise an error" do
|
14
|
+
expect { command.parse }.not_to raise_error(OptionParser::InvalidOption)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "with no options" do
|
19
|
+
its(:cmd) { should match /git checkout master/ }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "with a custom development branch" do
|
23
|
+
let(:command) { MergeBranch.new(['development']) }
|
24
|
+
its(:cmd) { should match /git checkout development/ }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "with some unknown options" do
|
28
|
+
let(:command) { MergeBranch.new(['dev', '-o', '-a', '-z', '--foo']) }
|
29
|
+
it_should_behave_like "merge-branch with known options"
|
30
|
+
its(:cmd) { should match /-a -z --foo/ }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "command-line command" do
|
34
|
+
subject { `bin/git-merge-branch --debug development` }
|
35
|
+
it { should match /git checkout development/ }
|
36
|
+
it { should match /git merge --no-ff --log/ }
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Open do
|
4
|
+
|
5
|
+
let(:command) { Open.new }
|
6
|
+
before do
|
7
|
+
command.stub(:current_branch).and_return('test-br')
|
8
|
+
end
|
9
|
+
subject { command }
|
10
|
+
|
11
|
+
its(:cmd) { should match /open #{command.page_url}/ }
|
12
|
+
|
13
|
+
it "should have the right page URLs" do
|
14
|
+
urls = %w[
|
15
|
+
https://mwatson@bitbucket.org/atlassian/amps.git https://bitbucket.org/atlassian/amps
|
16
|
+
git@bitbucket.org:atlassian/amps.git https://bitbucket.org/atlassian/amps
|
17
|
+
git@github.com:mhartl/git-utils.git https://github.com/mhartl/git-utils
|
18
|
+
https://github.com/mhartl/git-utils.git https://github.com/mhartl/git-utils
|
19
|
+
ssh://git@stash.atlassian.com:7999/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/browse?at=test-br
|
20
|
+
https://mwatson@stash.atlassian.com:7990/scm/stash/stash.git https://stash.atlassian.com:7990/projects/stash/repos/stash/browse?at=test-br
|
21
|
+
ssh://git@stash.atlassian.com/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/browse?at=test-br
|
22
|
+
https://mwatson@stash.atlassian.com/scm/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/browse?at=test-br
|
23
|
+
https://mwatson@stash.atlassian.com/stash/scm/stash/stash.git https://stash.atlassian.com/stash/projects/stash/repos/stash/browse?at=test-br
|
24
|
+
https://mwatson@stash.atlassian.com:7990/stash/scm/stash/stash.git https://stash.atlassian.com:7990/stash/projects/stash/repos/stash/browse?at=test-br
|
25
|
+
https://example.com/repos/foobar.git https://example.com/repos/foobar
|
26
|
+
]
|
27
|
+
urls.each_slice(2) do |origin_url, page_url|
|
28
|
+
command.stub(:origin_url).and_return(origin_url)
|
29
|
+
expect(command.page_url).to include page_url
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "command-line command" do
|
34
|
+
subject { `bin/git-open --debug` }
|
35
|
+
it { should match /open/ }
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PullRequest do
|
4
|
+
|
5
|
+
let(:command) { PullRequest.new }
|
6
|
+
before do
|
7
|
+
command.stub(:current_branch).and_return('test-br')
|
8
|
+
end
|
9
|
+
subject { command }
|
10
|
+
|
11
|
+
its(:cmd) { should match /open #{command.new_pr_url}/ }
|
12
|
+
|
13
|
+
it "should have the right pull request URLs" do
|
14
|
+
urls = %w[
|
15
|
+
https://mwatson@bitbucket.org/atlassian/amps.git https://bitbucket.org/atlassian/amps/pull-request/new
|
16
|
+
git@bitbucket.org:atlassian/amps.git https://bitbucket.org/atlassian/amps/pull-request/new
|
17
|
+
git@github.com:mhartl/git-utils.git https://github.com/mhartl/git-utils/pull/new/test-br
|
18
|
+
https://github.com/mhartl/git-utils.git https://github.com/mhartl/git-utils/pull/new/test-br
|
19
|
+
ssh://git@stash.atlassian.com:7999/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/pull-requests?create&sourceBranch=test-br
|
20
|
+
https://mwatson@stash.atlassian.com:7990/scm/stash/stash.git https://stash.atlassian.com:7990/projects/stash/repos/stash/pull-requests?create&sourceBranch=test-br
|
21
|
+
ssh://git@stash.atlassian.com/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/pull-requests?create&sourceBranch=test-br
|
22
|
+
https://mwatson@stash.atlassian.com/scm/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/pull-requests?create&sourceBranch=test-br
|
23
|
+
https://mwatson@stash.atlassian.com/stash/scm/stash/stash.git https://stash.atlassian.com/stash/projects/stash/repos/stash/pull-requests?create&sourceBranch=test-br
|
24
|
+
https://mwatson@stash.atlassian.com:7990/stash/scm/stash/stash.git https://stash.atlassian.com:7990/stash/projects/stash/repos/stash/pull-requests?create&sourceBranch=test-br
|
25
|
+
]
|
26
|
+
|
27
|
+
urls.each_slice(2) do |origin_url, new_pr_url|
|
28
|
+
command.stub(:origin_url).and_return(origin_url)
|
29
|
+
expect(command.new_pr_url).to include new_pr_url
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
describe "command-line command" do
|
35
|
+
subject { `bin/git-pull-request --debug` }
|
36
|
+
it { should match /open/ }
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PushBranch do
|
4
|
+
|
5
|
+
let(:command) { PushBranch.new(['remote_branch']) }
|
6
|
+
before do
|
7
|
+
command.stub(:current_branch).and_return('test-br')
|
8
|
+
end
|
9
|
+
subject { command }
|
10
|
+
|
11
|
+
its(:cmd) { should match /git push origin #{command.current_branch}/ }
|
12
|
+
|
13
|
+
describe "command-line command" do
|
14
|
+
subject { `bin/git-push-branch --debug` }
|
15
|
+
it { should match /git push origin/ }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Switch do
|
4
|
+
|
5
|
+
let(:command) { Switch.new(['other-branch']) }
|
6
|
+
before do
|
7
|
+
command.stub(:current_branch).and_return('test-br')
|
8
|
+
command.stub(:other_branch).and_return('other-branch')
|
9
|
+
end
|
10
|
+
subject { command }
|
11
|
+
|
12
|
+
its(:cmd) { should match /git checkout #{command.other_branch}/ }
|
13
|
+
|
14
|
+
describe "command-line command" do
|
15
|
+
subject { `bin/git-push-branch --debug` }
|
16
|
+
it { should match /git push origin/ }
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sync do
|
4
|
+
|
5
|
+
let(:command) { Sync.new }
|
6
|
+
before do
|
7
|
+
command.stub(:current_branch).and_return('test-br')
|
8
|
+
end
|
9
|
+
subject { command }
|
10
|
+
|
11
|
+
its(:cmd) { should match /git checkout master/ }
|
12
|
+
its(:cmd) { should match /git pull/ }
|
13
|
+
its(:cmd) { should match /git checkout #{command.current_branch}/ }
|
14
|
+
|
15
|
+
describe "command-line command" do
|
16
|
+
subject { `bin/git-sync --debug` }
|
17
|
+
it { should match /git checkout master/ }
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'git-utils'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
5
|
+
config.run_all_when_everything_filtered = true
|
6
|
+
config.filter_run :focus
|
7
|
+
|
8
|
+
# Disallow the old-style 'object.should' syntax.
|
9
|
+
config.expect_with :rspec do |c|
|
10
|
+
c.syntax = :expect
|
11
|
+
end
|
12
|
+
end
|
data/test-open-pr.sh
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
git init test-repo >/dev/null
|
4
|
+
cd test-repo
|
5
|
+
git checkout -b test-br 2>/dev/null
|
6
|
+
touch foo
|
7
|
+
git add foo
|
8
|
+
git commit -m "foo" >/dev/null
|
9
|
+
cat > open <<EOF
|
10
|
+
#!/usr/bin/env ruby
|
11
|
+
|
12
|
+
echo \$*
|
13
|
+
EOF
|
14
|
+
chmod +x open
|
15
|
+
cat > git-push-branch <<EOF
|
16
|
+
#!/usr/bin/env ruby
|
17
|
+
EOF
|
18
|
+
chmod +x git-push-branch
|
19
|
+
export PATH=`pwd`:$PATH
|
20
|
+
git remote add origin foo
|
21
|
+
|
22
|
+
test_open () {
|
23
|
+
REMOTE=$1
|
24
|
+
EXPECTED=$2
|
25
|
+
git remote set-url origin $REMOTE
|
26
|
+
RESULT=`../git-open`
|
27
|
+
if [ "$RESULT" = "$EXPECTED" ]
|
28
|
+
then
|
29
|
+
echo "passed: open $REMOTE"
|
30
|
+
else
|
31
|
+
echo "FAILED: open: Expected $EXPECTED (for origin $REMOTE) but got $RESULT"
|
32
|
+
fi
|
33
|
+
}
|
34
|
+
|
35
|
+
test_open https://mwatson@bitbucket.org/atlassian/amps.git https://bitbucket.org/atlassian/amps
|
36
|
+
test_open git@bitbucket.org:atlassian/amps.git https://bitbucket.org/atlassian/amps
|
37
|
+
test_open git@github.com:mhartl/git-utils.git https://github.com/mhartl/git-utils
|
38
|
+
test_open https://github.com/mhartl/git-utils.git https://github.com/mhartl/git-utils
|
39
|
+
test_open ssh://git@stash.atlassian.com:7999/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/browse?at=test-br
|
40
|
+
test_open https://mwatson@stash.atlassian.com:7990/scm/stash/stash.git https://stash.atlassian.com:7990/projects/stash/repos/stash/browse?at=test-br
|
41
|
+
test_open ssh://git@stash.atlassian.com/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/browse?at=test-br
|
42
|
+
test_open https://mwatson@stash.atlassian.com/scm/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/browse?at=test-br
|
43
|
+
test_open https://mwatson@stash.atlassian.com/stash/scm/stash/stash.git https://stash.atlassian.com/stash/projects/stash/repos/stash/browse?at=test-br
|
44
|
+
test_open https://mwatson@stash.atlassian.com:7990/stash/scm/stash/stash.git https://stash.atlassian.com:7990/stash/projects/stash/repos/stash/browse?at=test-br
|
45
|
+
|
46
|
+
test_pr () {
|
47
|
+
REMOTE=$1
|
48
|
+
EXPECTED=$2
|
49
|
+
git remote set-url origin $REMOTE
|
50
|
+
RESULT=`../git-pull-request`
|
51
|
+
if [ "$RESULT" = "$EXPECTED" ]
|
52
|
+
then
|
53
|
+
echo "passed: pull-request $REMOTE"
|
54
|
+
else
|
55
|
+
echo "FAILED: pull-request: Expected $EXPECTED (for origin $REMOTE) but got $RESULT"
|
56
|
+
fi
|
57
|
+
}
|
58
|
+
|
59
|
+
test_pr https://mwatson@bitbucket.org/atlassian/amps.git https://bitbucket.org/atlassian/amps/pull-request/new
|
60
|
+
test_pr git@bitbucket.org:atlassian/amps.git https://bitbucket.org/atlassian/amps/pull-request/new
|
61
|
+
test_pr git@github.com:mhartl/git-utils.git https://github.com/mhartl/git-utils/pull/new/test-br
|
62
|
+
test_pr https://github.com/mhartl/git-utils.git https://github.com/mhartl/git-utils/pull/new/test-br
|
63
|
+
test_pr ssh://git@stash.atlassian.com:7999/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/pull-requests?create\&sourceBranch=test-br
|
64
|
+
test_pr https://mwatson@stash.atlassian.com:7990/scm/stash/stash.git https://stash.atlassian.com:7990/projects/stash/repos/stash/pull-requests?create\&sourceBranch=test-br
|
65
|
+
test_pr ssh://git@stash.atlassian.com/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/pull-requests?create\&sourceBranch=test-br
|
66
|
+
test_pr https://mwatson@stash.atlassian.com/scm/stash/stash.git https://stash.atlassian.com/projects/stash/repos/stash/pull-requests?create\&sourceBranch=test-br
|
67
|
+
test_pr https://mwatson@stash.atlassian.com/stash/scm/stash/stash.git https://stash.atlassian.com/stash/projects/stash/repos/stash/pull-requests?create\&sourceBranch=test-br
|
68
|
+
test_pr https://mwatson@stash.atlassian.com:7990/stash/scm/stash/stash.git https://stash.atlassian.com:7990/stash/projects/stash/repos/stash/pull-requests?create\&sourceBranch=test-br
|
69
|
+
|
70
|
+
cd ..
|
71
|
+
rm -rf test-repo
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-utils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Hartl
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-19 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Add some Git utilities
|
14
|
+
email:
|
15
|
+
- michael@michaelhartl.com
|
16
|
+
executables:
|
17
|
+
- git-amend
|
18
|
+
- git-anal
|
19
|
+
- git-cleanup
|
20
|
+
- git-delete-remote-branch
|
21
|
+
- git-merge-branch
|
22
|
+
- git-open
|
23
|
+
- git-polish
|
24
|
+
- git-pull-request
|
25
|
+
- git-push-branch
|
26
|
+
- git-switch
|
27
|
+
- git-sync
|
28
|
+
- git-undo
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- .DS_Store
|
33
|
+
- .gitignore
|
34
|
+
- .project_id
|
35
|
+
- .rspec
|
36
|
+
- .ruby-gemset
|
37
|
+
- .ruby-version
|
38
|
+
- Gemfile
|
39
|
+
- Gemfile.lock
|
40
|
+
- LICENSE.txt
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- bin/git-amend
|
44
|
+
- bin/git-anal
|
45
|
+
- bin/git-cleanup
|
46
|
+
- bin/git-delete-remote-branch
|
47
|
+
- bin/git-merge-branch
|
48
|
+
- bin/git-open
|
49
|
+
- bin/git-polish
|
50
|
+
- bin/git-pull-request
|
51
|
+
- bin/git-push-branch
|
52
|
+
- bin/git-switch
|
53
|
+
- bin/git-sync
|
54
|
+
- bin/git-undo
|
55
|
+
- git-utils.gemspec
|
56
|
+
- lib/git-utils.rb
|
57
|
+
- lib/git-utils/command.rb
|
58
|
+
- lib/git-utils/delete_remote_branch.rb
|
59
|
+
- lib/git-utils/merge_branch.rb
|
60
|
+
- lib/git-utils/open.rb
|
61
|
+
- lib/git-utils/options.rb
|
62
|
+
- lib/git-utils/pull_request.rb
|
63
|
+
- lib/git-utils/push_branch.rb
|
64
|
+
- lib/git-utils/switch.rb
|
65
|
+
- lib/git-utils/sync.rb
|
66
|
+
- lib/git-utils/version.rb
|
67
|
+
- spec/.DS_Store
|
68
|
+
- spec/commands/.DS_Store
|
69
|
+
- spec/commands/command_spec.rb
|
70
|
+
- spec/commands/delete_remote_branch_spec.rb
|
71
|
+
- spec/commands/merge_branch_spec.rb
|
72
|
+
- spec/commands/open_spec.rb
|
73
|
+
- spec/commands/pull_request_spec.rb
|
74
|
+
- spec/commands/push_branch_spec.rb
|
75
|
+
- spec/commands/switch_spec.rb
|
76
|
+
- spec/commands/sync_spec.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
- test-open-pr.sh
|
79
|
+
homepage: https://github.com/mhartl/git-utils
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.0.3
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: See the README for full documentation
|
103
|
+
test_files:
|
104
|
+
- spec/.DS_Store
|
105
|
+
- spec/commands/.DS_Store
|
106
|
+
- spec/commands/command_spec.rb
|
107
|
+
- spec/commands/delete_remote_branch_spec.rb
|
108
|
+
- spec/commands/merge_branch_spec.rb
|
109
|
+
- spec/commands/open_spec.rb
|
110
|
+
- spec/commands/pull_request_spec.rb
|
111
|
+
- spec/commands/push_branch_spec.rb
|
112
|
+
- spec/commands/switch_spec.rb
|
113
|
+
- spec/commands/sync_spec.rb
|
114
|
+
- spec/spec_helper.rb
|