| This is an essay by Jim Blandy <jimb@redhat.com> on maintaining | |
| ChangeLog entries. | |
| Although Subversion generates its ChangeLogs from svn log data, | |
| instead of keeping independent ChangeLog files, most of the advice | |
| below is as applicable to cvs log messages as to ChangeLog entries. | |
| Maintaining the ChangeLog | |
| ========================= | |
| A project's ChangeLog provides a history of development. Comments in | |
| the code should explain the code's present state, but ChangeLog | |
| entries should explain how and when it got that way. The ChangeLog | |
| must show: | |
| * the relative order in which changes entered the code, so you can | |
| see the context in which a change was made, and | |
| * the date at which the change entered the code, so you can relate the | |
| change to outside events, like branch cuts, code freezes, and | |
| releases. | |
| In the case of CVS, these refer to when the change was committed, | |
| because that is the context in which other developers will see the | |
| change. | |
| Every change to the sources should have a ChangeLog entry. The value | |
| of the ChangeLog becomes much less if developers cannot rely on its | |
| completeness. Even if you've only changed comments, write an entry | |
| that says, "Doc fix." The only changes you needn't log are small | |
| changes that have no effect on the source, like formatting tweaks. | |
| In order to keep the ChangeLog a manageable size, at the beginning of | |
| each year, the ChangeLog should be renamed to "ChangeLog-YYYY", and a | |
| fresh ChangeLog file started. | |
| How to write ChangeLog entries | |
| ------------------------------ | |
| ChangeLog entries should be full sentences, not sentence fragments. | |
| Fragments are more often ambiguous, and it takes only a few more | |
| seconds to write out what you mean. Fragments like `New file' or `New | |
| function' are acceptable, because they are standard idioms, and all | |
| further details should appear in the source code. | |
| The log entry should mention every file changed. It should also | |
| mention by name every function, variable, macro, makefile target, | |
| grammar rule, etc. you changed. However, there are common-sense | |
| exceptions: | |
| * If you have made a change which requires trivial changes throughout | |
| the rest of the program (e.g., renaming a variable), you needn't | |
| name all the functions affected. | |
| * If you have rewritten a file completely, the reader understands that | |
| everything in it has changed, so your log entry may simply give the | |
| file name, and say "Rewritten". | |
| In general, there is a tension between making entries easy to find by | |
| searching for identifiers, and wasting time or producing unreadable | |
| entries by being exhaustive. Use your best judgement --- and be | |
| considerate of your fellow developers. | |
| Group ChangeLog entries into "paragraphs", separated by blank lines. | |
| Each paragraph should be a set of changes that accomplish a single | |
| goal. Independent changes should be in separate paragraphs. For | |
| example: | |
| 1999-03-24 Stan Shebs <shebs@andros.cygnus.com> | |
| * configure.host (mips-dec-mach3*): Use mipsm3, not mach3. | |
| Attempt to sort out SCO-related configs. | |
| * configure.host (i[3456]86-*-sysv4.2*): Use this instead of | |
| i[3456]86-*-sysv4.2MP and i[3456]86-*-sysv4.2uw2*. | |
| (i[3456]86-*-sysv5*): Recognize this. | |
| * configure.tgt (i[3456]86-*-sco3.2v5*, i[3456]86-*-sco3.2v4*): | |
| Recognize these. | |
| Even though this entry describes two changes to `configure.host', | |
| they're in separate paragraphs, because they're unrelated changes. | |
| The second change to `configure.host' is grouped with another change | |
| to `configure.tgt', because they both serve the same purpose. | |
| Also note that the author has kindly recorded his overall motivation | |
| for the paragraph, so we don't have to glean it from the individual | |
| changes. | |
| The header line for the ChangeLog entry should have the format shown | |
| above. If you are using an old version of Emacs (before 20.1) that | |
| generates entries with more verbose dates, consider using | |
| `etc/add-log.el', from the GDB source tree. If you are using vi, | |
| consider using the macro in `etc/add-log.vi'. Both of these generate | |
| entries in the newer, terser format. | |
| One should never need the ChangeLog to understand the current code. | |
| If you find yourself writing a significant explanation in the | |
| ChangeLog, you should consider carefully whether your text doesn't | |
| actually belong in a comment, alongside the code it explains. Here's | |
| an example of doing it right: | |
| 1999-02-23 Tom Tromey <tromey@cygnus.com> | |
| * cplus-dem.c (consume_count): If `count' is unreasonable, | |
| return 0 and don't advance input pointer. | |
| And then, in `consume_count' in `cplus-dem.c': | |
| while (isdigit ((unsigned char)**type)) | |
| { | |
| count *= 10; | |
| count += **type - '0'; | |
| /* A sanity check. Otherwise a symbol like | |
| `_Utf390_1__1_9223372036854775807__9223372036854775' | |
| can cause this function to return a negative value. | |
| In this case we just consume until the end of the string. */ | |
| if (count > strlen (*type)) | |
| { | |
| *type = save; | |
| return 0; | |
| } | |
| This is why a new function, for example, needs only a log entry saying | |
| "New Function" --- all the details should be in the source. | |
| Avoid the temptation to abbreviate filenames or function names, as in | |
| this example (mostly real, but slightly exaggerated): | |
| * gdbarch.[ch] (gdbarch_tdep, gdbarch_bfd_arch_info, | |
| gdbarch_byte_order, {set,}gdbarch_long_bit, | |
| {set,}gdbarch_long_long_bit, {set,}gdbarch_ptr_bit): Corresponding | |
| functions. | |
| This makes it difficult for others to search the ChangeLog for changes | |
| to the file or function they are interested in. For example, if you | |
| searched for `set_gdbarch_long_bit', you would not find the above | |
| entry, because the writer used CSH-style globbing to abbreviate the | |
| list of functions. If you gave up, and made a second pass looking for | |
| gdbarch.c, you wouldn't find that either. Consider your poor readers, | |
| and write out the names. | |
| ChangeLogs and the CVS log | |
| -------------------------- | |
| CVS maintains its own logs, which you can access using the `cvs log' | |
| command. This duplicates the information present in the ChangeLog, | |
| but binds each entry to a specific revision, which can be helpful at | |
| times. | |
| However, the CVS log is no substitute for the ChangeLog files. | |
| * CVS provides no easy way to see the changes made to a set of files | |
| in chronological order. They're sorted first by filename, not by date. | |
| * Unless you put full ChangeLog paragraphs in your CVS log entries, it's | |
| difficult to pull together changes that cross several files. | |
| * CVS doesn't segregate log entries for branches from those for the | |
| trunk in any useful way. | |
| In some circumstances, though, the CVS log is more useful than the | |
| ChangeLog, so we maintain both. When you commit a change, you should | |
| provide appropriate text in both the ChangeLog and the CVS log. | |
| It is not necessary to provide CVS log entries for ChangeLog changes, | |
| since it would simply duplicate the contents of the file itself. | |
| Writing ChangeLog entries for merges | |
| ------------------------------------ | |
| Revision management software like CVS can introduce some confusion | |
| when writing ChangeLog entries. For example, one might write a change | |
| on a branch, and then merge it into the trunk months later. In that | |
| case, what position and date should the developer use for the | |
| ChangeLog entry --- that of the original change, or the date of the | |
| merge? | |
| The principles described at the top need to hold for both the original | |
| change and the merged change. That is: | |
| * On the branch (or trunk) where the change is first committed, the | |
| ChangeLog entry should be written as normal, inserted at the top of | |
| the ChangeLog and reflecting the date the change was committed to | |
| the branch (or trunk). | |
| * When the change is then merged (to the trunk, or to another branch), | |
| the ChangeLog entry should have the following form: | |
| 1999-03-26 Jim Blandy <jimb@zwingli.cygnus.com> | |
| Merged change from foobar_20010401_branch: | |
| 1999-03-16 Keith Seitz <keiths@cygnus.com> | |
| [...] | |
| In this case, "Jim Blandy" is doing the merge on March 26; "Keith | |
| Seitz" is the original author of the change, who committed it to | |
| `foobar_20010401_branch' on March 16. | |
| As shown here, the entry for the merge should be like any other | |
| change --- inserted at the top of the ChangeLog, and stamped with | |
| the date the merge was committed. It should indicate the origin of | |
| the change, and provide the full text of the original entry, | |
| indented to avoid being confused with a true log entry. Remember | |
| that people looking for the merge will search for the original | |
| changelog text, so it's important to preserve it unchanged. | |
| For the merge entry, we use the merge date, and not the original | |
| date, because this is when the change appears on the trunk or branch | |
| this ChangeLog documents. Its impact on these sources is | |
| independent of when or where it originated. | |
| This approach preserves the structure of the ChangeLog (entries appear | |
| in order, and dates reflect when they appeared), but also provides | |
| full information about changes' origins. | |