summaryrefslogtreecommitdiff
path: root/Documentation/CodingGuidelines
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/CodingGuidelines')
-rw-r--r--Documentation/CodingGuidelines197
1 files changed, 197 insertions, 0 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
new file mode 100644
index 0000000000..fe1c1e5bc2
--- /dev/null
+++ b/Documentation/CodingGuidelines
@@ -0,0 +1,197 @@
+Like other projects, we also have some guidelines to keep to the
+code. For git in general, three rough rules are:
+
+ - Most importantly, we never say "It's in POSIX; we'll happily
+ ignore your needs should your system not conform to it."
+ We live in the real world.
+
+ - However, we often say "Let's stay away from that construct,
+ it's not even in POSIX".
+
+ - In spite of the above two rules, we sometimes say "Although
+ this is not in POSIX, it (is so convenient | makes the code
+ much more readable | has other good characteristics) and
+ practically all the platforms we care about support it, so
+ let's use it".
+
+ Again, we live in the real world, and it is sometimes a
+ judgement call, the decision based more on real world
+ constraints people face than what the paper standard says.
+
+
+As for more concrete guidelines, just imitate the existing code
+(this is a good guideline, no matter which project you are
+contributing to). It is always preferable to match the _local_
+convention. New code added to git suite is expected to match
+the overall style of existing code. Modifications to existing
+code is expected to match the style the surrounding code already
+uses (even if it doesn't match the overall style of existing code).
+
+But if you must have a list of rules, here they are.
+
+For shell scripts specifically (not exhaustive):
+
+ - We use tabs for indentation.
+
+ - Case arms are indented at the same depth as case and esac lines.
+
+ - We prefer $( ... ) for command substitution; unlike ``, it
+ properly nests. It should have been the way Bourne spelled
+ it from day one, but unfortunately isn't.
+
+ - We use POSIX compliant parameter substitutions and avoid bashisms;
+ namely:
+
+ - We use ${parameter-word} and its [-=?+] siblings, and their
+ colon'ed "unset or null" form.
+
+ - We use ${parameter#word} and its [#%] siblings, and their
+ doubled "longest matching" form.
+
+ - No "Substring Expansion" ${parameter:offset:length}.
+
+ - No shell arrays.
+
+ - No strlen ${#parameter}.
+
+ - No pattern replacement ${parameter/pattern/string}.
+
+ - We use Arithmetic Expansion $(( ... )).
+
+ - Inside Arithmetic Expansion, spell shell variables with $ in front
+ of them, as some shells do not grok $((x)) while accepting $(($x))
+ just fine (e.g. dash older than 0.5.4).
+
+ - We do not use Process Substitution <(list) or >(list).
+
+ - We prefer "test" over "[ ... ]".
+
+ - We do not write the noiseword "function" in front of shell
+ functions.
+
+ - As to use of grep, stick to a subset of BRE (namely, no \{m,n\},
+ [::], [==], nor [..]) for portability.
+
+ - We do not use \{m,n\};
+
+ - We do not use -E;
+
+ - We do not use ? nor + (which are \{0,1\} and \{1,\}
+ respectively in BRE) but that goes without saying as these
+ are ERE elements not BRE (note that \? and \+ are not even part
+ of BRE -- making them accessible from BRE is a GNU extension).
+
+For C programs:
+
+ - We use tabs to indent, and interpret tabs as taking up to
+ 8 spaces.
+
+ - We try to keep to at most 80 characters per line.
+
+ - When declaring pointers, the star sides with the variable
+ name, i.e. "char *string", not "char* string" or
+ "char * string". This makes it easier to understand code
+ like "char *string, c;".
+
+ - We avoid using braces unnecessarily. I.e.
+
+ if (bla) {
+ x = 1;
+ }
+
+ is frowned upon. A gray area is when the statement extends
+ over a few lines, and/or you have a lengthy comment atop of
+ it. Also, like in the Linux kernel, if there is a long list
+ of "else if" statements, it can make sense to add braces to
+ single line blocks.
+
+ - We try to avoid assignments inside if().
+
+ - Try to make your code understandable. You may put comments
+ in, but comments invariably tend to stale out when the code
+ they were describing changes. Often splitting a function
+ into two makes the intention of the code much clearer.
+
+ - Double negation is often harder to understand than no negation
+ at all.
+
+ - Some clever tricks, like using the !! operator with arithmetic
+ constructs, can be extremely confusing to others. Avoid them,
+ unless there is a compelling reason to use them.
+
+ - Use the API. No, really. We have a strbuf (variable length
+ string), several arrays with the ALLOC_GROW() macro, a
+ string_list for sorted string lists, a hash map (mapping struct
+ objects) named "struct decorate", amongst other things.
+
+ - When you come up with an API, document it.
+
+ - The first #include in C files, except in platform specific
+ compat/ implementations, should be git-compat-util.h or another
+ header file that includes it, such as cache.h or builtin.h.
+
+ - If you are planning a new command, consider writing it in shell
+ or perl first, so that changes in semantics can be easily
+ changed and discussed. Many git commands started out like
+ that, and a few are still scripts.
+
+ - Avoid introducing a new dependency into git. This means you
+ usually should stay away from scripting languages not already
+ used in the git core command set (unless your command is clearly
+ separate from it, such as an importer to convert random-scm-X
+ repositories to git).
+
+ - When we pass <string, length> pair to functions, we should try to
+ pass them in that order.
+
+Writing Documentation:
+
+ Every user-visible change should be reflected in the documentation.
+ The same general rule as for code applies -- imitate the existing
+ conventions. A few commented examples follow to provide reference
+ when writing or modifying command usage strings and synopsis sections
+ in the manual pages:
+
+ Placeholders are spelled in lowercase and enclosed in angle brackets:
+ <file>
+ --sort=<key>
+ --abbrev[=<n>]
+
+ Possibility of multiple occurrences is indicated by three dots:
+ <file>...
+ (One or more of <file>.)
+
+ Optional parts are enclosed in square brackets:
+ [<extra>]
+ (Zero or one <extra>.)
+
+ --exec-path[=<path>]
+ (Option with an optional argument. Note that the "=" is inside the
+ brackets.)
+
+ [<patch>...]
+ (Zero or more of <patch>. Note that the dots are inside, not
+ outside the brackets.)
+
+ Multiple alternatives are indicated with vertical bar:
+ [-q | --quiet]
+ [--utf8 | --no-utf8]
+
+ Parentheses are used for grouping:
+ [(<rev>|<range>)...]
+ (Any number of either <rev> or <range>. Parens are needed to make
+ it clear that "..." pertains to both <rev> and <range>.)
+
+ [(-p <parent>)...]
+ (Any number of option -p, each with one <parent> argument.)
+
+ git remote set-head <name> (-a | -d | <branch>)
+ (One and only one of "-a", "-d" or "<branch>" _must_ (no square
+ brackets) be provided.)
+
+ And a somewhat more contrived example:
+ --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]
+ Here "=" is outside the brackets, because "--diff-filter=" is a
+ valid usage. "*" has its own pair of brackets, because it can
+ (optionally) be specified only when one or more of the letters is
+ also provided.