ls: --color now highlights hard linked files, too
[coreutils/bo.git] / HACKING
blobb83565224cfbf5418d64b825bf07b08ce80856ae
1 Coreutils Contribution Guidelines
4 Prerequisites
5 =============
6 You will need the "git" version control tools.
7 On Fedora-based systems, do "yum install git".
8 On Debian-based ones install the "git-core" package.
9 Then run "git --version".  If that says it's older than
10 version 1.4.4, then you'd do well to get a newer version.
11 At worst, just download the latest stable release from
12 http://git.or.cz/ and build from source.
14 For details on building the programs in this package, see
15 the file, README-hacking.
18 Use the latest upstream sources
19 ===============================
20 Base any changes you make on the latest upstream sources.
21 You can get a copy of the latest with this command:
23     git clone git://git.sv.gnu.org/coreutils
25 That downloads the entire repository, including revision control history
26 dating back to 1991.  The repository (the part you download, and which
27 resides in coreutils/.git) currently weighs in at about 30MB.  So you
28 don't want to download it more often than necessary.  Once downloaded,
29 you can get incremental updates by running one of these commands from
30 inside your new coreutils/ directory:
32 If you have made *no* changes:
33     git pull
35 If you *have* made changes and committed them to "master", do this:
36     git fetch
37     git rebase origin
40 *Before* you commit changes
41 ===========================
43 In this project, we much prefer patches that automatically record
44 authorship.  That is important not just to give credit where due, but
45 also from a legal standpoint (see below).  To create author-annotated
46 patches with git, you must first tell git who you are.  That information
47 is best recorded in your ~/.gitconfig file.  Edit that file, creating
48 it if needed, and put your name and email address in place of these
49 example values:
51 [user]
52   name = Joe X. User
53   email = joe.user@example.com
56 Your first commit: the quick and dirty way
57 ==========================================
58 First of all, realize that to "commit" a change in git is a purely
59 local operation.  It affects only the local repository (the .git/ dir)
60 in your current coreutils/ hierarchy.
62 To try this out, modify a file or two.  If you create a new file, you'll
63 need to tell git about it with "git add new-file.c".  Commit all changes
64 with "git commit -a".  That prompts you for a log message, which should
65 include a one-line summary, a blank line, and ChangeLog-style entries
66 for all affected files.  More on that below.
68 Once your change is committed, you can create a proper patch that includes
69 a log message and authorship information as well as any permissions
70 changes.  Use this command to save that single, most-recent change set:
72   git format-patch --stdout -1 > DIFF
74 The trouble with this approach is that you've just checked in a change
75 (remember, it's only local) on the "master" branch, and that's where new
76 changes would normally appear when you pull the latest from "upstream".
77 When you "pull" from a remote repository to get the latest, your local
78 changes on "master" may well induce conflicts.   For this reason, you
79 may want to keep "master" free of any local changes, so that you can
80 use it to track unadulterated upstream sources.
82 However, if your cloned directory is for a one-shot patch submission and
83 you're going to remove it right afterwards, then this approach is fine.
84 Otherwise, for a more sustainable (and more generally useful, IMHO)
85 process, read on about "topic" branches.
88 Make your changes on a private "topic" branch
89 =============================================
90 So you checked out coreutils like this:
92   git clone git://git.sv.gnu.org/coreutils
94 Now, cd into the coreutils/ directory and run:
96   git checkout -b my-topic
98 That creates the my-topic branch and puts you on it.
99 To see which branch you're on, type "git branch".
100 Right after the clone, you were on "master" (aka the trunk).
101 To get back to the trunk, do this:
103   git checkout master
105 Note 1:
106     Be careful to run "git pull" only when on the "master" branch,
107     not when on a branch.  With newer versions of git, you can't cause
108     trouble if you forget, so this is a good reason to ensure you're
109     using 1.5.3.1 or newer.
111 Note 2:
112     It's best not to try to switch from one branch to another if
113     you have pending (uncommitted) changes.  Sometimes it works,
114     sometimes the checkout will fail, telling you that your local
115     modifications conflict with changes required to switch branches.
116     However, in any case, you will *not* lose your uncommitted changes.
118 Anyhow, get back onto your just-created branch:
120   git checkout my-topic
122 Now, modify some file and commit it:
124   git commit some-file.c
126 Personally, no matter what package I'm working on, I find it useful to
127 put the ChangeLog entries *only* in the commit log, initially, unless
128 I plan to commit/push right away.  Otherwise, I tend to get unnecessary
129 merge conflicts with each rebase (see below).  In coreutils, I've gone
130 a step further, and no longer maintain an explicit ChangeLog file in
131 version control.  Instead, in a git working directory, you can view
132 ChangeLog information via "git log".  However, each distribution tarball
133 does include a ChangeLog file that is automatically generated from the
134 git logs.
136 So, you've committed a change.  But it's only in your local repository,
137 and only on your "my-topic" branch.  Let's say you wait a day, and
138 then see that someone else changed something and pushed it to the
139 public repository.  Now, you want to update your trunk and "rebase"
140 your changes on the branch so that they are once again relative to the
141 tip of the trunk.  Currently, your branch is attached to the trunk at
142 the next-to-last change set.
144 First: update the trunk from the public repo:
145 [you've first made sure that "git diff" produces no output]
147   git checkout master
148   git pull
150 Now, return to your branch, and "rebase" relative to trunk (master):
152   git checkout my-topic
153   git rebase master
155 If there are no conflicts, this requires no more work from you.
156 However, let's say there was one in ChangeLog, since you didn't
157 follow my advice and modified it anyway.
158 git rebase will tell you there was a conflict and in which
159 file, and instruct you to resolve it and then resume with
160 "git rebase --continue" once that's done.
162 So you resolve as usual, by editing ChangeLog (which has the
163 usual conflict markers), then type "git rebase --continue".
164 That will fail, with a diagnostic telling you to mark
165 the file as "conflict resolved" by doing this:
167   git add ChangeLog
169 Then, finally, you can proceed (possibly onto more conflict resolution,
170 if there are conflicts in other files):
172   git rebase --continue
174 Once it finishes, your changes on the branch are now relative to
175 the tip of the trunk.
177 Now use git format-patch, as above.
180 Amending the most recent change on your private branch
181 ======================================================
182 Let's say you've just committed a change on your private
183 branch, and then realize that something about it is not right.
184 It's easy to adjust:
186   edit your files # this can include running "git add NEW" or "git rm BAD"
187   git commit --amend -e -a
188   git format-patch --stdout -1 > your-branch.diff
190 That replaces the most recent change-set with the revised one.
194 Coreutils-specific:
196 No more ChangeLog files
197 =======================
198 Do not modify any of the ChangeLog files in coreutils.  Starting in
199 2008, the policy changed.  Before, we would insert the exact same text
200 (or worse, sometimes slightly differing) into both the ChangeLog file
201 and the commit log.  Now we put that information only in the commit log,
202 and generate the top-level ChangeLog file from logs at "make dist" time.
203 As such, there are strict requirements on the form of the commit log
204 messages.
207 Commit log requirements
208 =======================
209 Your commit log should always start with a one-line summary, the second
210 line should be blank, and the remaining lines are usually ChangeLog-style
211 entries for all affected files.  Omit the leading TABs that you're used
212 to seeing in a "real" ChangeLog file.
214 Try to make the summary line fit one of the following forms:
216   program_name: change-description
217   prog1, prog2: change-description
218   doc: change-description
219   tests: change-description
222 Use SPACE-only indentation in new files.
223 ========================================
224 In any new file, eliminate all leading TABs (e.g., via running GNU indent
225 with --no-tabs) and put these lines at the end of the file:
226 [FIXME: suggest vim syntax to do same thing, if it can be done safely.
227  Most distros now "set nomodeline" by default for a good reason. ]
230  * Local variables:
231  * indent-tabs-mode: nil
232  * End:
233  */
235 Do not change TABs to spaces or vice versa in any existing file.
238 Send patches to the address listed in --help output
239 ===================================================
240 Please follow the guidelines in the "Sending your patches." section of
241 git's own SubmittingPatches:
243   http://git.kernel.org/?p=git/git.git;a=blob;f=Documentation/SubmittingPatches
246 Add documentation
247 =================
248 If you add a feature or change some user-visible aspect of a program,
249 document it.  If you add an option, document it both in --help output
250 (i.e., in the usage function that generates the --help output) and in
251 doc/*.texi.  The man pages are generated from --help output, so
252 you shouldn't need to change anything under man/.  User-visible changes
253 are usually documented in NEWS, too.
255 When writing prose (documentation, comments, log entries), use an
256 active voice, not a passive one.  I.e., say "print the frobnozzle",
257 not "the frobnozzle will be printed".
260 Minor syntactic preferences
261 ===========================
262 [I hesitate to write this one down, because it appears to be an
263  acquired taste, at least for native-English speakers.  It seems odd
264  (if not truly backwards) to nearly anyone who doesn't have a strong
265  mathematics background and perhaps a streak of something odd in their
266  character ;-) ]
267 In writing arithmetic comparisons, use "<" and "<=" rather than
268 ">" and ">=".  For some justification, read this:
269   http://thread.gmane.org/gmane.comp.version-control.git/3903/focus=4126
271 const placement:
272 Write "Type const *var", not "const Type *var".
273 FIXME: dig up justification
276 Be nice to translators
277 ======================
278 Don't change translatable strings if you can avoid it.
279 If you must rearrange individual lines (e.g., in multi-line --help
280 strings), extract and create new strings, rather than extracting
281 and moving into existing blocks.  This avoids making unnecessary
282 work for translators.
285 Add tests
286 ==========
287 Nearly every significant change must be accompanied by a test suite
288 addition that exercises it.  If you fix a bug, add at least one test that
289 fails without the patch, but that succeeds once your patch is applied.
290 If you add a feature, add tests to exercise as much of the new code
291 as possible.
293 There are hundreds of tests in the tests/ directories.  You can use
294 tests/sample-test as a template, or one of the various Perl-based ones
295 in tests/misc.
297 If writing tests is not your thing, don't worry too much about it,
298 but do provide scenarios, input/output pairs, or whatever, along with
299 examples of running the tool to demonstrate the new or changed feature,
300 and someone else will massage that into a test (writing portable tests
301 can be a challenge).
304 Copyright assignment
305 ====================
306 If your change is significant (i.e., if it adds more than ~10 lines),
307 then you'll have to have a copyright assignment on file with the FSF.
308 Since that involves first an email exchange between you and the FSF,
309 and then the exchange (FSF to you, then back) of an actual sheet of paper
310 with your signature on it, and finally, some administrative processing
311 in Boston, the process can take a few weeks.
313 The forms to choose from are in gnulib's doc/Copyright/ directory.
314 If you want to assign a single change, you should use the file,
315 doc/Copyright/request-assign.changes:
317     http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=doc/Copyright/request-assign.changes;hb=HEAD
319 If you would like to assign past and future contributions to a project,
320 you'd use doc/Copyright/request-assign.future:
322     http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=doc/Copyright/request-assign.future;hb=HEAD
324 You may make assignments for up to four projects at a time.
327 Run "make syntax-check", or even "make distcheck"
328 ================================================
329 Making either of those targets runs many integrity and
330 project-specific policy-conformance tests.  For example, the former
331 ensures that you add no trailing blanks and no uses of certain deprecated
332 functions.  The latter performs all "syntax-check" tests, and also
333 ensures that the build completes with no warnings when using a certain
334 set of gcc -W... options.  Don't even bother running "make distcheck"
335 unless you have a reasonably up to date installation including recent
336 versions of gcc and the linux kernel, and modern GNU tools.
339 Ensure that your changes are indented properly.
340 ===============================================
341 Format the code the way GNU indent does.
342 In a file with the "indent-tabs-mode: nil" directive at the end,
343 running "indent --no-tabs" should induce no change.
344 With other files, there will be some existing differences.
345 Try not to add any more.
348 -------------------------------------------
350 Miscellaneous useful git commands
351 =================================
353   * gitk: give a graphical view of the revision graph
354   * git log: to get most of the same info in text form
355   * git log -p: same as above, but with diffs
356   * git log -p SOME_FILE: same as above, but limit to SOME_FILE
357   * git reset --soft HEAD^: Commit the delta required to restore
358       state to the revision just before HEAD (i.e., next-to-last).
359   * git rebase -i master: run this from on a branch, and it gives
360       you an interface with which you can reorder and modify arbitrary
361       change sets on that branch.
363   * if you "misplace" a change set, i.e., via git reset --hard ..., so that
364     it's no longer reachable by any branch, you can use "git fsck" to find
365     its SHA1 and then tag it or cherry-pick it onto an existing branch.
366     For example, run this:
367       git fsck --lost-found HEAD && cd .git/lost-found/commit \
368         && for i in *; do git show $i|grep SOME_IDENTIFYING_STRING \
369         && echo $i; done
370     The "git fsck ..." command creates the .git/lost-found/... hierarchy
371     listing all unreachable objects.  Then the for loop
372     print SHA1s for commits that match via log or patch.
373     For example, say that found 556fbb57216b119155cdda824c98dc579b8121c8,
374     you could run "git show 556fbb57216b119" to examine the change set,
375     or "git checkout -b found 556fbb5721" to give it a branch name.
376     Finally, you might run "git checkout master && git cherry-pick 556fbb5721"
377     to put that change on the tip of "master".
379 -------------------------------------------
381 Finding things to do
382 ====================
383 If you don't know where to start, check out the TODO file for projects
384 that look like they're at your skill-/interest-level.  Another good
385 option is always to improve tests.  You never know what you might
386 uncover when you improve test coverage, and even if you don't find
387 any bugs your contribution is sure to be appreciated.
389 A good way to quickly assess current test coverage is to use "lcov"
390 to generate HTML coverage reports.  Follow these steps:
392   # configure with coverage information
393   ./configure CFLAGS="-g -fprofile-arcs -ftest-coverage"
394   make
395   # run whatever tests you want, i.e.:
396   make check
397   # run lcov
398   lcov -t coreutils -q -d lib -b lib -o lib.lcov -c
399   lcov -t coreutils -q -d src -b src -o src.lcov -c
400   # generate HTML from the output
401   genhtml -p `pwd` -t coreutils -q --output-directory lcov-html *.lcov
403 Then just open the index.html file (in the generated lcov-html directory)
404 in your favorite web browser.