hub 1.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of hub might be problematic. Click here for more details.

@@ -0,0 +1,159 @@
1
+ module Hub
2
+ # Provides methods for inspecting the environment, such as GitHub user/token
3
+ # settings, repository info, and similar.
4
+ module Context
5
+ private
6
+
7
+ # Caches output when shelling out to git
8
+ GIT_CONFIG = Hash.new do |cache, cmd|
9
+ result = %x{git #{cmd}}.chomp
10
+ cache[cmd] = $?.success? && !result.empty? ? result : nil
11
+ end
12
+
13
+ # Parses URLs for git remotes and stores info
14
+ REMOTES = Hash.new do |cache, remote|
15
+ if remote
16
+ urls = GIT_CONFIG["config --get-all remote.#{remote}.url"].to_s.split("\n")
17
+
18
+ if urls.find { |u| u =~ %r{\bgithub\.com[:/](.+)/(.+).git$} }
19
+ cache[remote] = { :user => $1, :repo => $2 }
20
+ else
21
+ cache[remote] = { }
22
+ end
23
+ else
24
+ cache[remote] = { }
25
+ end
26
+ end
27
+
28
+ LGHCONF = "http://github.com/guides/local-github-config"
29
+
30
+ def repo_owner
31
+ REMOTES[default_remote][:user]
32
+ end
33
+
34
+ def repo_user
35
+ REMOTES[current_remote][:user]
36
+ end
37
+
38
+ def repo_name
39
+ REMOTES[default_remote][:repo] || current_dirname
40
+ end
41
+
42
+ # Either returns the GitHub user as set by git-config(1) or aborts
43
+ # with an error message.
44
+ def github_user(fatal = true)
45
+ if user = ENV['GITHUB_USER'] || GIT_CONFIG['config github.user']
46
+ user
47
+ elsif fatal
48
+ abort("** No GitHub user set. See #{LGHCONF}")
49
+ end
50
+ end
51
+
52
+ def github_token(fatal = true)
53
+ if token = ENV['GITHUB_TOKEN'] || GIT_CONFIG['config github.token']
54
+ token
55
+ elsif fatal
56
+ abort("** No GitHub token set. See #{LGHCONF}")
57
+ end
58
+ end
59
+
60
+ def current_branch
61
+ GIT_CONFIG['symbolic-ref -q HEAD']
62
+ end
63
+
64
+ def tracked_branch
65
+ branch = current_branch && tracked_for(current_branch)
66
+ normalize_branch(branch) if branch
67
+ end
68
+
69
+ def remotes
70
+ list = GIT_CONFIG['remote'].to_s.split("\n")
71
+ main = list.delete('origin') and list.unshift(main)
72
+ list
73
+ end
74
+
75
+ def remotes_group(name)
76
+ GIT_CONFIG["config remotes.#{name}"]
77
+ end
78
+
79
+ def current_remote
80
+ return if remotes.empty?
81
+
82
+ if current_branch
83
+ remote_for(current_branch)
84
+ else
85
+ default_remote
86
+ end
87
+ end
88
+
89
+ def default_remote
90
+ remotes.first
91
+ end
92
+
93
+ def normalize_branch(branch)
94
+ branch.sub('refs/heads/', '')
95
+ end
96
+
97
+ def remote_for(branch)
98
+ GIT_CONFIG['config branch.%s.remote' % normalize_branch(branch)]
99
+ end
100
+
101
+ def tracked_for(branch)
102
+ GIT_CONFIG['config branch.%s.merge' % normalize_branch(branch)]
103
+ end
104
+
105
+ def http_clone?
106
+ GIT_CONFIG['config --bool hub.http-clone'] == 'true'
107
+ end
108
+
109
+ def git_alias_for(name)
110
+ GIT_CONFIG["config alias.#{name}"]
111
+ end
112
+
113
+ # Core.repositoryformatversion should exist for all git
114
+ # repositories, and be blank for all non-git repositories. If
115
+ # there's a better config setting to check here, this can be
116
+ # changed without breaking anything.
117
+ def is_repo?
118
+ GIT_CONFIG['config core.repositoryformatversion']
119
+ end
120
+
121
+ def github_url(options = {})
122
+ repo = options[:repo]
123
+ user, repo = repo.split('/') if repo && repo.index('/')
124
+ user ||= options[:user] || github_user
125
+ repo ||= repo_name
126
+ secure = options[:private]
127
+
128
+ if options[:web]
129
+ scheme = secure ? 'https:' : 'http:'
130
+ path = options[:web] == true ? '' : options[:web].to_s
131
+ if repo =~ /\.wiki$/
132
+ repo = repo.sub(/\.wiki$/, '')
133
+ unless '/wiki' == path
134
+ path = '/wiki%s' % if path =~ %r{^/commits/} then '/_history'
135
+ else path.sub(/\w+/, '_\0')
136
+ end
137
+ end
138
+ end
139
+ '%s//github.com/%s/%s%s' % [scheme, user, repo, path]
140
+ else
141
+ if secure
142
+ url = 'git@github.com:%s/%s.git'
143
+ elsif http_clone?
144
+ url = 'http://github.com/%s/%s.git'
145
+ else
146
+ url = 'git://github.com/%s/%s.git'
147
+ end
148
+
149
+ url % [user, repo]
150
+ end
151
+ end
152
+
153
+ DIRNAME = File.basename(Dir.pwd)
154
+
155
+ def current_dirname
156
+ DIRNAME
157
+ end
158
+ end
159
+ end
data/lib/hub/runner.rb ADDED
@@ -0,0 +1,71 @@
1
+ module Hub
2
+ # The Hub runner expects to be initialized with `ARGV` and primarily
3
+ # exists to run a git command.
4
+ #
5
+ # The actual functionality, that is, the code it runs when it needs to
6
+ # augment a git command, is kept in the `Hub::Commands` module.
7
+ class Runner
8
+ attr_reader :args
9
+
10
+ def initialize(*args)
11
+ @args = Args.new(args)
12
+ Commands.run(@args)
13
+ end
14
+
15
+ # Shortcut
16
+ def self.execute(*args)
17
+ new(*args).execute
18
+ end
19
+
20
+ # A string representation of the command that would run.
21
+ def command
22
+ if args.skip?
23
+ ''
24
+ else
25
+ commands.join('; ')
26
+ end
27
+ end
28
+
29
+ # An array of all commands as strings.
30
+ def commands
31
+ args.commands.map do |cmd|
32
+ if cmd.respond_to?(:join)
33
+ # a simplified `Shellwords.join` but it's OK since this is only used to inspect
34
+ cmd.map { |c| (c.index(' ') || c.empty?) ? "'#{c}'" : c }.join(' ')
35
+ else
36
+ cmd.to_s
37
+ end
38
+ end
39
+ end
40
+
41
+ # Runs the target git command with an optional callback. Replaces
42
+ # the current process.
43
+ #
44
+ # If `args` is empty, this will skip calling the git command. This
45
+ # allows commands to print an error message and cancel their own
46
+ # execution if they don't make sense.
47
+ def execute
48
+ unless args.skip?
49
+ if args.chained?
50
+ execute_command_chain
51
+ else
52
+ exec(*args.to_exec)
53
+ end
54
+ end
55
+ end
56
+
57
+ # Runs multiple commands in succession; exits at first failure.
58
+ def execute_command_chain
59
+ commands = args.commands
60
+ commands.each_with_index do |cmd, i|
61
+ if cmd.respond_to?(:call) then cmd.call
62
+ elsif i == commands.length - 1
63
+ # last command in chain
64
+ exec(*cmd)
65
+ else
66
+ exit($?.exitstatus) unless system(*cmd)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,52 @@
1
+ module Hub
2
+ module Standalone
3
+ extend self
4
+
5
+ PREAMBLE = <<-preamble
6
+ #!/usr/bin/env ruby
7
+ #
8
+ # This file, hub, is generated code.
9
+ # Please DO NOT EDIT or send patches for it.
10
+ #
11
+ # Please take a look at the source from
12
+ # http://github.com/defunkt/hub
13
+ # and submit patches against the individual files
14
+ # that build hub.
15
+ #
16
+
17
+ preamble
18
+
19
+ POSTAMBLE = "Hub::Runner.execute(*ARGV)\n"
20
+ __DIR__ = File.dirname(__FILE__)
21
+ MANPAGE = "__END__\n#{File.read(__DIR__ + '/../../man/hub.1')}"
22
+
23
+ def save(filename, path = '.')
24
+ target = File.join(File.expand_path(path), filename)
25
+ File.open(target, 'w') do |f|
26
+ f.puts build
27
+ f.chmod 0755
28
+ end
29
+ end
30
+
31
+ def build
32
+ root = File.dirname(__FILE__)
33
+
34
+ standalone = ''
35
+ standalone << PREAMBLE
36
+
37
+ Dir["#{root}/*.rb"].each do |file|
38
+ # skip standalone.rb
39
+ next if file == __FILE__
40
+
41
+ File.readlines(file).each do |line|
42
+ next if line =~ /^\s*#/
43
+ standalone << line
44
+ end
45
+ end
46
+
47
+ standalone << POSTAMBLE
48
+ standalone << MANPAGE
49
+ standalone
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Hub
2
+ Version = VERSION = '1.6.0'
3
+ end
data/man/hub.1 ADDED
@@ -0,0 +1,356 @@
1
+ .\" generated with Ronn/v0.7.3
2
+ .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
+ .
4
+ .TH "HUB" "1" "December 2010" "DEFUNKT" "Git Manual"
5
+ .
6
+ .SH "NAME"
7
+ \fBhub\fR \- git + hub = github
8
+ .
9
+ .SH "SYNOPSIS"
10
+ \fBhub\fR \fICOMMAND\fR \fIOPTIONS\fR
11
+ .
12
+ .br
13
+ \fBhub alias\fR [\fB\-s\fR] \fISHELL\fR
14
+ .
15
+ .P
16
+ \fBgit init \-g\fR \fIOPTIONS\fR
17
+ .
18
+ .br
19
+ \fBgit create\fR [\fB\-p\fR] [\fB\-d <DESCRIPTION>\fR] [\fB\-h <HOMEPAGE>\fR]
20
+ .
21
+ .br
22
+ \fBgit clone\fR [\fB\-p\fR] \fIOPTIONS\fR [\fIUSER\fR/]\fIREPOSITORY\fR \fIDIRECTORY\fR
23
+ .
24
+ .br
25
+ \fBgit remote add\fR [\fB\-p\fR] \fIOPTIONS\fR \fIUSER\fR[/\fIREPOSITORY\fR]
26
+ .
27
+ .br
28
+ \fBgit remote set\-url\fR [\fB\-p\fR] \fIOPTIONS\fR \fIREMOTE\-NAME\fR \fIUSER\fR[/\fIREPOSITORY\fR]
29
+ .
30
+ .br
31
+ \fBgit fetch\fR \fIUSER\-1\fR,[\fIUSER\-2\fR,\.\.\.]
32
+ .
33
+ .br
34
+ \fBgit cherry\-pick\fR \fIGITHUB\-REF\fR
35
+ .
36
+ .br
37
+ \fBgit am\fR \fIGITHUB\-URL\fR
38
+ .
39
+ .br
40
+ \fBgit push\fR \fIREMOTE\-1\fR,\fIREMOTE\-2\fR,\.\.\.,\fIREMOTE\-N\fR \fIREF\fR
41
+ .
42
+ .br
43
+ \fBgit browse\fR [\fB\-u\fR] [[\fIUSER\fR\fB/\fR]\fIREPOSITORY\fR] [SUBPAGE]
44
+ .
45
+ .br
46
+ \fBgit compare\fR [\fB\-u\fR] [\fIUSER\fR] [\fISTART\fR\.\.\.]\fIEND\fR
47
+ .
48
+ .br
49
+ \fBgit submodule add\fR [\fB\-p\fR] \fIOPTIONS\fR [\fIUSER\fR/]\fIREPOSITORY\fR \fIDIRECTORY\fR
50
+ .
51
+ .br
52
+ \fBgit fork\fR [\fB\-\-no\-remote\fR]
53
+ .
54
+ .SH "DESCRIPTION"
55
+ \fBhub\fR enhances various \fBgit\fR commands with GitHub remote expansion\. The alias command displays information on configuring your environment:
56
+ .
57
+ .IP "\(bu" 4
58
+ \fBhub alias\fR [\fB\-s\fR] \fISHELL\fR: Writes shell aliasing code for \fISHELL\fR (\fBbash\fR, \fBsh\fR, \fBzsh\fR, \fBcsh\fR) to standard output\. With the \fB\-s\fR option, the output of this command can be evaluated directly within the shell:
59
+ .
60
+ .br
61
+ \fBeval $(hub alias \-s bash)\fR
62
+ .
63
+ .IP "\(bu" 4
64
+ \fBgit init\fR \fB\-g\fR \fIOPTIONS\fR: Create a git repository as with git\-init(1) and add remote \fBorigin\fR at "git@github\.com:\fIUSER\fR/\fIREPOSITORY\fR\.git"; \fIUSER\fR is your GitHub username and \fIREPOSITORY\fR is the current working directory\'s basename\.
65
+ .
66
+ .IP "\(bu" 4
67
+ \fBgit create\fR [\fB\-p\fR] [\fB\-d <DESCRIPTION>\fR] [\fB\-h <HOMEPAGE>\fR]:
68
+ .
69
+ .br
70
+ Create a new public github repository from the current git repository and add remote \fBorigin\fR at "git@github\.com:\fIUSER\fR/\fIREPOSITORY\fR\.git"; \fIUSER\fR is your GitHub username and \fIREPOSITORY\fR is the current working directory\'s basename\. With \fB\-p\fR, create a private repository\. \fB\-d\fR and \fB\-h\fR set the repository\'s description and homepage, respectively\.
71
+ .
72
+ .IP "\(bu" 4
73
+ \fBgit clone\fR [\fB\-p\fR] \fIOPTIONS\fR [\fIUSER\fR\fB/\fR]\fIREPOSITORY\fR \fIDIRECTORY\fR:
74
+ .
75
+ .br
76
+ Clone repository "git://github\.com/\fIUSER\fR/\fIREPOSITORY\fR\.git" into \fIDIRECTORY\fR as with git\-clone(1)\. When \fIUSER\fR/ is omitted, assumes your GitHub login\. With \fB\-p\fR, use private remote "git@github\.com:\fIUSER\fR/\fIREPOSITORY\fR\.git"\.
77
+ .
78
+ .IP "\(bu" 4
79
+ \fBgit remote add\fR [\fB\-p\fR] \fIOPTIONS\fR \fIUSER\fR[\fB/\fR\fIREPOSITORY\fR]:
80
+ .
81
+ .br
82
+ Add remote "git://github\.com/\fIUSER\fR/\fIREPOSITORY\fR\.git" as with git\-remote(1)\. When /\fIREPOSITORY\fR is omitted, the basename of the current working directory is used\. With \fB\-p\fR, use private remote "git@github\.com:\fIUSER\fR/\fIREPOSITORY\fR\.git"\. If \fIUSER\fR is "origin" then uses your GitHub login\.
83
+ .
84
+ .IP "\(bu" 4
85
+ \fBgit remote set\-url\fR [\fB\-p\fR] \fIOPTIONS\fR \fIREMOTE\-NAME\fR \fIUSER\fR[/\fIREPOSITORY\fR]
86
+ .
87
+ .br
88
+ Sets the url of remote \fIREMOTE\-NAME\fR using the same rules as \fBgit remote add\fR\.
89
+ .
90
+ .IP "\(bu" 4
91
+ \fBgit fetch\fR \fIUSER\-1\fR,[\fIUSER\-2\fR,\.\.\.]: Adds missing remote(s) with \fBgit remote add\fR prior to fetching\. New remotes are only added if they correspond to valid forks on GitHub\.
92
+ .
93
+ .IP "\(bu" 4
94
+ \fBgit cherry\-pick\fR \fIGITHUB\-REF\fR: Cherry\-pick a commit from a fork using either full URL to the commit or GitHub\-flavored Markdown notation, which is \fBuser@sha\fR\. If the remote doesn\'t yet exist, it will be added\. A \fBgit fetch <user>\fR is issued prior to the cherry\-pick attempt\.
95
+ .
96
+ .IP "\(bu" 4
97
+ \fBgit am\fR \fIGITHUB\-URL\fR: Downloads the patch file for the pull request or commit at the URL and applies that patch from disk with \fBgit am\fR\. Similar to \fBcherry\-pick\fR, but doesn\'t add new remotes\.
98
+ .
99
+ .IP "\(bu" 4
100
+ \fBgit push\fR \fIREMOTE\-1\fR,\fIREMOTE\-2\fR,\.\.\.,\fIREMOTE\-N\fR \fIREF\fR: Push \fIREF\fR to each of \fIREMOTE\-1\fR through \fIREMOTE\-N\fR by executing multiple \fBgit push\fR commands\.
101
+ .
102
+ .IP "\(bu" 4
103
+ \fBgit browse\fR [\fB\-u\fR] [[\fIUSER\fR\fB/\fR]\fIREPOSITORY\fR] [SUBPAGE]: Open repository\'s GitHub page in the system\'s default web browser using \fBopen(1)\fR or the \fBBROWSER\fR env variable\. If the repository isn\'t specified, \fBbrowse\fR opens the page of the repository found in the current directory\. If SUBPAGE is specified, the browser will open on the specified subpage: one of "wiki", "commits", "issues" or other (the default is "tree")\.
104
+ .
105
+ .IP "\(bu" 4
106
+ \fBgit compare\fR [\fB\-u\fR] [\fIUSER\fR] [\fISTART\fR\.\.\.]\fIEND\fR: Open a GitHub compare view page in the system\'s default web browser\. \fISTART\fR to \fIEND\fR are branch names, tag names, or commit SHA1s specifying the range of history to compare\. If \fISTART\fR is omitted, GitHub will compare against the base branch (the default is "master")\.
107
+ .
108
+ .IP "\(bu" 4
109
+ \fBgit submodule add\fR [\fB\-p\fR] \fIOPTIONS\fR [\fIUSER\fR/]\fIREPOSITORY\fR \fIDIRECTORY\fR:
110
+ .
111
+ .br
112
+ Submodule repository "git://github\.com/\fIUSER\fR/\fIREPOSITORY\fR\.git" into \fIDIRECTORY\fR as with git\-submodule(1)\. When \fIUSER\fR/ is omitted, assumes your GitHub login\. With \fB\-p\fR, use private remote "git@github\.com:\fIUSER\fR/\fIREPOSITORY\fR\.git"\.
113
+ .
114
+ .IP "\(bu" 4
115
+ \fBgit fork\fR [\fB\-\-no\-remote\fR]: Forks the original project (referenced by "origin" remote) on GitHub and adds a new remote for it under your username\. Requires \fBgithub\.token\fR to be set (see CONFIGURATION)\.
116
+ .
117
+ .IP "\(bu" 4
118
+ \fBgit help\fR: Display enhanced git\-help(1)\.
119
+ .
120
+ .IP "" 0
121
+ .
122
+ .SH "CONFIGURATION"
123
+ Use git\-config(1) to display the currently configured GitHub username:
124
+ .
125
+ .IP "" 4
126
+ .
127
+ .nf
128
+
129
+ $ git config \-\-global github\.user
130
+ .
131
+ .fi
132
+ .
133
+ .IP "" 0
134
+ .
135
+ .P
136
+ Or, set the GitHub username and token with:
137
+ .
138
+ .IP "" 4
139
+ .
140
+ .nf
141
+
142
+ $ git config \-\-global github\.user <username>
143
+ $ git config \-\-global github\.token <token>
144
+ .
145
+ .fi
146
+ .
147
+ .IP "" 0
148
+ .
149
+ .P
150
+ See \fIhttp://github\.com/guides/local\-github\-config\fR for more information\.
151
+ .
152
+ .P
153
+ You can also tell \fBhub\fR to use \fBhttp://\fR rather than \fBgit://\fR when cloning:
154
+ .
155
+ .IP "" 4
156
+ .
157
+ .nf
158
+
159
+ $ git config \-\-global \-\-bool hub\.http\-clone true
160
+ .
161
+ .fi
162
+ .
163
+ .IP "" 0
164
+ .
165
+ .P
166
+ Want to use environment variables instead of a local gitconfig for authentication?
167
+ .
168
+ .IP "\(bu" 4
169
+ \fBGITHUB_USER\fR \- If set, this will be used instead of the \fBgithub\.user\fR config
170
+ .
171
+ .IP "\(bu" 4
172
+ \fBGITHUB_TOKEN\fR \- If set, this will be used instead of the \fBgithub\.token\fR
173
+ .
174
+ .IP "" 0
175
+ .
176
+ .SH "EXAMPLES"
177
+ .
178
+ .SS "git clone"
179
+ .
180
+ .nf
181
+
182
+ $ git clone schacon/ticgit
183
+ > git clone git://github\.com/schacon/ticgit\.git
184
+
185
+ $ git clone \-p schacon/ticgit
186
+ > git clone git@github\.com:schacon/ticgit\.git
187
+
188
+ $ git clone resque
189
+ > git clone git://github\.com/YOUR_USER/resque\.git
190
+
191
+ $ git clone \-p resque
192
+ > git clone git@github\.com:YOUR_USER/resque\.git
193
+ .
194
+ .fi
195
+ .
196
+ .SS "git remote add"
197
+ .
198
+ .nf
199
+
200
+ $ git remote add rtomayko
201
+ > git remote add rtomayko git://github\.com/rtomayko/CURRENT_REPO\.git
202
+
203
+ $ git remote add \-p rtomayko
204
+ > git remote add rtomayko git@github\.com:rtomayko/CURRENT_REPO\.git
205
+
206
+ $ git remote add origin
207
+ > git remote add origin git://github\.com/YOUR_USER/CURRENT_REPO\.git
208
+ .
209
+ .fi
210
+ .
211
+ .SS "git fetch"
212
+ .
213
+ .nf
214
+
215
+ $ git fetch mislav
216
+ > git remote add mislav git://github\.com/mislav/REPO\.git
217
+ > git fetch mislav
218
+
219
+ $ git fetch mislav,xoebus
220
+ > git remote add mislav \.\.\.
221
+ > git remote add xoebus \.\.\.
222
+ > git fetch \-\-multiple mislav xoebus
223
+ .
224
+ .fi
225
+ .
226
+ .SS "git cherry\-pick"
227
+ .
228
+ .nf
229
+
230
+ $ git cherry\-pick http://github\.com/mislav/REPO/commit/SHA
231
+ > git remote add \-f mislav git://github\.com/mislav/REPO\.git
232
+ > git cherry\-pick SHA
233
+
234
+ $ git cherry\-pick mislav@SHA
235
+ > git remote add \-f mislav git://github\.com/mislav/CURRENT_REPO\.git
236
+ > git cherry\-pick SHA
237
+
238
+ $ git cherry\-pick mislav@SHA
239
+ > git fetch mislav
240
+ > git cherry\-pick SHA
241
+ .
242
+ .fi
243
+ .
244
+ .SS "git am"
245
+ .
246
+ .nf
247
+
248
+ $ git am https://github\.com/defunkt/hub/pull/55
249
+ > curl https://github\.com/defunkt/hub/pull/55\.patch \-o /tmp/55\.patch
250
+ > git am /tmp/55\.patch
251
+
252
+ $ git am \-\-ignore\-whitespace https://github\.com/davidbalbert/hub/commit/fdb9921
253
+ > curl https://github\.com/davidbalbert/hub/commit/fdb9921\.patch \-o /tmp/fdb9921\.patch
254
+ > git am \-\-ignore\-whitespace /tmp/fdb9921\.patch
255
+ .
256
+ .fi
257
+ .
258
+ .SS "git fork"
259
+ .
260
+ .nf
261
+
262
+ $ git fork
263
+ \.\.\. hardcore forking action \.\.\.
264
+ > git remote add YOUR_USER git@github\.com:YOUR_USER/CURRENT_REPO\.git
265
+ .
266
+ .fi
267
+ .
268
+ .SS "git init"
269
+ .
270
+ .nf
271
+
272
+ $ git init \-g
273
+ > git init
274
+ > git remote add origin git@github\.com:YOUR_USER/REPO\.git
275
+ .
276
+ .fi
277
+ .
278
+ .SS "git create"
279
+ .
280
+ .nf
281
+
282
+ $ git create
283
+ \.\.\. hardcore creating action \.\.\.
284
+ > git remote add origin git@github\.com:YOUR_USER/CURRENT_REPO\.git
285
+ .
286
+ .fi
287
+ .
288
+ .SS "git push"
289
+ .
290
+ .nf
291
+
292
+ $ git push origin,staging,qa bert_timeout
293
+ > git push origin bert_timeout
294
+ > git push staging bert_timeout
295
+ > git push qa bert_timeout
296
+ .
297
+ .fi
298
+ .
299
+ .SS "git browse"
300
+ .
301
+ .nf
302
+
303
+ $ git browse
304
+ > open https://github\.com/YOUR_USER/CURRENT_REPO
305
+
306
+ $ git browse \-\- issues
307
+ > open https://github\.com/YOUR_USER/CURRENT_REPO/issues
308
+
309
+ $ git browse schacon/ticgit
310
+ > open https://github\.com/schacon/ticgit
311
+
312
+ $ git browse resque
313
+ > open https://github\.com/YOUR_USER/resque
314
+
315
+ $ git browse resque network
316
+ > open https://github\.com/YOUR_USER/resque/network
317
+ .
318
+ .fi
319
+ .
320
+ .SS "git compare"
321
+ .
322
+ .nf
323
+
324
+ $ git compare refactor
325
+ > open https://github\.com/CURRENT_REPO/compare/refactor
326
+
327
+ $ git compare 1\.0\.\.\.1\.1
328
+ > open https://github\.com/CURRENT_REPO/compare/1\.0\.\.\.1\.1
329
+
330
+ $ git compare \-u fix
331
+ > (https://github\.com/CURRENT_REPO/compare/fix)
332
+
333
+ $ git compare other\-user patch
334
+ > open https://github\.com/other\-user/REPO/compare/patch
335
+ .
336
+ .fi
337
+ .
338
+ .SS "git help"
339
+ .
340
+ .nf
341
+
342
+ $ git help
343
+ > (improved git help)
344
+ $ git help hub
345
+ > (hub man page)
346
+ .
347
+ .fi
348
+ .
349
+ .SH "BUGS"
350
+ \fIhttp://github\.com/defunkt/hub/issues\fR
351
+ .
352
+ .SH "AUTHORS"
353
+ \fIhttps://github\.com/defunkt/hub/contributors\fR
354
+ .
355
+ .SH "SEE ALSO"
356
+ git(1), git\-clone(1), git\-remote(1), git\-init(1), \fIhttp://github\.com\fR, \fIhttp://github\.com/defunkt/hub\fR