summaryrefslogtreecommitdiff
path: root/HACKING
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2008-04-02 09:05:18 +0200
committerJim Meyering <meyering@redhat.com>2008-04-02 09:08:08 +0200
commit184a0298f345a82f484d5281ee14217513703cc1 (patch)
tree952a8778bcc03c7c1b25b33c765c8b9699756dc0 /HACKING
parent1fb8739c0b693820cc059d83c8247a9ffab3c17d (diff)
downloadcoreutils-184a0298f345a82f484d5281ee14217513703cc1.tar.xz
HACKING: rename README-contribution-guidelines
README-contribution-guidelines: Rename to .. HACKING: ...this.
Diffstat (limited to 'HACKING')
-rw-r--r--HACKING314
1 files changed, 314 insertions, 0 deletions
diff --git a/HACKING b/HACKING
new file mode 100644
index 000000000..d61644392
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,314 @@
+Coreutils Contribution Guidelines
+
+
+Prerequisites
+=============
+You will need the "git" version control tools.
+On Fedora-based systems, do "yum install git".
+On Debian-based ones install the "git-core" package.
+Then run "git --version". If that says it's older than
+version 1.4.4, then you'd do well to get a newer version.
+At worst, just download the latest stable release from
+http://git.or.cz/ and build from source.
+
+For details on building the programs in this package, see
+the file, README-hacking.
+
+
+Use the latest upstream sources
+===============================
+Base any changes you make on the latest upstream sources.
+You can get a copy of the latest with this command:
+
+ git clone git://git.sv.gnu.org/coreutils
+
+That downloads the entire repository, including revision control history
+dating back to 1991. The repository (the part you download, and which
+resides in coreutils/.git) currently weighs in at about 30MB. So you
+don't want to download it more often than necessary. Once downloaded,
+you can get incremental updates by running this command from inside
+your new coreutils/ directory:
+
+ git pull
+
+
+*Before* you commit changes
+===========================
+
+In this project, we much prefer patches that automatically record
+authorship. That is important not just to give credit where due, but
+also from a legal standpoint (see below). To create author-annotated
+patches with git, you must first tell git who you are. That information
+is best recorded in your ~/.gitconfig file. Edit that file, creating
+it if needed, and put your name and email address in place of these
+example values:
+
+[user]
+ name = Joe X. User
+ email = joe.user@example.com
+
+
+Your first commit: the quick and dirty way
+==========================================
+First of all, realize that to "commit" a change in git is a purely
+local operation. It affects only the local repository (the .git/ dir)
+in your current coreutils/ hierarchy.
+
+To try this out, modify a file or two. If you create a new file, you'll
+need to tell git about it with "git add new-file.c". Commit all changes
+with "git commit -a". That prompts you for a log message, which should
+include a one-line summary, a blank line, and ChangeLog-style entries
+for all affected files. More on that below.
+
+Once your change is committed, you can create a proper patch that includes
+a log message and authorship information as well as any permissions
+changes. Use this command to save that single, most-recent change set:
+
+ git format-patch --stdout --signoff HEAD~1 > DIFF
+
+The trouble with this approach is that you've just checked in a change
+(remember, it's only local) on the "master" branch, and that's where new
+changes would normally appear when you pull the latest from "upstream".
+When you "pull" from a remote repository to get the latest, your local
+changes on "master" may well induce conflicts. For this reason, you
+may want to keep "master" free of any local changes, so that you can
+use it to track unadulterated upstream sources.
+
+However, if your cloned directory is for a one-shot patch submission and
+you're going to remove it right afterwards, then this approach is fine.
+Otherwise, for a more sustainable (and more generally useful, IMHO)
+process, read on about "topic" branches.
+
+
+Make your changes on a private "topic" branch
+=============================================
+So you checked out coreutils like this:
+
+ git clone git://git.sv.gnu.org/coreutils
+
+Now, cd into the coreutils/ directory and run:
+
+ git checkout -b my-topic
+
+That creates the my-topic branch and puts you on it.
+To see which branch you're on, type "git branch".
+Right after the clone, you were on "master" (aka the trunk).
+To get back to the trunk, do this:
+
+ git checkout master
+
+Note 1:
+ Be careful to run "git pull" only when on the "master" branch,
+ not when on a branch. With newer versions of git, you can't cause
+ trouble if you forget, so this is a good reason to ensure you're
+ using 1.5.3.1 or newer.
+
+Note 2:
+ It's best not to try to switch from one branch to another if
+ you have pending (uncommitted) changes. Sometimes it works,
+ sometimes the checkout will fail, telling you that your local
+ modifications conflict with changes required to switch branches.
+ However, in any case, you will *not* lose your uncommitted changes.
+
+Anyhow, get back onto your just-created branch:
+
+ git checkout my-topic
+
+Now, modify some file and commit it:
+
+ git commit some-file.c
+
+Personally, no matter what package I'm working on, I find it useful to
+put the ChangeLog entries *only* in the commit log, initially, unless
+I plan to commit/push right away. Otherwise, I tend to get unnecessary
+merge conflicts with each rebase (see below). In coreutils, I've gone
+a step further, and no longer maintain an explicit ChangeLog file in
+version control. Instead, in a git working directory, you can view
+ChangeLog information via "git log". However, each distribution tarball
+does include a ChangeLog file that is automatically generated from the
+git logs.
+
+So, you've committed a change. But it's only in your local repository,
+and only on your "my-topic" branch. Let's say you wait a day, and
+then see that someone else changed something and pushed it to the
+public repository. Now, you want to update your trunk and "rebase"
+your changes on the branch so that they are once again relative to the
+tip of the trunk. Currently, your branch is attached to the trunk at
+the next-to-last change set.
+
+First: update the trunk from the public repo:
+[you've first made sure that "git diff" produces no output]
+
+ git checkout master
+ git pull
+
+Now, return to your branch, and "rebase" relative to trunk (master):
+
+ git checkout my-topic
+ git rebase master
+
+If there are no conflicts, this requires no more work from you.
+However, let's say there was one in ChangeLog, since you didn't
+follow my advice and modified it anyway.
+git rebase will tell you there was a conflict and in which
+file, and instruct you to resolve it and then resume with
+"git rebase --continue" once that's done.
+
+So you resolve as usual, by editing ChangeLog (which has the
+usual conflict markers), then type "git rebase --continue".
+That will fail, with a diagnostic telling you to mark
+the file as "conflict resolved" by doing this:
+
+ git add ChangeLog
+
+Then, finally, you can proceed (possibly onto more conflict resolution,
+if there are conflicts in other files):
+
+ git rebase --continue
+
+Once it finishes, your changes on the branch are now relative to
+the tip of the trunk.
+
+Now use git format-patch, as above.
+
+
+Amending the most recent change on your private branch
+======================================================
+Let's say you've just committed a change on your private
+branch, and then realize that something about it is not right.
+It's easy to adjust:
+
+ edit your files # this can include running "git add NEW" or "git rm BAD"
+ git commit --amend -e -a
+ git format-patch --stdout --signoff HEAD~1 > your-branch.diff
+
+That replaces the most recent commit with the revised one.
+
+
+
+Coreutils-specific:
+
+No more ChangeLog files
+=======================
+Do not modify any of the ChangeLog files in coreutils. Starting in
+2008, the policy changed. Before, we would insert the exact same text
+(or worse, sometimes slightly differing) into both the ChangeLog file
+and the commit log. Now we put that information only in the commit log,
+and generate the top-level ChangeLog file from logs at "make dist" time.
+As such, there are strict requirements on the form of the commit log
+messages.
+
+
+Commit log requirements
+=======================
+Your commit log should always start with a one-line summary, the second
+line should be blank, and the remaining lines are usually ChangeLog-style
+entries for all affected files. Omit the leading TABs that you're used
+to seeing in a "real" ChangeLog file.
+
+
+Use SPACE-only indentation in new files.
+========================================
+In any new file, eliminate all leading TABs (e.g., via running GNU indent
+with --no-tabs) and put these lines at the end of the file:
+[FIXME: suggest vim syntax to do same thing, if it can be done safely.
+ Most distros now "set nomodeline" by default for a good reason. ]
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
+
+Do not change TABs to spaces or vice versa in any existing file.
+
+
+Send patches to bug-coreutils@gnu.org
+=====================================
+
+
+Add documentation
+=================
+If you add a feature or change some user-visible aspect of a program,
+document it. If you add an option, document it both in --help output
+(i.e., in the usage function that generates the --help output) and in
+doc/coreutils.texi. The man pages are generated from --help output, so
+you shouldn't need to change anything under man/. User-visible changes
+are usually documented in NEWS, too.
+
+
+Add tests
+==========
+Nearly every significant change must be accompanied by a test suite
+addition that exercises it. If you fix a bug, add at least one test that
+fails without the patch, but that succeeds once your patch is applied.
+If you add a feature, add tests to exercise as much of the new code
+as possible.
+
+There are hundreds of tests in the tests/ directories. You can use
+tests/sample-test as a template, or one of the various Perl-based ones
+in tests/misc.
+
+If writing tests is not your thing, don't worry too much about it,
+but do provide scenarios, input/output pairs, or whatever, along with
+examples of running the tool to demonstrate the new or changed feature,
+and someone else will massage that into a test (writing portable tests
+can be a challenge).
+
+
+Copyright assignment
+====================
+If your change is significant (i.e., if it adds more than ~10 lines),
+then you'll have to have a copyright assignment on file with the FSF.
+Since that involves first an email exchange between you and the FSF,
+and then the exchange (FSF to you, then back) of an actual sheet of paper
+with your signature on it, and finally, some administrative processing
+in Boston, the process can take a few weeks.
+
+The forms to choose from are in gnulib's doc/Copyright/ directory.
+If you want to assign a single change, you should use the file,
+doc/Copyright/request-assign.changes:
+
+ http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=doc/Copyright/request-assign.changes;hb=HEAD
+
+If you would like to assign past and future coreutils work,
+you'd use doc/Copyright/request-assign.future:
+
+ http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=doc/Copyright/request-assign.future;hb=HEAD
+
+
+Run "make syntax-check", or even "make distcheck"
+================================================
+Making either of those targets runs many integrity and
+coreutils-specific policy-conformance tests. For example, the former
+ensures that you add no trailing blanks and no uses of certain deprecated
+functions. The latter performs all "syntax-check" tests, and also
+ensures that the build completes with no warnings when using a certain
+set of gcc -W... options. Don't even bother running "make distcheck"
+unless you have a very up to date installation including recent versions
+of gcc and the linux kernel, and modern GNU tools.
+
+
+Ensure that your changes are indented properly.
+===============================================
+Format the code the way GNU indent does.
+In a file with the "indent-tabs-mode: nil" directive at the end,
+running "indent --no-tabs" should induce no change.
+With other files, there will be some existing differences.
+Try not to add any more.
+
+
+-------------------------------------------
+
+Miscellaneous useful git commands
+=================================
+
+ * gitk: give a graphical view of the revision graph
+ * git log: to get most of the same info in text form
+ * git log -p: same as above, but with diffs
+ * git log -p SOME_FILE: same as above, but limit to SOME_FILE
+ * git reset --soft HEAD^: Commit the delta required to restore
+ state to the revision just before HEAD (i.e., next-to-last).
+ * git rebase -i master: run this from on a branch, and it gives
+ you an interface with which you can reorder and modify arbitrary
+ change sets on that branch.