1 Grep Contribution Guidelines
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:
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:
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
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:
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.
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
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]
146 Now, return to your branch, and "rebase" relative to trunk (master):
148 git checkout my-topic
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:
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.
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.
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
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
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:
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:
257 /* comment... */ // BAD: multi-line body without braces
263 { /* Always put braces around a multi-line body. */
268 There is one exception: when the second body line is not at the same
269 indentation level as the first body line.
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:
282 while (expr_2) // BAD: multi-line body without braces
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
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:
319 x = y; /* more readable */
326 If you'd rather not negate the condition, then add braces:
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
365 " Coreutils specific, expand TABs with spaces
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
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
407 In writing arithmetic comparisons, use "<" and "<=" rather than
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.
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:
437 RUN_EXPENSIVE_TESTS=no
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
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:
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
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
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 \
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 -------------------------------------------
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"
588 # run whatever tests you want, i.e.:
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.