1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
|
Ways to contribute to Rubinius
=================================
We appreciate every contribution from the community, whether it is a clever
patch with killing feature, bug report, documentation patch, idea for project website,
promotion or donation.
Contributing is easy, it's like an interesting adventure:
* Get on [mailing list](http://groups.google.com/group/rubinius-dev), or join [our community](http://rubini.us/community) other ways.
* Start [investigating the code base](http://rubinius.lighthouseapp.com/projects/5089/getting-started), write a documentation patch.
* Explore and [use Rubinius](http://rubinius.lighthouseapp.com/projects/5089/common-build-problems-and-solutions), [report problems](http://rubinius.lighthouseapp.com/projects/5089/howto-write-a-ticket) you encounter.
* Start [writing specs](http://rubinius.lighthouseapp.com/projects/5089/howto-write-a-spec) for either [Rubinius VM](http://rubinius.lighthouseapp.com/projects/5089/shotgun-the-rubinius-virtual-machine) or the Ruby language. Note that there is [The Ruby Spec](http://spec.ruby-doc.org/wiki/Main_Page) project may be helpful and use your help.
* [Work on implementation](http://rubinius.lighthouseapp.com/projects/5089/coding-style-guide) to make your specs pass.
* Double check and [watch for CI](http://rubinius.lighthouseapp.com/projects/5089/specs-continuous-integration) staying green.
* We are now one step closer to next generation Ruby virtual machine making goods for the mankind.
Now let's have a closer look at each step.
Development: flowing commit bit
===================================
Rubinius has commit rights policy known as FCB (flowing commit bit) from day one. Evan given commit rights to every developer who's patch
got into Rubinius without questions asked, etc. If you patch is applied, you get commit rights right away. That's the way we do it.
Helping out on mailing list and IRC
======================================
Main tool for communication of Rubinius developers is historically IRC. People ask questions and send patches to mailing list too, though.
If you are just starting with Rubinius you may ask for help, help others and get some insight in group archives. If you have problems, please
clarify what OS and architecture you use, what exactly you do and what exactly error message you get. Given this someone will definitely come
and help you.
If they don't, maybe it is time to grab some coffee and submit a patch. This happens in open source software.
Documentation
==================
As with any documentation, there are no many guidelines you should follow. Two of them are
* keep things well-organized
* make things clear for both novices and experienced gurus
This is it.
Writing specs
==================
Overview
--------------------------------
The Rubinius project uses [BDD](http://en.wikipedia.org/wiki/Behavior_driven_development)-style executable specifications to drive development. The specs are intended to be syntax-compatible with [RSpec](http://rspec.rubyforge.org/). However, RSpec liberally uses advanced Ruby language features that are difficult to support while a Ruby implementation is being developed. Hence, Rubinius uses a custom implementation to run the spec files.
RSpec is essentially a DSL (domain-specific language) for describing the behavior of code. The specs serve two purposes: 1) to drive development, and 2) as a verification mechanism. These goal can sometimes be at odds. During development, the code and specs evolve together. For verification, a highly stable set of specs that ideally have been audited for correctness is desirable.
Rubinius is attempting to write a standard set of Ruby specs based on the behavior of MRI (Matz's Ruby Interpreter) at roughly version 1.8.6. One of the significant challenges is the variations in the existing Ruby implementations. For example, JRuby does not have Kernel.fork. Rubinius has the Tuple class, which is not a standard part of the Ruby core library. The specs need to accommodate the compliant and non-compliant behavior of the various implementations. RSpec itself is a fairly young project. So, Rubinius defines several extensions (that are compatible with RSpec) to control execution of the specs based on the implementation that is executing them.
Organization
--------------------------------
There are many conceivable ways to organize the spec files. A graphical representation of the Rubinius directories is shown below. This structure is based on the Ruby language as well as the major components of a Ruby implementation. The goal is to maintain locality by grouping related specs.
There are two primary divisions of the specs in the spec directory: 1. specs for the Ruby language, which includes the Ruby core and standard libraries; 2. specs for the Rubinius system and its extensions to the Ruby core and standard libraries.
<pre>
spec
|-- compiler
|-- core
| +-- array
| +-- bignum
| +-- breakpoint
| +-- bytearray
| +-- ...
|-- data
|-- kernel
|-- language
|-- library
|-- parser
|-- ruby
| +-- 1.8
| +-- core
| + -- array
| + -- bignum
| + -- binding
| + -- class
| + -- ...
| + -- time
| + -- true
| + -- unboundmethod
| +-- fixtures
| +-- language
| +-- library
| + -- enumerator
| + -- ...
| + -- time
| + -- yaml
+-- subtend
+-- ext
</pre>
The reference implementation of the Ruby language
----------------------------------------------------
The specs for the reference implementation of the Ruby language (MRI) are under spec/ruby. Presently, these are only focused on **version 1.8.x** and there is only the 1.8 subdirectory. However, as specs are written for version 1.9, those specs will be placed in a parallel tree under the 1.9 subdirectory. In the spec files under **spec/ruby**, there are also specs for other Ruby implementations where these implementations comply with or deviate from MRI (again, the reference implementation for Ruby).
All the spec directories except for spec/ruby are for Rubinius specific code. Under spec/core, spec/language, and spec/libraries, there are specs for how Rubinius extends or significantly deviates from MRI.
In general, there is no goal to unify spec/core, spec/language, and spec/libraries with the parallel directories under spec/ruby/. These directories serve different purposes.
The language directory contains specs for the Ruby language proper. There are numerous possible way of categorizing the entities and concepts that make up a programming language. Ruby has a fairly large number of reserved words. These words significantly describe major elements of the language, including flow control constructs like "for" and "while", conditional execution like "if" and "unless", exceptional execution control like "rescue", etc. There are also literals for the basic "types" like String, Regexp, Array and Fixnum.
Behavioral specifications describe the behavior of concrete entities. Rather than using concepts of computation to organize these spec files, we use entities of the Ruby language. Consider looking at any syntactic element of a Ruby program. With (almost) no ambiguity, one can identify it as a literal, reserved word, variable, etc. There is a spec file that corresponds to each literal construct and most reserved words, with the exceptions noted below. There are also several files that are more difficult to classify: all predefined variables, constants, and objects (predefined\_spec.rb), the precedence of all operators (precedence\_spec.rb), the behavior of assignment to variables (variables\_spec.rb), the behavior of subprocess execution (execution\_spec.rb), the behavior of the raise method as it impacts the execution of a Ruby program (raise\_spec.rb), and the block entities like "begin", "do", " { ... }" (block\_spec.rb).
Several reserved words and other entities are combined with the primary reserved word or entity to which they are related:
# predefined\_spec.rb: false, true, nil, self
# for\_spec.rb: in
# if\_spec.rb: then, elsif
# case\_spec.rb: when
# throw\_spec.rb: catch
Core library
--------------------
The core directory contains specs for the Ruby core library. These include classes such as Array, String, Regexp, Range, Fixnum, Float, etc. The core directory contains a subdirectory named after the classes in the core library. For example, specs for the Array class are in the array directory. Within each subdirectory of @core@, the specs for each method of that class are placed in a separate file. For example, specs for Array#compact are places in spec/core/array/compact\_spec.rb. Method names with characters like "?", "=", and "!" are in files named by stripping those characters. For example, specs for Array#compact! are in the same file as specs for Array#compact. All the spec files that are needed have already likely been created. (See bin/mkspec for details.)
Standard library
The library directory contains specs for the classes of the Ruby standard library. The same naming convention used in the core directory applies here, also. However, there are some legacy specs that do not yet conform to this convention.
Rubinius extensions
The spec/core , spec/language , and spec/library directories are for extensions to the Ruby core, language, and standard libraries respectively.
Rubinius components
* The compiler directory contains specs related to the compiler tool chain.
* The parser directory contains specs for the parser.
* The subtend directory contains specs for the Rubinius C API that is header file compatible with the MRI C API.
Spec runners
----------------------
There are three runners for the the Rubinius specs: **mspec**, **ci**, and **completeness**. The completeness runner uses **mspec**. See Continuous Integration section about usage for ci.
The mspec command accepts a file, directory, or shell glob to specify which spec files to execute.
<pre>
$ bin/mspec -h
mspec [options] (FILE|DIRECTORY|GLOB)+
-f, --format FORMAT Formatter for reporting: s:specdox|d:dotted|c:ci|h:html|i:immediate
-t, --target TARGET Implementation that will run the specs: r:ruby|r19:ruby19|x:rbx|j:jruby
-T, --targetopt OPT Pass OPT as a flag to the target implementation
-I, --include DIR Pass DIR through as the -I option to the target
-r, --require LIBRARY Pass LIBRARY through as the -r option to the target
-n, --name RUBY_NAME Override the name used to determine the implementation
-o, --output FILE Formatter output will be sent to FILE
-e STRING|FILE Execute example(s) with descriptions matching STRING or each line of FILE
--example
-x STRING|FILE Exclude example(s) with descriptions matching STRING or each line of FILE
--exclude
-C, --clean Remove all compiled spec files first
-V, --verbose Output the name of each file processed
-m, --marker MARKER Outout MARKER for each file processed. Overrides -V
-w, --warnings Don't supress warnings
-g, --gdb Run under gdb
-A, --valgrind Run under valgrind
-v, --version Show version
-h, --help Show this message
-f, --format FORMAT
Selects the reporter format to output specs strings and failures. The specdox report is very similar to RSpec's -f s option. The dotted reporter outputs the familiar '....F..EF..'' with exceptions listed after all specs are run. The ci reporter will only output the describe + it string for specs that fail. The immediate reporter outputs spec strings before the spec is executed so that if the VM exits due to an exception, the cause of the exception is more easily determined.
-t, --target TARGET
Selects the Ruby implementation to be used to execute the spec files.
-T, --targetopt OPT
Passes OPT as a flag to the target implementation, For example, bin/mspec -T "-d" -t r would pass the debug flag to ruby.
-I, --include DIR
Passes this option directly to the selected target (see -t).
-r, --require LIBRARY
Passes this option directly to the selected target (see -t).
-n, --name RUBY_NAME
Overrides the name used to determine the Ruby implementation. RUBY_NAME defaults to require 'rbconfig'; Config::CONFIG["RUBY_INSTALL_NAME"] if this executes without exception.
-o, --output FILE
Specifies the file that the reporter will write to. Defaults to STDOUT.
-e, --example STRING|FILE
Executes only the specs whose describe + it message string matches STRING. If a file name is given, each line of the file is equivalent to -e STRING.
-x, --exclude STRING|FILE
Does not execute any spec whose describe + it message string matches STRING. If a file name is given, each line of the file is equivalent to -x STRING.
-C, --clean
Deletes the compiled spec files for any spec files that will be executed before running the specs.
-V, --verbose
Outputs the name of each file processed
-m, --marker MARKER
Outouts MARKER for each file processed. Overrides -V.
-w, --warnings
Don't supress warnings from the target (see -t).
-g, --gdb
Only useful with Rubinius. Passes the --gdb argument to shotgun to launch gdb.
-A, --valgrind
Only useful with Rubinius on a platform with Valgrind installed. Passes the --valgrind option to shotgun to run under Valgrind.
Completeness Reporter
</pre>
The completeness script is useful for several tasks. Using -t ruby, the script can be used to show how complete the specs are in terms of the coverage of the Ruby core library. Note that this is not anything like the rcov tool. The completeness script merely uses some naming conventions in the spec strings to run specs for class and instance methods of classes and modules whose names are accessible as constants on Object.
When writing specs, you should use the completeness script to determine which class or module the specs should be written for. This is especially important for Kernel and Object. Most methods that one associates with being on an instance of Object are actually defined in the Kernel module. The specs for these need to be added to spec/core/kernel_spec.rb.
<pre>
n$ bin/completeness -h
completeness [options]
-r, --require LIBRARY Name of library to require
-c, --constant CONSTANT Name of a Class or Module
-b, --base BASE Set base directory to BASE
-t, --target TARGET Implementation to test for completeness: r:ruby|r19:ruby19|x:rbx|j:jruby
-x STRING|FILE Exclude example(s) with descriptions matching STRING or each line of FILE
--exclude
-F, --report-failures Report spec failure locations
-o, --color Use colors green=NoFailures yellow=WithFailures red=NoExamples
-V, --verbose Show mspec command being executed
-q, --quiet Suppress output except for final summary
-v, --version Show version
-h, --help Show this message
-r, --require LIBRARY
Specifies the name of the library to require.
-c, --constant CONSTANT
Specifies the name of a constant for which to run specs.
-b, --base BASE
Set base directory to BASE. The base directory is treated as the root directory of the spec directories tree.
-t, --target TARGET
Selects the Ruby implementation to be used to execute the spec files.
-x, --exclude STRING|FILE
Does not execute any spec whose describe + it message string matches STRING. If a file name is given, each line of the file is equivalent to -x STRING.
-F, --report-failures
Normally, the script does not output any failure messages or backtraces. Use this option to report spec failures.
-o, --color
Colorize the output using green for no failures, yellow for failures, and red for no examples found.
-V, --verbose
Print out the mspec command that is being executed for each method.
-q, --quiet
Do not output information for each method. Only output the final summary.</pre>
Examples of spec runners
--------------
For example, to determine what is the public interface of Digest::MD5, run the following:
<pre>bin/completeness -t ruby -r'digest/md5' -c Digest::MD5</pre>
Continuous integration in Rubinius
-------------------------------------
As Rubinius is undergoing continual development, and since TDD/BDD is the recommended way to develop new features, Rubinius does not pass all the specs that have been written. Because of the same feature specific to virtual machine development Rubinius developers currently do not use dedicated CI server like [CruiseControl.rb](http://cruisecontrolrb.thoughtworks.com/). However, when making changes to the code, we need a way to confirm that working features are not inadvertently broken. Generally, some sort of continuous integration (CI) mechanism serves this purpose.
To meet this need, Rubinius has a special runner (bin/ci) that excludes the failing specs. Every developer who writes new specs must ensure that the CI specs are updated. If all the specs pass, bin/ci -f ci will output nothing. If any specs fail, the reporter will output the spec description string for the failing spec. To be more useful for developers, the default output formatter for bin/ci is DottedFormatter (see -f option below).
CI spec runner
-----------------------
The rake spec task prints our the revision of the VM build and then invokes the CI spec runner bin/ci. This command is documented below.
<pre>
$ bin/ci -h
ci [options] (FILE|DIRECTORY|GLOB)+
-c, --create Create the exclude file for failing specs
-R, --run Run the specs excluding the expected failures
-i, --invert Run the specs using only the expected failures
-t, --target TARGET Use TARGET to run the specs: r:ruby|r19:ruby19|x:rbx|j:jruby
-f, --format FORMAT Use FORMAT for reporting: s:specdox|d:dotted|c:CI|h:html|i:immediate
-E, --excludes-dir DIR Use DIR for the files containing spec descriptions to exclude
-I, --include DIR Pass DIR through as the -I option to the target
-r, --require LIBRARY Pass LIBRARY through as the -r option to the target
-n, --name RUBY_NAME Override the name used to determine the implementation
-T, --targetopt OPT Pass OPT as a flag to the target implementation
-C, --clean Remove all compiled spec files first
-V, --verbose Output the name of each file processed
-m, --marker MARKER Output MARKER for each file processed. Overrides -V
-g, --gdb Run under gdb
-A, --valgrind Run under valgrind
-v, --version Show version
-h, --help Show this message
The bin/ci command accepts a file, directory, or shell glob to specify which spec files to execute. The default set of spec files are those that have been determined to not cause the VM to raise an unhandled exception. For the purpose of simply running all CI specs, just use bin/ci.
-c, --create
Creates the the spec exclude files for each spec file. The exclude file is spec/core/class/.spec/method_excludes.txt. Use this option to update the spec excludes when adding new specs that pass on MRI but fail on Rubinius. Also use this to update the spec excludes for any particular specs that you have made to pass on Rubinius.
-R, --run
Executes all the specs except those listed in spec/excludes.txt and the exclude file for each spec file. This is the default action if nothing is specified. Equivalent to bin/ci.
-i, --invert
Executes all the specs that match each line of spec/excludes.txt or each line of the exclude file for each spec file. This is the simplest way to determine if specs that were failing now pass. The default reporter is changed to DottedReporter.
-t, --target TARGET
Selects the Ruby implementation to be used to execute the spec files.
-f, --format FORMAT
Selects the reporter to be used for showing the output from executing the specs.
-E, --excludes-dir DIR
Uses DIR for the files containing spec descriptions to exclude. This option overrides the CI_EXCLUDES_DIR constant. If the path is absolute (i.e. starts with '/'), the excludes directories are created in the specified directory. Otherwise, the exclude directories are created relative to the directories containing the spec files. The default exclude directory is '.spec'.
-I, --include DIR
Passes DIR through as the -I option to the target (see -t).
-r, --require LIBRARY
Passes LIBRARY through as the -r option to the target (see -t).
-n, --name RUBY_NAME
Overrides the name used to determine the Ruby implementation. RUBY_NAME defaults to require 'rbconfig'; Config::CONFIG["RUBY_INSTALL_NAME"] if this executes without exception.
-T, --targetopt OPT
Passes OPT as a flag to the target implementation (see -t).
-C, --clean
Deletes the compiled version of any spec files that will be executed. Does not delete any compiled version for any spec files that would not be executed.
-V, --verbose
Prints to STDERR each spec file that is being executed.
-m, --marker MARKER
Output MARKER for each file processed. Overrides -V
-g, --gdb
Only useful with Rubinius. Passes the --gdb argument to shotgun to launch gdb.
-A, --valgrind
Only useful with Rubinius on a platform with Valgrind installed. Passes the --valgrind option to shotgun to run under Valgrind.
</pre>
CI excludes
--------------
The spec/data directory contains a tree of directories that parallels all the spec directories. In this directory, files named *\_excludes.txt list spec description strings for specs that should be excluded by the CI spec runner.
Howto fix a failing spec
------------------------------
Here's the general procedure to fix a spec that is failing on Rubinius.
# Run the spec with bin/mspec spec/core/class/method_spec.rb
# Write the Rubinius code to make the spec pass
# Run the spec again to ensure it passes
# Run the CI specs with bin/ci to ensure you have not broken something else
# If you get CI spec failures, run bin/ci spec/core/whatever to ensure that the failures are not resulting from interaction with other code
# Update the CI excludes for the spec that you fixed with bin/ci -c spec/core/class/method_spec.rb
# Format your patch with git format-patch and create a ticket (or commit if you have a bit).
Development
==================
Using Git distributed version control system
---------------------------------------------------
The Rubinius project is using the Git SCM. Committers need to use git to commit their code directly to the main repo. Below is information on getting Git installed, getting source code with Git, and steps for working with Git. Also, see these references:
* [Git crash course](http://git.or.cz/course/svn.html) for SVN users
* [Git tutorial](http://www.kernel.org/pub/software/scm/git/docs/tutorial.html)
* [Everyday Git](http://www.kernel.org/pub/software/scm/git/docs/everyday.html) with 20 commands or so
The following manuals are more advanced but very recommended because Git is truly advanced and has a lot to offer to it's users:
* [Git user manual](http://www.kernel.org/pub/software/scm/git/docs/user-manual.html)
* [Branching and merging with Git](http://lwn.net/Articles/210045/) (extremely recommended)
* Git local/following/remote/tracking branches [terminology confusion discussion](http://kerneltrap.org/mailarchive/git/2007/8/4/253944)
* [Complete Git reference](http://www.kernel.org/pub/software/scm/git/docs/)
Getting Git for Your System
----------------------------------
You can use an earlier version, but 1.5.x is definitely recommended.
* MacPorts has 'git-core' port
* Debian and Ubuntu has 'git-core' package
* FreeBSD has 'devel/git' port (there are some issues with 1.5.3.2 version in ports so you may it easier to compile Git from source)
* Get the source at http://git.or.cz/ and compile it as usual, Git dependencies are very friendly compared to ImageMagick.
Development environment setup
------------------------------------
Configure Git with your proper name and email. This will display when you submit changes to the Rubinius repository.
<pre>
git config --global user.name "My Name"
git config --global user.email "my@email"
</pre>
If you prefer to use different credentials for different projects, you can also configure the above for a single repository only. See the git documentation.
Formatting Git commit messages
-----------------------------------
In general, use an editor to create your commit messages rather than passing them on the command line. The format should be:
* A hard wrap at 72 characters
* A single, short, summary of the commit
* Followed by a single blank line
* Followed by supporting details
The supporting details could be a bulleted enumeration or an explanatory paragraph. The single summary line helps folks reviewing commits. An example commit:
Fixes for Module#make\_my\_day return values.
* Return nil when passed ':('
* Return true when passed ':)'
* Updated specs for #make_my_day for nil argument case
* Updated CI excludes.
Getting the code
--------------------
If you are an existing committer, see below instead.
Getting the code is easy once you have git installed:
<pre>git clone git://git.rubini.us/code</pre>
(Your local directory will be called code. You can give a different name by appending it to the command above.)
Commit rights and process for existing committers
------------------------------------------------------
If you are an existing committer, you can get setup to commit to the Rubinius git repository. Paste your ssh public key (~/.ssh/id_rsa.pub) into pastie.caboo.se and give Evan the URL.
To get the code:
<pre>git clone git@git.rubini.us:code</pre>
(Your local directory will be called code. You can give a different name by appending it to the command above.)
New committers
-------------------
If you do not have commit rights yet, you can create patch files with Git. The instructions for this are after the Git workflow section.
Git workflow
-------------------
Working with [Git](http://git.or.cz) is significantly different that working with SVN. In particular, although similar, git pull is not svn update, git push is not svn commit, and git add is not svn add. If you are a SVN user, be sure to read the man pages for the different git commands.
The following workflow is recommended by Evan and is the guideline for contributing code to Rubinius.
<pre>
1. Create a local working copy of the source code (we did this earlier.)
git clone git://git.rubini.us:code
2. Change to the newly created directory that contains the local working copy.
cd code
3. Create a branch for your work. What happens is that your working directory
git checkout -b new_feature
4. Edit the code and test your changes. Then commit to your local working copy
git commit -a
5. When you are ready to send your local changes back to the Rubinius repository, you first need to ensure that your local copy is up-to-date. First, ensure you have committed your local changes. Then switch from your topic branch to the master branch.
git checkout master
6. Update your local copy with changes from the Rubinius repository
git pull
7. Switch back to your topic branch and integrate any new changes. The git rebase command will save your changes away, update the topic branch, and then reapply them.
git checkout new_feature
git rebase master
Warning! If you are sharing a branch, you must use:
git merge master
Rebase causes the commit layout to change and will confuse anyone you've shared this branch with.
8. If you there are conflicts applying your changes during the git rebase command, fix them and use the following to finish applying them
git rebase --continue
9. Now, switch back to the master branch and merge your changes from the topic branch
git checkout master
git merge new_feature
10. You might want to check that your commits ended up as you intended. To do so, you can have a look at the log
git log
11. Get your changes in the main repository. If you have commit rights, you can just use the git push command. Otherwise, see the section below for information on creating a set of patches to send.
git push
12. At this point, you can delete the branch if you like.
git branch -d new_feature
</pre>
Patches: git-format-patch
------------------------------
If you are a new committer (or want to create a patch instead of directly pushing the code for some other reason) you should create a patch file for your commits. The patch file should be then attached to a ticket on Lighthouse (see the ticket writing howto for instructions for more details on that.) You can also send the patch to the mailing list but use the ticket tracker if at all possible. Either way, the patch file(s) should be created using Git.
First, make your changes as detailed below and then use the git format-patch command to create the patch files. Usually using the command is as simple as specifying the commits you want to create patches for, and that is done in one of two ways: by giving a range of commits or a starting point. As mentioned earlier, each commit is identified by a unique hash ID which you can see, for example, by looking at the git log output. You can generally shorten it -- first 8 should be plenty -- because it is unlikely to conflict (if it does, just use the full ID instead.) In my examples below I just use imaginary IDs. Let us say you created three commits, in this order my1stcom -> my2ndcom -> my3rdcom (and that the patch before those is notmycom):
* Specify a range of revisions. You can use the syntax git format-patch my1stcom..my3rdcom to include the first, the last and any inbetween. Alternatively, you could use git format-patch my1stcom..HEAD and other variants instead.
* Specify a single revision. This takes all patches following the one given. The only possibly unintuitive part here is that the revision you give is the last patch you do not want to include. For example, if you do git format-patch my3rdcom or git format-patch HEAD there will be no patches since there have been none since. In our case, you would want one of the following: git format-patch notmycom , git format-patch my1stcom^ , git format-patch HEAD^^^ or git format-patch HEAD~3 (or any of the other possible variations.)
(In Git terminology, HEAD is the last commit in your current branch. Parent patches can be referenced either by using a caret so that HEAD^ is one before HEAD and HEAD^^ is one before one before (i.e. two before) HEAD which gets cumbersome after the second or third caret; or by tilde-number: HEAD~1 is one before HEAD, HEAD~5 is five before HEAD and much easier to use. The caret and tilde can be used for commit hashes as well. For other variants, see the git-rev-parse man page.)
Whichever way you decide on, a separate patch file is produced for each, named [number]-[first line of commit message].patch. You can then attach these to a ticket (or e-mail them.)
The process and Rake git tasks
------------------------------------------------
The above workflow has been wrapped up into a some rake tasks. The simplified version is:
Create a branch for your work:
<pre>rake git:topic</pre>
Make your changes and commit as needed:
<pre>git commit -a</pre>
Push your changes to master branch:
<pre>rake git:push</pre>
|