doc: clarify a --help sentence
[grep.git] / HACKING
blob6b9b52a0929096dad774f21829fceb5a03327182
1 Grep Contribution Guidelines
4 Prerequisites
5 =============
6 For details on building the programs in this package, see
7 the file, README-hacking.
10 Use the latest upstream sources
11 ===============================
12 Base any changes you make on the latest upstream sources.
13 You can get a copy of the latest with this command:
15     git clone https://git.savannah.gnu.org/git/grep
17 That downloads the entire repository, including revision control history.
18 Once downloaded, you can get incremental updates by running one of
19 these commands from inside your new grep/ directory:
21 If you have made *no* changes:
22     git pull
24 If you *have* made changes and mistakenly committed them to "master",
25 do the following to put your changes on a private branch, "br", and
26 to restore master to its unmodified (relative-to-upstream) state:
27     git checkout -b br
28     git checkout master
29     git reset --hard origin
31 Then "git pull" should work.
34 *Before* you commit changes
35 ===========================
37 In this project, we much prefer patches that automatically record
38 authorship.  That is important not just to give credit where due, but
39 also from a legal standpoint (see below).  To create author-annotated
40 patches with git, you must first tell git who you are.  That information
41 is best recorded in your ~/.gitconfig file.  Edit that file, creating
42 it if needed, and put your name and email address in place of these
43 example values:
45 [user]
46   name = Joe X. User
47   email = joe.user@example.com
50 Your first commit: the quick and dirty way
51 ==========================================
52 First of all, realize that to "commit" a change in git is a purely
53 local operation.  It affects only the local repository (the .git/ dir)
54 in your current grep/ hierarchy.
56 To try this out, modify a file or two.  If you create a new file, you'll
57 need to tell git about it with "git add new-file.c".  Commit all changes
58 with "git commit -a".  That prompts you for a log message, which should
59 include a one-line summary, a blank line, and ChangeLog-style entries
60 for all affected files.  More on that below.
62 Once your change is committed, you can create a proper patch that includes
63 a log message and authorship information as well as any permissions
64 changes.  Use this command to save that single, most-recent change set:
66   git format-patch --stdout -1 > DIFF
68 The trouble with this approach is that you've just checked in a change
69 (remember, it's only local) on the "master" branch, and that's where new
70 changes would normally appear when you pull the latest from "upstream".
71 When you "pull" from a remote repository to get the latest, your local
72 changes on "master" may well induce conflicts.   For this reason, you
73 may want to keep "master" free of any local changes, so that you can
74 use it to track unadulterated upstream sources.
76 However, if your cloned directory is for a one-shot patch submission and
77 you're going to remove it right afterwards, then this approach is fine.
78 Otherwise, for a more sustainable (and more generally useful, IMHO)
79 process, read on about "topic" branches.
82 Make your changes on a private "topic" branch
83 =============================================
84 So you checked out grep like this:
86   git clone https://git.savannah.gnu.org/git/grep
88 Now, cd into the grep/ directory and run:
90   git checkout -b my-topic
92 That creates the my-topic branch and puts you on it.
93 To see which branch you're on, type "git branch".
94 Right after the clone, you were on "master" (aka the trunk).
95 To get back to the trunk, do this:
97   git checkout master
99 Note 1:
100     Be careful to run "git pull" only when on the "master" branch,
101     not when on a branch.  With newer versions of git, you can't cause
102     trouble if you forget, so this is a good reason to ensure you're
103     using 1.5.3.1 or newer.
105 Note 2:
106     It's best not to try to switch from one branch to another if
107     you have pending (uncommitted) changes.  Sometimes it works,
108     sometimes the checkout will fail, telling you that your local
109     modifications conflict with changes required to switch branches.
110     However, in any case, you will *not* lose your uncommitted changes.
111     Run "git stash" to temporarily hide uncommitted changes in your
112     local directory, restoring a clean working directory.
114 Anyhow, get back onto your just-created branch:
116   git checkout my-topic
118 Now, modify some file and commit it:
120   git commit some-file.c
122 Personally, no matter what package I'm working on, I find it useful to
123 put the ChangeLog entries *only* in the commit log, initially, unless
124 I plan to commit/push right away.  Otherwise, I tend to get unnecessary
125 merge conflicts with each rebase (see below).  In grep, I've gone
126 a step further, and no longer maintain an explicit ChangeLog file in
127 version control.  Instead, in a git working directory, you can view
128 ChangeLog information via "git log".  However, each distribution tarball
129 does include a ChangeLog file that is automatically generated from the
130 git logs.
132 So, you've committed a change.  But it's only in your local repository,
133 and only on your "my-topic" branch.  Let's say you wait a day, and
134 then see that someone else changed something and pushed it to the
135 public repository.  Now, you want to update your trunk and "rebase"
136 your changes on the branch so that they are once again relative to the
137 tip of the trunk.  Currently, your branch is attached to the trunk at
138 the next-to-last change set.
140 First: update the trunk from the public repo:
141 [you've first made sure that "git diff" produces no output]
143   git checkout master
144   git pull
146 Now, return to your branch, and "rebase" relative to trunk (master):
148   git checkout my-topic
149   git rebase master
151 If there are no conflicts, this requires no more work from you.
152 However, let's say there was one in ChangeLog, since you didn't
153 follow my advice and modified it anyway.
154 git rebase will tell you there was a conflict and in which
155 file, and instruct you to resolve it and then resume with
156 "git rebase --continue" once that's done.
158 So you resolve as usual, by editing ChangeLog (which has the
159 usual conflict markers), then type "git rebase --continue".
160 That will fail, with a diagnostic telling you to mark
161 the file as "conflict resolved" by doing this:
163   git add ChangeLog
165 Then, finally, you can proceed (possibly onto more conflict resolution,
166 if there are conflicts in other files):
168   git rebase --continue
170 Once it finishes, your changes on the branch are now relative to
171 the tip of the trunk.
173 Now use git format-patch, as above.
176 Amending the most recent change on your private branch
177 ======================================================
178 Let's say you've just committed a change on your private
179 branch, and then realize that something about it is not right.
180 It's easy to adjust:
182   edit your files # this can include running "git add NEW" or "git rm BAD"
183   git commit --amend -a
184   git format-patch --stdout -1 > your-branch.diff
186 That replaces the most recent change-set with the revised one.
190 grep-specific:
192 No more ChangeLog files
193 =======================
195 Do not modify the ChangeLog files during development.  Instead,
196 put that information only in commit messages.  The "make dist" command
197 will generate the top-level ChangeLog file from commit messages.
198 As such, there are strict requirements on the form of the commit log
199 messages.
202 Commit log requirements
203 =======================
204 Your commit log should always start with a one-line summary, the second
205 line should be blank, and the remaining lines are usually ChangeLog-style
206 entries for all affected files.  However, it's fine -- even recommended --
207 to write a few lines of prose describing the change, when the summary
208 and ChangeLog entries don't give enough of the big picture.  Omit the
209 leading TABs that you're used to seeing in a "real" ChangeLog file, but
210 keep the maximum line length at 72 or smaller, so that the generated
211 ChangeLog lines, each with its leading TAB, will not exceed 80 columns.
212 As for the ChangeLog-style content, please follow these guidelines:
214   https://www.gnu.org/prep/standards/html_node/Change-Logs.html
216 Try to make the summary line fit one of the following forms:
218   program_name: change-description
219   prog1, prog2: change-description
220   doc: change-description
221   tests: change-description
222   build: change-description
223   maint: change-description
225 If your commit fixes a bug, try to find the commit that introduced that
226 bug.  If you do that, add a note in your new commit log saying something
227 like "Introduced by commit v2.18-85-g2c94326.".  If that change made it
228 into a release, also add something like [bug introduced in grep-2.19] in
229 the corresponding NEWS blurb.  Assuming you found the bug in commit
230 54cbe6e6, "git describe 54cbe6e6" will print the longer tag-relative
231 string that you'll need.  Note that we used to use an 8-byte SHA1
232 prefix like "54cbe6e6", because that was automatically rendered as a
233 clickable link by "gitk", but with git-1.7.10, the more descriptive
234 version-containing "git describe" format that we now require is also
235 highlighted.
238 Curly braces: use judiciously
239 =============================
240 Omit the curly braces around an "if", "while", "for" etc. body only when
241 that body occupies a single line.  In every other case we require the braces.
242 This ensures that it is trivially easy to identify a single-*statement* loop:
243 each has only one *line* in its body.
245 Omitting braces with a single-line body is fine:
247      while (expr)
248        single_line_stmt ();
250 However, the moment your loop/if/else body extends onto a second line,
251 for whatever reason (even if it's just an added comment), then you should
252 add braces.  Otherwise, it would be too easy to insert a statement just
253 before that comment (without adding braces), thinking it is already a
254 multi-statement loop:
256      while (true)
257        /* comment... */      // BAD: multi-line body without braces
258        single_line_stmt ();
260 Do this instead:
262      while (true)
263        {  /* Always put braces around a multi-line body.  */
264          /* explanation... */
265          single_line_stmt ();
266        }
268 There is one exception: when the second body line is not at the same
269 indentation level as the first body line.
271      if (expr)
272        error (0, 0, _("a diagnostic that would make this line"
273                       " extend past the 80-column limit"));
275 It is safe to omit the braces in the code above, since the
276 further-indented second body line makes it obvious that this is still
277 a single-statement body.
279 To reiterate, don't do this:
281      if (expr)
282        while (expr_2)        // BAD: multi-line body without braces
283          {
284            ...
285          }
287 Do this, instead:
289      if (expr)
290        {
291          while (expr_2)
292            {
293              ...
294            }
295        }
297 However, there is one exception in the other direction, when even a
298 one-line block should have braces.  That occurs when that one-line,
299 brace-less block is an "else" block, and the corresponding "then" block
300 *does* use braces.  In that case, either put braces around the "else"
301 block, or negate the "if"-condition and swap the bodies, putting the
302 one-line block first and making the longer, multi-line block be the
303 "else" block.
305     if (expr)
306       {
307         ...
308         ...
309       }
310     else
311       x = y;    // BAD: braceless "else" with braced "then"
313 This is preferred, especially when the multi-line body is more than a
314 few lines long, because it is easier to read and grasp the semantics of
315 an if-then-else block when the simpler block occurs first, rather than
316 after the more involved block:
318     if (!expr)
319       x = y;                  /* more readable */
320     else
321       {
322         ...
323         ...
324       }
326 If you'd rather not negate the condition, then add braces:
328     if (expr)
329       {
330         ...
331         ...
332       }
333     else
334       {
335         x = y;
336       }
339 Use SPACE-only indentation in all[*] files
340 ==========================================
341 We use space-only indentation in nearly all files.
342 If you use Emacs and your grep working directory name matches,
343 this code enables the right mode:
345   ;; In grep, indent with spaces everywhere (not TABs).
346   ;; Exceptions: Makefile and ChangeLog modes.
347   (add-hook 'find-file-hook '(lambda ()
348     (if (and buffer-file-name
349              (string-match "/grep\\>" (buffer-file-name))
350              (not (string-equal mode-name "Change Log"))
351              (not (string-equal mode-name "Makefile")))
352         (setq indent-tabs-mode nil))))
354 If you use vim (7+ compiled with autocommands), and grep working
355 directory name also matches, add the following in ~/.vimrc:
357   " Set GNU style indentation, spaces instead of TABs
358   function! CoreutilsIndent()
359       " Check if 'grep' is part of the current working directory
360       if match(getcwd(), "grep") > 0
361           " The next 3 lines below set the GNU indentation
362           setlocal cinoptions=>4,n-2,{2,^-2,:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
363           setlocal shiftwidth=2
364           setlocal tabstop=8
365           " Coreutils specific, expand TABs with spaces
366           setlocal expandtab
367       endif
368   endfunction
370   autocmd BufEnter *.c,*.h call CoreutilsIndent()
372 [*] Makefile and ChangeLog files are exempt, of course.
375 Send patches to the address listed in --help output
376 ===================================================
377 Please follow the guidelines in the "Sending your patches." section of
378 git's own SubmittingPatches:
380  https://git.kernel.org/pub/scm/git/git.git/tree/Documentation/SubmittingPatches
383 Add documentation
384 =================
385 If you add a feature or change some user-visible aspect of a program,
386 document it.  If you add an option, document it both in --help output
387 (i.e., in the usage function that generates the --help output) and in
388 doc/*.texi.  The man pages are generated from --help output, so
389 you shouldn't need to change anything under man/.  User-visible changes
390 are usually documented in NEWS, too.
392 When writing prose (documentation, comments, log entries), use an
393 active voice, not a passive one.  I.e., say "print the frobnozzle",
394 not "the frobnozzle will be printed".
396 Please add comments per the GNU Coding Standard:
397   https://www.gnu.org/prep/standards/html_node/Comments.html
400 Minor syntactic preferences
401 ===========================
402 [I hesitate to write this one down, because it appears to be an
403  acquired taste, at least for native-English speakers.  It seems odd
404  (if not truly backwards) to nearly anyone who doesn't have a strong
405  mathematics background and perhaps a streak of something odd in their
406  character ;-) ]
407 In writing arithmetic comparisons, use "<" and "<=" rather than
408 ">" and ">=".
410 const placement:
411 Write "Type const *var", not "const Type *var".
412 FIXME: dig up justification
415 Be nice to translators
416 ======================
417 Don't change translatable strings if you can avoid it.
418 If you must rearrange individual lines (e.g., in multi-line --help
419 strings), extract and create new strings, rather than extracting
420 and moving into existing blocks.  This avoids making unnecessary
421 work for translators.
424 Add tests
425 ==========
426 Nearly every significant change must be accompanied by a test suite
427 addition that exercises it.  If you fix a bug, add at least one test that
428 fails without the patch, but that succeeds once your patch is applied.
429 If you add a feature, add tests to exercise as much of the new code
430 as possible. Note to run tests/new-test in isolation you can do:
432   (cd tests && make check TESTS=new-test VERBOSE=yes)
434 Variables that are significant for tests with their default values are:
436   VERBOSE=yes
437   RUN_EXPENSIVE_TESTS=no
438   SHELL=/bin/sh
440 There are many tests in the tests/ directories.  Use one of the
441 init.sh-using scripts as a template.
443 If writing tests is not your thing, don't worry too much about it,
444 but do provide scenarios, input/output pairs, or whatever, along with
445 examples of running the tool to demonstrate the new or changed feature,
446 and someone else will massage that into a test (writing portable tests
447 can be a challenge).
450 Copyright assignment
451 ====================
452 If your change is significant (i.e., if it adds more than ~10 lines),
453 then you'll have to have a copyright assignment on file with the FSF.
454 Since that involves first an email exchange between you and the FSF,
455 and then the exchange (FSF to you, then back) of an actual sheet of paper
456 with your signature on it, and finally, some administrative processing
457 in Boston, the process can take a few weeks.
459 The forms to choose from are in gnulib's doc/Copyright/ directory.
460 If you want to assign a single change, you should use the file,
461 doc/Copyright/request-assign.changes:
463     https://www.gnu.org/software/gnulib/Copyright/request-assign.changes
465 If you would like to assign past and future contributions to a project,
466 you'd use doc/Copyright/request-assign.future:
468     https://www.gnu.org/software/gnulib/Copyright/request-assign.future
470 You may make assignments for up to four projects at a time.
472 In case you're wondering why we bother with all of this, read this:
474     https://www.gnu.org/licenses/why-assign.html
477 Run "make syntax-check", or even "make distcheck"
478 ================================================
479 Making either of those targets runs many integrity and
480 project-specific policy-conformance tests.  For example, the former
481 ensures that you add no trailing blanks and no uses of certain deprecated
482 functions.  The latter performs all "syntax-check" tests, and also
483 ensures that the build completes with no warnings when using a certain
484 set of gcc -W... options.  Don't even bother running "make distcheck"
485 unless you have a reasonably up to date installation including recent
486 versions of gcc and the linux kernel, and modern GNU tools.
489 Ensure that your changes are indented properly.
490 ===============================================
491 Format the code the way GNU indent does.
492 Filtering most source files through "indent --no-tabs" should
493 induce no change in indentation.  Try not to add any more.
496 Avoid trailing white space
497 ==========================
498 There are no trailing blanks in grep's version-controlled files.
500 Do not add any more trailing blanks anywhere.  While "make syntax-check"
501 will alert you if you slip up, it's better to nip any problem in the
502 bud, as you're typing.  A good way to help you adapt to this rule is
503 to configure your editor to highlight any offending characters in the
504 files you edit.  If you use Emacs, customize its font-lock mode
505 or use its WhiteSpace mode:
507     https://www.emacswiki.org/emacs/WhiteSpace
509 If you use vim, add this to ~/.vimrc:
511     let c_space_errors=1
512     highlight RedundantSpaces ctermbg=red guibg=red
513     match RedundantSpaces /\s\+$\| \+\ze\t/
516 Git can help too, by stopping you from committing any change that would
517 add trailing blanks.  The example pre-commit hook contains code to check
518 for trailing whitespace and spaces before tabs; enable it by moving it
519 to the right place and making sure it is executable:
521     mv .git/hooks/pre-commit.sample .git/hooks/pre-commit
523 With a repository created by git-1.5.6 or older, use this command:
525     chmod +x .git/hooks/pre-commit
527 To manually check for whitespace errors before committing, you can use
529     git diff --check
531 Git also has some settings to enable suitable internal whitespace checks.
532 See the manpage for git-apply for details.
535 -------------------------------------------
537 Miscellaneous useful git commands
538 =================================
540   * gitk: give a graphical view of the revision graph of the current branch
541   * gitk --all: same, but display all branches
542   * git log: to get most of the same info in text form
543   * git log -p: same as above, but with diffs
544   * git log -p SOME_FILE: same as above, but limit to SOME_FILE
545   * git log -p -2 SOME_FILE: same as above, but print only two deltas
546   * git log -p -1: print the most recently committed change set
547   * git format-patch --stdout -1 > FILE: output the most recently committed
548       change set, in a format suitable to be submitted and/or applied via
549       "git am FILE".
550   * git reset --soft HEAD^: Commit the delta required to restore
551       state to the revision just before HEAD (i.e., next-to-last).
552   * git rebase -i master: run this from on a branch, and it gives
553       you an interface with which you can reorder and modify arbitrary
554       change sets on that branch.
556   * if you "misplace" a change set, i.e., via git reset --hard ..., so that
557     it's no longer reachable by any branch, you can use "git fsck" to find
558     its SHA1 and then tag it or cherry-pick it onto an existing branch.
559     For example, run this:
560       git fsck --lost-found HEAD && cd .git/lost-found/commit \
561         && for i in *; do git show $i|grep SOME_IDENTIFYING_STRING \
562         && echo $i; done
563     The "git fsck ..." command creates the .git/lost-found/... hierarchy
564     listing all unreachable objects.  Then the for loop
565     print SHA1s for commits that match via log or patch.
566     For example, say that found 556fbb57216b119155cdda824c98dc579b8121c8,
567     you could run "git show 556fbb57216b119" to examine the change set,
568     or "git checkout -b found 556fbb5721" to give it a branch name.
569     Finally, you might run "git checkout master && git cherry-pick 556fbb5721"
570     to put that change on the tip of "master".
572 -------------------------------------------
574 Finding things to do
575 ====================
576 If you don't know where to start, check out the TODO file for projects
577 that look like they're at your skill-/interest-level.  Another good
578 option is always to improve tests.  You never know what you might
579 uncover when you improve test coverage, and even if you don't find
580 any bugs your contribution is sure to be appreciated.
582 A good way to quickly assess current test coverage is to use "lcov"
583 to generate HTML coverage reports.  Follow these steps:
585   # configure with coverage information
586   ./configure CFLAGS="-g -fprofile-arcs -ftest-coverage"
587   make
588   # run whatever tests you want, i.e.:
589   make check
590   # run lcov
591   lcov -t grep -q -d lib -b lib -o lib.lcov -c
592   lcov -t grep -q -d src -b src -o src.lcov -c
593   # generate HTML from the output
594   genhtml -p `pwd` -t grep -q --output-directory lcov-html *.lcov
596 Then just open the index.html file (in the generated lcov-html directory)
597 in your favorite web browser.
599 ========================================================================
600 Copyright (C) 2009-2025 Free Software Foundation, Inc.
602 Permission is granted to copy, distribute and/or modify this document
603 under the terms of the GNU Free Documentation License, Version 1.3 or
604 any later version published by the Free Software Foundation; with no
605 Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
606 Texts.  A copy of the license is included in the "GNU Free
607 Documentation License" file as part of this distribution.