diff options
Diffstat (limited to 'Documentation')
30 files changed, 1348 insertions, 122 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile index 2415e0d657..471bb29725 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -67,6 +67,7 @@ SP_ARTICLES += howto/maintain-git API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt))) SP_ARTICLES += $(API_DOCS) +TECH_DOCS += technical/hash-function-transition TECH_DOCS += technical/http-protocol TECH_DOCS += technical/index-format TECH_DOCS += technical/pack-format diff --git a/Documentation/RelNotes/2.14.3.txt b/Documentation/RelNotes/2.14.3.txt new file mode 100644 index 0000000000..977c9e857c --- /dev/null +++ b/Documentation/RelNotes/2.14.3.txt @@ -0,0 +1,99 @@ +Git v2.14.3 Release Notes +========================= + +Fixes since v2.14.2 +------------------- + + * A helper function to read a single whole line into strbuf + mistakenly triggered OOM error at EOF under certain conditions, + which has been fixed. + + * In addition to "cc: <a@dd.re.ss> # cruft", "cc: a@dd.re.ss # cruft" + was taught to "git send-email" as a valid way to tell it that it + needs to also send a carbon copy to <a@dd.re.ss> in the trailer + section. + + * Fix regression to "gitk --bisect" by a recent update. + + * Unlike "git commit-tree < file", "git commit-tree -F file" did not + pass the contents of the file verbatim and instead completed an + incomplete line at the end, if exists. The latter has been updated + to match the behaviour of the former. + + * "git archive", especially when used with pathspec, stored an empty + directory in its output, even though Git itself never does so. + This has been fixed. + + * API error-proofing which happens to also squelch warnings from GCC. + + * "git gc" tries to avoid running two instances at the same time by + reading and writing pid/host from and to a lock file; it used to + use an incorrect fscanf() format when reading, which has been + corrected. + + * The test linter has been taught that we do not like "echo -e". + + * Code cmp.std.c nitpick. + + * "git describe --match" learned to take multiple patterns in v2.13 + series, but the feature ignored the patterns after the first one + and did not work at all. This has been fixed. + + * "git cat-file --textconv" started segfaulting recently, which + has been corrected. + + * The built-in pattern to detect the "function header" for HTML did + not match <H1>..<H6> elements without any attributes, which has + been fixed. + + * "git mailinfo" was loose in decoding quoted printable and produced + garbage when the two letters after the equal sign are not + hexadecimal. This has been fixed. + + * The documentation for '-X<option>' for merges was misleadingly + written to suggest that "-s theirs" exists, which is not the case. + + * Spell the name of our system as "Git" in the output from + request-pull script. + + * Fixes for a handful memory access issues identified by valgrind. + + * Backports a moral equivalent of 2015 fix to the poll emulation from + the upstream gnulib to fix occasional breakages on HPE NonStop. + + * In the "--format=..." option of the "git for-each-ref" command (and + its friends, i.e. the listing mode of "git branch/tag"), "%(atom:)" + (e.g. "%(refname:)", "%(body:)" used to error out. Instead, treat + them as if the colon and an empty string that follows it were not + there. + + * Users with "color.ui = always" in their configuration were broken + by a recent change that made plumbing commands to pay attention to + them as the patch created internally by "git add -p" were colored + (heh) and made unusable. This has been fixed. + + * "git branch -M a b" while on a branch that is completely unrelated + to either branch a or branch b misbehaved when multiple worktree + was in use. This has been fixed. + + * "git fast-export" with -M/-C option issued "copy" instruction on a + path that is simultaneously modified, which was incorrect. + + * The checkpoint command "git fast-import" did not flush updates to + refs and marks unless at least one object was created since the + last checkpoint, which has been corrected, as these things can + happen without any new object getting created. + + * The scripts to drive TravisCI has been reorganized and then an + optimization to avoid spending cycles on a branch whose tip is + tagged has been implemented. + + * "git fetch <there> <src>:<dst>" allows an object name on the <src> + side when the other side accepts such a request since Git v2.5, but + the documentation was left stale. + + * A regression in 2.11 that made the code to read the list of + alternate object stores overrun the end of the string has been + fixed. + +Also contains various documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.15.0.txt b/Documentation/RelNotes/2.15.0.txt index 1be62c9e27..cdd761bcc2 100644 --- a/Documentation/RelNotes/2.15.0.txt +++ b/Documentation/RelNotes/2.15.0.txt @@ -8,12 +8,12 @@ Backward compatibility notes and other notable changes. more explicit '.' for that instead. The hope is that existing users will not mind this change, and eventually the warning can be turned into a hard error, upgrading the deprecation into removal of - this (mis)feature. That is now scheduled to happen in the upcoming - release. + this (mis)feature. That is now scheduled to happen in Git v2.16, + the next major release after this one. * Git now avoids blindly falling back to ".git" when the setup sequence said we are _not_ in Git repository. A corner case that - happens to work right now may be broken by a call to die("BUG"). + happens to work right now may be broken by a call to BUG(). We've tried hard to locate such cases and fixed them, but there might still be cases that need to be addressed--bug reports are greatly appreciated. @@ -61,7 +61,11 @@ UI, Workflows & Features other options to make it easier for scripts to grab existing trailer lines from a commit log message. - * "gitweb" shows a link to visit the 'raw' contents of blbos in the + * The "--format=%(trailers)" option "git log" and its friends take + learned to take the 'unfold' and 'only' modifiers to normalize its + output, e.g. "git log --format=%(trailers:only,unfold)". + + * "gitweb" shows a link to visit the 'raw' contents of blobs in the history overview page. * "[gc] rerereResolved = 5.days" used to be invalid, as the variable @@ -95,19 +99,23 @@ UI, Workflows & Features operations in the same repository. The new "--no-optional-locks" option can be passed to Git to disable them. + * "git for-each-ref --format=..." learned a new format element, + %(trailers), to show only the commit log trailer part of the log + message. + Performance, Internal Implementation, Development Support etc. * Conversion from uchar[20] to struct object_id continues. * Start using selected c99 constructs in small, stable and - essentialpart of the system to catch people who care about + essential part of the system to catch people who care about older compilers that do not grok them. * The filter-process interface learned to allow a process with long latency give a "delayed" response. - * Many uses of comparision callback function the hashmap API uses + * Many uses of comparison callback function the hashmap API uses cast the callback function type when registering it to hashmap_init(), which defeats the compile time type checking when the callback interface changes (e.g. gaining more parameters). @@ -125,7 +133,6 @@ Performance, Internal Implementation, Development Support etc. * A helper function to read a single whole line into strbuf mistakenly triggered OOM error at EOF under certain conditions, which has been fixed. - (merge 642956cf45 rs/strbuf-getwholeline-fix later to maint). * The "ref-store" code reorganization continues. @@ -222,6 +229,16 @@ Performance, Internal Implementation, Development Support etc. * Add comment to clarify that the style file is meant to be used with clang-5 and the rules are still work in progress. + * Many variables that points at a region of memory that will live + throughout the life of the program have been marked with UNLEAK + marker to help the leak checkers concentrate on real leaks.. + + * Plans for weaning us off of SHA-1 has been documented. + + * A new "oidmap" API has been introduced and oidset API has been + rewritten to use it. + + Also contains various documentation updates and code clean-ups. @@ -324,7 +341,6 @@ Fixes since v2.14 was taught to "git send-email" as a valid way to tell it that it needs to also send a carbon copy to <a@dd.re.ss> in the trailer section. - (merge cc90750677 mm/send-email-cc-cruft later to maint). * "git branch -M a b" while on a branch that is completely unrelated to either branch a or branch b misbehaved when multiple worktree @@ -338,7 +354,6 @@ Fixes since v2.14 garbage collection. * A regression to "gitk --bisect" by a recent update has been fixed. - (merge 1d0538e486 mh/packed-ref-store-prep later to maint). * "git -c submodule.recurse=yes pull" did not work as if the "--recurse-submodules" option was given from the command line. @@ -348,7 +363,6 @@ Fixes since v2.14 pass the contents of the file verbatim and instead completed an incomplete line at the end, if exists. The latter has been updated to match the behaviour of the former. - (merge c818e74332 rk/commit-tree-make-F-verbatim later to maint). * Many codepaths did not diagnose write failures correctly when disks go full, due to their misuse of write_in_full() helper function, @@ -361,10 +375,8 @@ Fixes since v2.14 * "git archive", especially when used with pathspec, stored an empty directory in its output, even though Git itself never does so. This has been fixed. - (merge 4318094047 rs/archive-excluded-directory later to maint). * API error-proofing which happens to also squelch warnings from GCC. - (merge c788c54cde tg/refs-allowed-flags later to maint). * The explanation of the cut-line in the commit log editor has been slightly tweaked. @@ -374,7 +386,6 @@ Fixes since v2.14 reading and writing pid/host from and to a lock file; it used to use an incorrect fscanf() format when reading, which has been corrected. - (merge afe2fab72c aw/gc-lockfile-fscanf-fix later to maint). * The scripts to drive TravisCI has been reorganized and then an optimization to avoid spending cycles on a branch whose tip is @@ -382,10 +393,8 @@ Fixes since v2.14 (merge 8376eb4a8f ls/travis-scriptify later to maint). * The test linter has been taught that we do not like "echo -e". - (merge 1a6d46895d tb/test-lint-echo-e later to maint). * Code cmp.std.c nitpick. - (merge ac7da78ede mh/for-each-string-list-item-empty-fix later to maint). * A regression fix for 2.11 that made the code to read the list of alternate object stores overrun the end of the string. @@ -394,7 +403,6 @@ Fixes since v2.14 * "git describe --match" learned to take multiple patterns in v2.13 series, but the feature ignored the patterns after the first one and did not work at all. This has been fixed. - (merge da769d2986 jk/describe-omit-some-refs later to maint). * "git filter-branch" cannot reproduce a history with a tag without the tagger field, which only ancient versions of Git allowed to be @@ -403,17 +411,14 @@ Fixes since v2.14 * "git cat-file --textconv" started segfaulting recently, which has been corrected. - (merge cc0ea7c9e5 jk/diff-blob later to maint). * The built-in pattern to detect the "function header" for HTML did not match <H1>..<H6> elements without any attributes, which has been fixed. - (merge 9c03caca2c ik/userdiff-html-h-element-fix later to maint). * "git mailinfo" was loose in decoding quoted printable and produced garbage when the two letters after the equal sign are not hexadecimal. This has been fixed. - (merge c8cf423eab rs/mailinfo-qp-decode-fix later to maint). * The machinery to create xdelta used in pack files received the sizes of the data in size_t, but lost the higher bits of them by @@ -427,7 +432,6 @@ Fixes since v2.14 * The documentation for '-X<option>' for merges was misleadingly written to suggest that "-s theirs" exists, which is not the case. - (merge c25d98b2a7 jc/merge-x-theirs-docfix later to maint). * "git fast-export" with -M/-C option issued "copy" instruction on a path that is simultaneously modified, which was incorrect. @@ -453,31 +457,52 @@ Fixes since v2.14 * Spell the name of our system as "Git" in the output from request-pull script. - (merge e66d7c37a5 ar/request-pull-phrasofix later to maint). + + * Fixes for a handful memory access issues identified by valgrind. + + * Backports a moral equivalent of 2015 fix to the poll() emulation + from the upstream gnulib to fix occasional breakages on HPE NonStop. + + * Users with "color.ui = always" in their configuration were broken + by a recent change that made plumbing commands to pay attention to + them as the patch created internally by "git add -p" were colored + (heh) and made unusable. This has been fixed by reverting the + offending change. + + * In the "--format=..." option of the "git for-each-ref" command (and + its friends, i.e. the listing mode of "git branch/tag"), "%(atom:)" + (e.g. "%(refname:)", "%(body:)" used to error out. Instead, treat + them as if the colon and an empty string that follows it were not + there. + + * An ancient bug that made Git misbehave with creation/renaming of + refs has been fixed. + + * "git fetch <there> <src>:<dst>" allows an object name on the <src> + side when the other side accepts such a request since Git v2.5, but + the documentation was left stale. + (merge 83558a412a jc/fetch-refspec-doc-update later to maint). + + * Update the documentation for "git filter-branch" so that the filter + options are listed in the same order as they are applied, as + described in an earlier part of the doc. + (merge 07c4984508 dg/filter-branch-filter-order-doc later to maint). + + * A possible oom error is now caught as a fatal error, instead of + continuing and dereferencing NULL. + (merge 55d7d15847 ao/path-use-xmalloc later to maint). * Other minor doc, test and build updates and code cleanups. (merge f094b89a4d ma/parse-maybe-bool later to maint). - (merge 39b00fa4d4 jk/drop-sha1-entry-pos later to maint). (merge 6cdf8a7929 ma/ts-cleanups later to maint). (merge 7560f547e6 ma/up-to-date later to maint). (merge 0db3dc75f3 rs/apply-epoch later to maint). - (merge 74f1bd912b dw/diff-highlight-makefile-fix later to maint). - (merge f991761eb8 jk/config-lockfile-leak-fix later to maint). - (merge 150efef1e7 ma/pkt-line-leakfix later to maint). - (merge 5554451de6 mg/timestamp-t-fix later to maint). (merge 276d0e35c0 ma/split-symref-update-fix later to maint). - (merge 3bc4b8f7c7 bb/doc-eol-dirty later to maint). - (merge c1bb33c99c jk/system-path-cleanup later to maint). - (merge ab46e6fc72 cc/subprocess-handshake-missing-capabilities later to maint). - (merge f7a32dd97f kd/doc-for-each-ref later to maint). - (merge be94568bc7 ez/doc-duplicated-words-fix later to maint). - (merge 01e4be6c3d ks/test-readme-phrasofix later to maint). - (merge 217bb56d4f hn/typofix later to maint). - (merge c08fd6388c jk/doc-read-tree-table-asciidoctor-fix later to maint). - (merge c3342b362e ks/doc-use-camelcase-for-config-name later to maint). - (merge 0bca165fdb jk/validate-headref-fix later to maint). - (merge 93dbefb389 mr/doc-negative-pathspec later to maint). - (merge 5e633326e4 ad/doc-markup-fix later to maint). - (merge 9ca356fa8b rs/cocci-de-paren-call-params later to maint). - (merge 7099153e8d rs/tag-null-pointer-arith-fix later to maint). - (merge 0e187d758c rs/run-command-use-alloc-array later to maint). + (merge f777623514 ks/branch-tweak-error-message-for-extra-args later to maint). + (merge 33f3c683ec ks/verify-filename-non-option-error-message-tweak later to maint). + (merge 7cbbf9d6a2 ls/filter-process-delayed later to maint). + (merge 488aa65c8f wk/merge-options-gpg-sign-doc later to maint). + (merge e61cb19a27 jc/branch-force-doc-readability-fix later to maint). + (merge 32fceba3fd np/config-path-doc later to maint). + (merge e38c681fb7 sb/rev-parse-show-superproject-root later to maint). + (merge 4f851dc883 sg/rev-list-doc-reorder-fix later to maint). diff --git a/Documentation/RelNotes/2.16.0.txt b/Documentation/RelNotes/2.16.0.txt new file mode 100644 index 0000000000..e46197f478 --- /dev/null +++ b/Documentation/RelNotes/2.16.0.txt @@ -0,0 +1,166 @@ +Git 2.16 Release Notes +====================== + +Backward compatibility notes and other notable changes. + + * Use of an empty string as a pathspec element that is used for + 'everything matches' is now an error. + + +Updates since v2.15 +------------------- + +UI, Workflows & Features + + * An empty string as a pathspec element that means "everything" + i.e. 'git add ""', is now illegal. We started this by first + deprecating and warning a pathspec that has such an element in + 2.11 (Nov 2016). + + * A hook script that is set unexecutable is simply ignored. Git + notifies when such a file is ignored, unless the message is + squelched via advice.ignoredHook configuration. + + * "git pull" has been taught to accept "--[no-]signoff" option and + pass it down to "git merge". + + * The "--push-option=<string>" option to "git push" now defaults to a + list of strings configured via push.pushOption variable. + + * "gitweb" checks if a directory is searchable with Perl's "-x" + operator, which can be enhanced by using "filetest 'access'" + pragma, which now we do. + + * "git stash save" has been deprecated in favour of "git stash push". + + +Performance, Internal Implementation, Development Support etc. + + * An earlier update made it possible to use an on-stack in-core + lockfile structure (as opposed to having to deliberately leak an + on-heap one). Many codepaths have been updated to take advantage + of this new facility. + + * Calling cmd_foo() as if it is a general purpose helper function is + a no-no. Correct two instances of such to set an example. + + * We try to see if somebody runs our test suite with a shell that + does not support "local" like bash/dash does. + + * An early part of piece-by-piece rewrite of "git bisect" in C. + + * GSoC to piece-by-piece rewrite "git submodule" in C. + + * Optimize the code to find shortest unique prefix of object names. + + * Pathspec-limited revision traversal was taught not to keep finding + unneeded differences once it knows two trees are different inside + given pathspec. + + * Conversion from uchar[20] to struct object_id continues. + + * Code cleanup. + (merge 62a24c8923 rs/hex-to-bytes-cleanup later to maint). + + * A single-word "unsigned flags" in the diff options is being split + into a structure with many bitfields. + (merge 0d1e0e7801 bw/diff-opt-impl-to-bitfields later to maint). + + * TravisCI build updates. + (merge c2154953b8 sg/travis-fixes later to maint). + + +Also contains various documentation updates and code clean-ups. + + +Fixes since v2.15 +----------------- + + * "auto" as a value for the columnar output configuration ought to + judge "is the output consumed by humans?" with the same criteria as + "auto" for coloured output configuration, i.e. either the standard + output stream is going to tty, or a pager is in use. We forgot the + latter, which has been fixed. + (merge 965ff23a43 kd/auto-col-with-pager-fix later to maint). + + * The experimental "color moved lines differently in diff output" + feature was buggy around "ignore whitespace changes" edges, whihch + has been corrected. + (merge b66b507292 jk/diff-color-moved-fix later to maint). + + * Instead of using custom line comparison and hashing functions to + implement "moved lines" coloring in the diff output, use the pair + of these functions from lower-layer xdiff/ code. + (merge 01be97c2b2 sb/diff-color-moved-use-xdl-recmatch later to maint). + + * Some codepaths did not check for errors when asking what branch the + HEAD points at, which have been fixed. + (merge dbd2b55cb7 jk/misc-resolve-ref-unsafe-fixes later to maint). + + * "git commit", after making a commit, did not check for errors when + asking on what branch it made the commit, which has been correted. + (merge c26de08370 ao/check-resolve-ref-unsafe-result later to maint). + + * "git status --ignored -u" did not stop at a working tree of a + separate project that is embedded in an ignored directory and + listed files in that other project, instead of just showing the + directory itself as ignored. + (merge fadb4820c4 js/submodule-in-excluded later to maint). + + * A broken access to object databases in recent update to "git grep + --recurse-submodules" has been fixed. + (merge 9560e6245a bw/grep-recurse-submodules later to maint). + + * A recent regression in "git rebase -i" that broke execution of git + commands from subdirectories via "exec" insn has been fixed. + (merge 09d7b6c6fa jk/rebase-i-exec-gitdir-fix later to maint). + + * A (possibly flakey) test fix. + (merge cff48ccf2a jc/t5601-copy-workaround later to maint). + + * "git check-ref-format --branch @{-1}" bit a "BUG()" when run + outside a repository for obvious reasons; clarify the documentation + and make sure we do not even try to expand the at-mark magic in + such a case, but still call the validation logic for branch names. + (merge 89dd32aedc jc/check-ref-format-oor later to maint). + + * "git fetch --recurse-submodules" now knows that submodules can be + moved around in the superproject in addition to getting updated, + and finds the ones that need to be fetched accordingly. + (merge 4b4acedd61 hv/fetch-moved-submodules-on-demand later to maint). + + * Command line completion (in contrib/) update. + (merge 6357d9d004 tb/complete-checkout later to maint). + + * Description of blame.{showroot,blankboundary,showemail,date} + configuration variables have been added to "git config --help". + (merge de0bc11d13 sb/blame-config-doc later to maint). + + * After an error from lstat(), diff_populate_filespec() function + sometimes still went ahead and used invalid data in struct stat, + which has been fixed. + (merge 10e0ca843d ao/diff-populate-filespec-lstat-errorpath-fix later to maint). + + * UNC paths are also relevant in Cygwin builds and they are now + tested just like Mingw builds. + (merge f21d60b429 ad/5580-unc-tests-on-cygwin later to maint). + + * Correct start-up sequence so that a repository could be placed + immediately under the root directory again (which was broken at + around Git 2.13). + (merge fa4d8c783d js/early-config later to maint). + + * The credential helper for libsecret (in contrib/) has been improved + to allow possibly prompting the end user to unlock secrets that are + currently locked (otherwise the secrets may not be loaded). + (merge 9c109e9bbc dk/libsecret-unlock-to-load-fix later to maint). + + * MinGW updates. + (merge 39bb86b4e5 js/mingw-full-version-in-resources later to maint). + (merge 601e1e7897 js/wincred-empty-cred later to maint). + (merge b2f55717c7 js/mingw-redirect-std-handles later to maint). + + * Other minor doc, test and build updates and code cleanups. + (merge bab76141da cn/diff-indent-no-longer-is-experimental later to maint). + (merge 8684dde10d jm/relnotes-2.15-typofix later to maint). + (merge cd3f8e2fc2 ks/mailmap later to maint). diff --git a/Documentation/config.txt b/Documentation/config.txt index 1ac0ae6adb..671fcbaa0f 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -351,6 +351,9 @@ advice.*:: addEmbeddedRepo:: Advice on what to do when you've accidentally added one git repo inside of another. + ignoredHook:: + Advice shown if an hook is ignored because the hook is not + set as executable. -- core.fileMode:: @@ -949,6 +952,23 @@ apply.whitespace:: Tells 'git apply' how to handle whitespaces, in the same way as the `--whitespace` option. See linkgit:git-apply[1]. +blame.showRoot:: + Do not treat root commits as boundaries in linkgit:git-blame[1]. + This option defaults to false. + +blame.blankBoundary:: + Show blank commit object name for boundary commits in + linkgit:git-blame[1]. This option defaults to false. + +blame.showEmail:: + Show the author email instead of author name in linkgit:git-blame[1]. + This option defaults to false. + +blame.date:: + Specifies the format used to output dates in linkgit:git-blame[1]. + If unset the iso format is used. For supported values, + see the discussion of the `--date` option at linkgit:git-log[1]. + branch.autoSetupMerge:: Tells 'git branch' and 'git checkout' to set up new branches so that linkgit:git-pull[1] will appropriately merge from the @@ -2621,6 +2641,35 @@ push.gpgSign:: override a value from a lower-priority config file. An explicit command-line flag always overrides this config option. +push.pushOption:: + When no `--push-option=<option>` argument is given from the + command line, `git push` behaves as if each <value> of + this variable is given as `--push-option=<value>`. ++ +This is a multi-valued variable, and an empty value can be used in a +higher priority configuration file (e.g. `.git/config` in a +repository) to clear the values inherited from a lower priority +configuration files (e.g. `$HOME/.gitconfig`). ++ +-- + +Example: + +/etc/gitconfig + push.pushoption = a + push.pushoption = b + +~/.gitconfig + push.pushoption = c + +repo/.git/config + push.pushoption = + push.pushoption = b + +This will result in only b (a and c are cleared). + +-- + push.recurseSubmodules:: Make sure all submodule commits used by the revisions to be pushed are available on a remote-tracking branch. If the value is 'check' diff --git a/Documentation/diff-heuristic-options.txt b/Documentation/diff-heuristic-options.txt deleted file mode 100644 index d4f3d95505..0000000000 --- a/Documentation/diff-heuristic-options.txt +++ /dev/null @@ -1,5 +0,0 @@ ---indent-heuristic:: ---no-indent-heuristic:: - These are to help debugging and tuning experimental heuristics - (which are off by default) that shift diff hunk boundaries to - make patches easier to read. diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index a88c76741e..dd0dba5b1d 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -63,7 +63,12 @@ ifndef::git-format-patch[] Synonym for `-p --raw`. endif::git-format-patch[] -include::diff-heuristic-options.txt[] +--indent-heuristic:: + Enable the heuristic that shift diff hunk boundaries to make patches + easier to read. This is the default. + +--no-indent-heuristic:: + Disable the indent heuristic. --minimal:: Spend extra time to make sure the smallest possible diff --git a/Documentation/git-annotate.txt b/Documentation/git-annotate.txt index 94be4b85e0..05fd482b74 100644 --- a/Documentation/git-annotate.txt +++ b/Documentation/git-annotate.txt @@ -23,7 +23,6 @@ familiar command name for people coming from other SCM systems. OPTIONS ------- include::blame-options.txt[] -include::diff-heuristic-options.txt[] SEE ALSO -------- diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt index fdc3aea30a..16323eb80e 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.txt @@ -89,8 +89,6 @@ include::blame-options.txt[] abbreviated object name, use <n>+1 digits. Note that 1 column is used for a caret to mark the boundary commit. -include::diff-heuristic-options.txt[] - THE PORCELAIN FORMAT -------------------- diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index fe029ac6fc..d6587c5e96 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -104,8 +104,8 @@ OPTIONS -f:: --force:: - Reset <branchname> to <startpoint> if <branchname> exists - already. Without `-f` 'git branch' refuses to change an existing branch. + Reset <branchname> to <startpoint>, even if <branchname> exists + already. Without `-f`, 'git branch' refuses to change an existing branch. In combination with `-d` (or `--delete`), allow deleting the branch irrespective of its merged status. In combination with `-m` (or `--move`), allow renaming the branch even if the new diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt index 92777cef25..cf0a0b7df2 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.txt @@ -77,7 +77,14 @@ reference name expressions (see linkgit:gitrevisions[7]): . at-open-brace `@{` is used as a notation to access a reflog entry. -With the `--branch` option, it expands the ``previous branch syntax'' +With the `--branch` option, the command takes a name and checks if +it can be used as a valid branch name (e.g. when creating a new +branch). The rule `git check-ref-format --branch $name` implements +may be stricter than what `git check-ref-format refs/heads/$name` +says (e.g. a dash may appear at the beginning of a ref component, +but it is explicitly forbidden at the beginning of a branch name). +When run with `--branch` option in a repository, the input is first +expanded for the ``previous branch syntax'' `@{-n}`. For example, `@{-1}` is a way to refer the last branch you were on. This option should be used by porcelains to accept this syntax anywhere a branch name is expected, so they can act as if you diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index bd268a8fcc..e108b0f74b 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -13,7 +13,8 @@ SYNOPSIS 'git checkout' [-q] [-f] [-m] [--detach] <commit> 'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>] 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>... -'git checkout' [-p|--patch] [<tree-ish>] [--] [<paths>...] +'git checkout' [<tree-ish>] [--] <pathspec>... +'git checkout' (-p|--patch) [<tree-ish>] [--] [<paths>...] DESCRIPTION ----------- @@ -78,20 +79,13 @@ be used to detach HEAD at the tip of the branch (`git checkout + Omitting <branch> detaches HEAD at the tip of the current branch. -'git checkout' [-p|--patch] [<tree-ish>] [--] <pathspec>...:: +'git checkout' [<tree-ish>] [--] <pathspec>...:: - When <paths> or `--patch` are given, 'git checkout' does *not* - switch branches. It updates the named paths in the working tree - from the index file or from a named <tree-ish> (most often a - commit). In this case, the `-b` and `--track` options are - meaningless and giving either of them results in an error. The - <tree-ish> argument can be used to specify a specific tree-ish - (i.e. commit, tag or tree) to update the index for the given - paths before updating the working tree. -+ -'git checkout' with <paths> or `--patch` is used to restore modified or -deleted paths to their original contents from the index or replace paths -with the contents from a named <tree-ish> (most often a commit-ish). + Overwrite paths in the working tree by replacing with the + contents in the index or in the <tree-ish> (most often a + commit). When a <tree-ish> is given, the paths that + match the <pathspec> are updated both in the index and in + the working tree. + The index may contain unmerged entries because of a previous failed merge. By default, if you try to check out such an entry from the index, the @@ -101,6 +95,14 @@ specific side of the merge can be checked out of the index by using `--ours` or `--theirs`. With `-m`, changes made to the working tree file can be discarded to re-create the original conflicted merge result. +'git checkout' (-p|--patch) [<tree-ish>] [--] [<pathspec>...]:: + This is similar to the "check out paths to the working tree + from either the index or from a tree-ish" mode described + above, but lets you use the interactive interface to show + the "diff" output and choose which hunks to use in the + result. See below for the description of `--patch` option. + + OPTIONS ------- -q:: diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 83f86b9231..4edd09fc6b 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -174,11 +174,11 @@ See also <<FILES>>. either --bool or --int, as described above. --path:: - 'git-config' will expand leading '{tilde}' to the value of - '$HOME', and '{tilde}user' to the home directory for the + `git config` will expand a leading `~` to the value of + `$HOME`, and `~user` to the home directory for the specified user. This option has no effect when setting the - value (but you can use 'git config bla {tilde}/' from the - command line to let your shell do the expansion). + value (but you can use `git config section.variable ~/` + from the command line to let your shell do the expansion). -z:: --null:: diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index bebdcdec5a..3a52e4dce3 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -8,11 +8,11 @@ git-filter-branch - Rewrite branches SYNOPSIS -------- [verse] -'git filter-branch' [--setup <command>] [--env-filter <command>] - [--tree-filter <command>] [--index-filter <command>] - [--parent-filter <command>] [--msg-filter <command>] - [--commit-filter <command>] [--tag-name-filter <command>] - [--subdirectory-filter <directory>] [--prune-empty] +'git filter-branch' [--setup <command>] [--subdirectory-filter <directory>] + [--env-filter <command>] [--tree-filter <command>] + [--index-filter <command>] [--parent-filter <command>] + [--msg-filter <command>] [--commit-filter <command>] + [--tag-name-filter <command>] [--prune-empty] [--original <namespace>] [-d <directory>] [-f | --force] [--state-branch <branch>] [--] [<rev-list options>...] @@ -89,6 +89,11 @@ OPTIONS can be used or modified in the following filter steps except the commit filter, for technical reasons. +--subdirectory-filter <directory>:: + Only look at the history which touches the given subdirectory. + The result will contain that directory (and only that) as its + project root. Implies <<Remap_to_ancestor>>. + --env-filter <command>:: This filter may be used if you only need to modify the environment in which the commit will be performed. Specifically, you might @@ -167,11 +172,6 @@ be removed, buyer beware. There is also no support for changing the author or timestamp (or the tag message for that matter). Tags which point to other tags will be rewritten to point to the underlying commit. ---subdirectory-filter <directory>:: - Only look at the history which touches the given subdirectory. - The result will contain that directory (and only that) as its - project root. Implies <<Remap_to_ancestor>>. - --prune-empty:: Some filters will generate empty commits that leave the tree untouched. This option instructs git-filter-branch to remove such commits if they diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index 174af2c0ec..dffa14a795 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -57,6 +57,11 @@ OPTIONS `xx`; for example `%00` interpolates to `\0` (NUL), `%09` to `\t` (TAB) and `%0a` to `\n` (LF). +--color[=<when>]: + Respect any colors specified in the `--format` option. The + `<when>` field must be one of `always`, `never`, or `auto` (if + `<when>` is absent, behave as if `always` was given). + --shell:: --perl:: --python:: @@ -220,11 +225,15 @@ and `date` to extract the named component. The complete message in a commit and tag object is `contents`. Its first line is `contents:subject`, where subject is the concatenation of all lines of the commit message up to the first blank line. The next -line is 'contents:body', where body is all of the lines after the first +line is `contents:body`, where body is all of the lines after the first blank line. The optional GPG signature is `contents:signature`. The first `N` lines of the message is obtained using `contents:lines=N`. Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1] -are obtained as 'contents:trailers'. +are obtained as `trailers` (or by using the historical alias +`contents:trailers`). Non-trailer lines from the trailer block can be omitted +with `trailers:only`. Whitespace-continuations can be removed from trailers so +that each trailer appears on a line by itself with its full content with +`trailers:unfold`. Both can be used together as `trailers:unfold,only`. For sorting purposes, fields with numeric values sort in numeric order (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`). diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 4df6431c34..d5dfd8430f 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -64,20 +64,6 @@ OPTIONS ------- include::merge-options.txt[] ---signoff:: - Add Signed-off-by line by the committer at the end of the commit - log message. The meaning of a signoff depends on the project, - but it typically certifies that committer has - the rights to submit this work under the same license and - agrees to a Developer Certificate of Origin - (see http://developercertificate.org/ for more information). - --S[<keyid>]:: ---gpg-sign[=<keyid>]:: - GPG-sign the resulting merge commit. The `keyid` argument is - optional and defaults to the committer identity; if specified, - it must be stuck to the option without a space. - -m <msg>:: Set the commit message to be used for the merge commit (in case one is created). diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 3e76e99f38..5b08302fc2 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -156,11 +156,17 @@ already exists on the remote side. Either all refs are updated, or on error, no refs are updated. If the server does not support atomic pushes the push will fail. --o:: ---push-option:: +-o <option>:: +--push-option=<option>:: Transmit the given string to the server, which passes them to the pre-receive as well as the post-receive hook. The given string must not contain a NUL or LF character. + When multiple `--push-option=<option>` are given, they are + all sent to the other side in the order listed on the + command line. + When no `--push-option=<option>` is given from the command + line, the values of configuration variable `push.pushOption` + are used instead. --receive-pack=<git-receive-pack>:: --exec=<git-receive-pack>:: diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 0917b8207b..95326b85ff 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -264,7 +264,7 @@ print a message to stderr and exit with nonzero status. --show-toplevel:: Show the absolute path of the top-level directory. ---show-superproject-working-tree +--show-superproject-working-tree:: Show the absolute path of the root of the superproject's working tree (if exists) that uses the current repository as its submodule. Outputs nothing if the current repository is diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt index 00f95fee1f..8be661007d 100644 --- a/Documentation/git-stash.txt +++ b/Documentation/git-stash.txt @@ -13,8 +13,6 @@ SYNOPSIS 'git stash' drop [-q|--quiet] [<stash>] 'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>] 'git stash' branch <branchname> [<stash>] -'git stash' save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] - [-u|--include-untracked] [-a|--all] [<message>] 'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all] [-m|--message <message>]] [--] [<pathspec>...]] @@ -33,7 +31,7 @@ and reverts the working directory to match the `HEAD` commit. The modifications stashed away by this command can be listed with `git stash list`, inspected with `git stash show`, and restored (potentially on top of a different commit) with `git stash apply`. -Calling `git stash` without any arguments is equivalent to `git stash save`. +Calling `git stash` without any arguments is equivalent to `git stash push`. A stash is by default listed as "WIP on 'branchname' ...", but you can give a more descriptive message on the command line when you create one. @@ -48,7 +46,6 @@ stash index (e.g. the integer `n` is equivalent to `stash@{n}`). OPTIONS ------- -save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]:: push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]:: Save your local modifications to a new 'stash entry' and roll them @@ -87,6 +84,12 @@ linkgit:git-add[1] to learn how to operate the `--patch` mode. The `--patch` option implies `--keep-index`. You can use `--no-keep-index` to override this. +save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]:: + + This option is deprecated in favour of 'git stash push'. It + differs from "stash push" in that it cannot take pathspecs, + and any non-option arguments form the message. + list [<options>]:: List the stash entries that you currently have. Each 'stash entry' is @@ -118,7 +121,7 @@ pop [--index] [-q|--quiet] [<stash>]:: Remove a single stashed state from the stash list and apply it on top of the current working tree state, i.e., do the inverse - operation of `git stash save`. The working directory must + operation of `git stash push`. The working directory must match the index. + Applying the state can fail with conflicts; in this case, it is not @@ -137,7 +140,7 @@ apply [--index] [-q|--quiet] [<stash>]:: Like `pop`, but do not remove the state from the stash list. Unlike `pop`, `<stash>` may be any commit that looks like a commit created by - `stash save` or `stash create`. + `stash push` or `stash create`. branch <branchname> [<stash>]:: @@ -148,7 +151,7 @@ branch <branchname> [<stash>]:: `stash@{<revision>}`, it then drops the `<stash>`. When no `<stash>` is given, applies the latest one. + -This is useful if the branch on which you ran `git stash save` has +This is useful if the branch on which you ran `git stash push` has changed enough that `git stash apply` fails due to conflicts. Since the stash entry is applied on top of the commit that was HEAD at the time `git stash` was run, it restores the originally stashed state @@ -255,14 +258,14 @@ $ git stash pop Testing partial commits:: -You can use `git stash save --keep-index` when you want to make two or +You can use `git stash push --keep-index` when you want to make two or more commits out of the changes in the work tree, and you want to test each change before committing: + ---------------------------------------------------------------- # ... hack hack hack ... $ git add --patch foo # add just first part to the index -$ git stash save --keep-index # save all other changes to the stash +$ git stash push --keep-index # save all other changes to the stash $ edit/build/test first part $ git commit -m 'First part' # commit fully tested change $ git stash pop # prepare to work on all other changes diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 9f3a78a36c..fc282e0a92 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This implies diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 95e9f391d8..956fc019f9 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -115,6 +115,11 @@ options for details. variable if it exists, or lexicographic order otherwise. See linkgit:git-config[1]. +--color[=<when>]: + Respect any colors specified in the `--format` option. The + `<when>` field must be one of `always`, `never`, or `auto` (if + `<when>` is absent, behave as if `always` was given). + -i:: --ignore-case:: Sorting and filtering tags are case insensitive. diff --git a/Documentation/git.txt b/Documentation/git.txt index 7a1d629ca0..463b0eb0f5 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -709,6 +709,24 @@ of clones and fetches. the background which do not want to cause lock contention with other operations on the repository. Defaults to `1`. +`GIT_REDIRECT_STDIN`:: +`GIT_REDIRECT_STDOUT`:: +`GIT_REDIRECT_STDERR`:: + Windows-only: allow redirecting the standard input/output/error + handles to paths specified by the environment variables. This is + particularly useful in multi-threaded applications where the + canonical way to pass standard handles via `CreateProcess()` is + not an option because it would require the handles to be marked + inheritable (and consequently *every* spawned process would + inherit them, possibly blocking regular Git operations). The + primary intended use case is to use named pipes for communication + (e.g. `\\.\pipe\my-git-stdin-123`). ++ +Two special values are supported: `off` will simply close the +corresponding standard handle, and if `GIT_REDIRECT_STDERR` is +`2>&1`, standard error will be redirected to the same handle as +standard output. + Discussion[[Discussion]] ------------------------ diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt index 177610e44e..02569d0614 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.txt @@ -40,7 +40,7 @@ beginning. It is always easier to squash a few commits together than to split one big commit into several. Don't be afraid of making too small or imperfect steps along the way. You can always go back later and edit the commits with `git rebase --interactive` before you -publish them. You can use `git stash save --keep-index` to run the +publish them. You can use `git stash push --keep-index` to run the test suite independent of other uncommitted changes; see the EXAMPLES section of linkgit:git-stash[1]. diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 4e32304301..3888c3ff85 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -42,6 +42,12 @@ set to `no` at the beginning of them. current `HEAD` is already up to date or the merge can be resolved as a fast-forward. +-S[<keyid>]:: +--gpg-sign[=<keyid>]:: + GPG-sign the resulting merge commit. The `keyid` argument is + optional and defaults to the committer identity; if specified, + it must be stuck to the option without a space. + --log[=<n>]:: --no-log:: In addition to branch names, populate the log message with @@ -51,6 +57,16 @@ set to `no` at the beginning of them. With --no-log do not list one-line descriptions from the actual commits being merged. +--signoff:: +--no-signoff:: + Add Signed-off-by line by the committer at the end of the commit + log message. The meaning of a signoff depends on the project, + but it typically certifies that committer has + the rights to submit this work under the same license and + agrees to a Developer Certificate of Origin + (see http://developercertificate.org/ for more information). ++ +With --no-signoff do not add a Signed-off-by line. --stat:: -n:: diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index 1ebbf1d738..c579793af5 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -23,9 +23,11 @@ ifdef::git-pull[] endif::git-pull[] + The format of a <refspec> parameter is an optional plus -`+`, followed by the source ref <src>, followed +`+`, followed by the source <src>, followed by a colon `:`, followed by the destination ref <dst>. -The colon can be omitted when <dst> is empty. +The colon can be omitted when <dst> is empty. <src> is +typically a ref, but it can also be a fully spelled hex object +name. + `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`; it requests fetching everything up to the given tag. diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 7d860bfca1..13501e1556 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -799,11 +799,11 @@ endif::git-rev-list[] --parents:: Print also the parents of the commit (in the form "commit parent..."). - Also enables parent rewriting, see 'History Simplification' below. + Also enables parent rewriting, see 'History Simplification' above. --children:: Print also the children of the commit (in the form "commit child..."). - Also enables parent rewriting, see 'History Simplification' below. + Also enables parent rewriting, see 'History Simplification' above. ifdef::git-rev-list[] --timestamp:: @@ -846,7 +846,7 @@ you would get an output like this: to be drawn properly. Cannot be combined with `--no-walk`. + -This enables parent rewriting, see 'History Simplification' below. +This enables parent rewriting, see 'History Simplification' above. + This implies the `--topo-order` option by default, but the `--date-order` option may also be specified. diff --git a/Documentation/technical/api-argv-array.txt b/Documentation/technical/api-argv-array.txt index cfc063018c..870c8edbfb 100644 --- a/Documentation/technical/api-argv-array.txt +++ b/Documentation/technical/api-argv-array.txt @@ -8,7 +8,7 @@ always NULL-terminated at the element pointed to by `argv[argc]`. This makes the result suitable for passing to functions expecting to receive argv from main(), or the link:api-run-command.html[run-command API]. -The link:api-string-list.html[string-list API] is similar, but cannot be +The string-list API (documented in string-list.h) is similar, but cannot be used for these purposes; instead of storing a straight string pointer, it contains an item structure with a `util` field that is not compatible with the traditional argv interface. diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt index 6c77b4920c..7fae00f44f 100644 --- a/Documentation/technical/api-directory-listing.txt +++ b/Documentation/technical/api-directory-listing.txt @@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`::: @@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt new file mode 100644 index 0000000000..417ba491d0 --- /dev/null +++ b/Documentation/technical/hash-function-transition.txt @@ -0,0 +1,797 @@ +Git hash function transition +============================ + +Objective +--------- +Migrate Git from SHA-1 to a stronger hash function. + +Background +---------- +At its core, the Git version control system is a content addressable +filesystem. It uses the SHA-1 hash function to name content. For +example, files, directories, and revisions are referred to by hash +values unlike in other traditional version control systems where files +or versions are referred to via sequential numbers. The use of a hash +function to address its content delivers a few advantages: + +* Integrity checking is easy. Bit flips, for example, are easily + detected, as the hash of corrupted content does not match its name. +* Lookup of objects is fast. + +Using a cryptographically secure hash function brings additional +advantages: + +* Object names can be signed and third parties can trust the hash to + address the signed object and all objects it references. +* Communication using Git protocol and out of band communication + methods have a short reliable string that can be used to reliably + address stored content. + +Over time some flaws in SHA-1 have been discovered by security +researchers. https://shattered.io demonstrated a practical SHA-1 hash +collision. As a result, SHA-1 cannot be considered cryptographically +secure any more. This impacts the communication of hash values because +we cannot trust that a given hash value represents the known good +version of content that the speaker intended. + +SHA-1 still possesses the other properties such as fast object lookup +and safe error checking, but other hash functions are equally suitable +that are believed to be cryptographically secure. + +Goals +----- +Where NewHash is a strong 256-bit hash function to replace SHA-1 (see +"Selection of a New Hash", below): + +1. The transition to NewHash can be done one local repository at a time. + a. Requiring no action by any other party. + b. A NewHash repository can communicate with SHA-1 Git servers + (push/fetch). + c. Users can use SHA-1 and NewHash identifiers for objects + interchangeably (see "Object names on the command line", below). + d. New signed objects make use of a stronger hash function than + SHA-1 for their security guarantees. +2. Allow a complete transition away from SHA-1. + a. Local metadata for SHA-1 compatibility can be removed from a + repository if compatibility with SHA-1 is no longer needed. +3. Maintainability throughout the process. + a. The object format is kept simple and consistent. + b. Creation of a generalized repository conversion tool. + +Non-Goals +--------- +1. Add NewHash support to Git protocol. This is valuable and the + logical next step but it is out of scope for this initial design. +2. Transparently improving the security of existing SHA-1 signed + objects. +3. Intermixing objects using multiple hash functions in a single + repository. +4. Taking the opportunity to fix other bugs in Git's formats and + protocols. +5. Shallow clones and fetches into a NewHash repository. (This will + change when we add NewHash support to Git protocol.) +6. Skip fetching some submodules of a project into a NewHash + repository. (This also depends on NewHash support in Git + protocol.) + +Overview +-------- +We introduce a new repository format extension. Repositories with this +extension enabled use NewHash instead of SHA-1 to name their objects. +This affects both object names and object content --- both the names +of objects and all references to other objects within an object are +switched to the new hash function. + +NewHash repositories cannot be read by older versions of Git. + +Alongside the packfile, a NewHash repository stores a bidirectional +mapping between NewHash and SHA-1 object names. The mapping is generated +locally and can be verified using "git fsck". Object lookups use this +mapping to allow naming objects using either their SHA-1 and NewHash names +interchangeably. + +"git cat-file" and "git hash-object" gain options to display an object +in its sha1 form and write an object given its sha1 form. This +requires all objects referenced by that object to be present in the +object database so that they can be named using the appropriate name +(using the bidirectional hash mapping). + +Fetches from a SHA-1 based server convert the fetched objects into +NewHash form and record the mapping in the bidirectional mapping table +(see below for details). Pushes to a SHA-1 based server convert the +objects being pushed into sha1 form so the server does not have to be +aware of the hash function the client is using. + +Detailed Design +--------------- +Repository format extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A NewHash repository uses repository format version `1` (see +Documentation/technical/repository-version.txt) with extensions +`objectFormat` and `compatObjectFormat`: + + [core] + repositoryFormatVersion = 1 + [extensions] + objectFormat = newhash + compatObjectFormat = sha1 + +Specifying a repository format extension ensures that versions of Git +not aware of NewHash do not try to operate on these repositories, +instead producing an error message: + + $ git status + fatal: unknown repository extensions found: + objectformat + compatobjectformat + +See the "Transition plan" section below for more details on these +repository extensions. + +Object names +~~~~~~~~~~~~ +Objects can be named by their 40 hexadecimal digit sha1-name or 64 +hexadecimal digit newhash-name, plus names derived from those (see +gitrevisions(7)). + +The sha1-name of an object is the SHA-1 of the concatenation of its +type, length, a nul byte, and the object's sha1-content. This is the +traditional <sha1> used in Git to name objects. + +The newhash-name of an object is the NewHash of the concatenation of its +type, length, a nul byte, and the object's newhash-content. + +Object format +~~~~~~~~~~~~~ +The content as a byte sequence of a tag, commit, or tree object named +by sha1 and newhash differ because an object named by newhash-name refers to +other objects by their newhash-names and an object named by sha1-name +refers to other objects by their sha1-names. + +The newhash-content of an object is the same as its sha1-content, except +that objects referenced by the object are named using their newhash-names +instead of sha1-names. Because a blob object does not refer to any +other object, its sha1-content and newhash-content are the same. + +The format allows round-trip conversion between newhash-content and +sha1-content. + +Object storage +~~~~~~~~~~~~~~ +Loose objects use zlib compression and packed objects use the packed +format described in Documentation/technical/pack-format.txt, just like +today. The content that is compressed and stored uses newhash-content +instead of sha1-content. + +Pack index +~~~~~~~~~~ +Pack index (.idx) files use a new v3 format that supports multiple +hash functions. They have the following format (all integers are in +network byte order): + +- A header appears at the beginning and consists of the following: + - The 4-byte pack index signature: '\377t0c' + - 4-byte version number: 3 + - 4-byte length of the header section, including the signature and + version number + - 4-byte number of objects contained in the pack + - 4-byte number of object formats in this pack index: 2 + - For each object format: + - 4-byte format identifier (e.g., 'sha1' for SHA-1) + - 4-byte length in bytes of shortened object names. This is the + shortest possible length needed to make names in the shortened + object name table unambiguous. + - 4-byte integer, recording where tables relating to this format + are stored in this index file, as an offset from the beginning. + - 4-byte offset to the trailer from the beginning of this file. + - Zero or more additional key/value pairs (4-byte key, 4-byte + value). Only one key is supported: 'PSRC'. See the "Loose objects + and unreachable objects" section for supported values and how this + is used. All other keys are reserved. Readers must ignore + unrecognized keys. +- Zero or more NUL bytes. This can optionally be used to improve the + alignment of the full object name table below. +- Tables for the first object format: + - A sorted table of shortened object names. These are prefixes of + the names of all objects in this pack file, packed together + without offset values to reduce the cache footprint of the binary + search for a specific object name. + + - A table of full object names in pack order. This allows resolving + a reference to "the nth object in the pack file" (from a + reachability bitmap or from the next table of another object + format) to its object name. + + - A table of 4-byte values mapping object name order to pack order. + For an object in the table of sorted shortened object names, the + value at the corresponding index in this table is the index in the + previous table for that same object. + + This can be used to look up the object in reachability bitmaps or + to look up its name in another object format. + + - A table of 4-byte CRC32 values of the packed object data, in the + order that the objects appear in the pack file. This is to allow + compressed data to be copied directly from pack to pack during + repacking without undetected data corruption. + + - A table of 4-byte offset values. For an object in the table of + sorted shortened object names, the value at the corresponding + index in this table indicates where that object can be found in + the pack file. These are usually 31-bit pack file offsets, but + large offsets are encoded as an index into the next table with the + most significant bit set. + + - A table of 8-byte offset entries (empty for pack files less than + 2 GiB). Pack files are organized with heavily used objects toward + the front, so most object references should not need to refer to + this table. +- Zero or more NUL bytes. +- Tables for the second object format, with the same layout as above, + up to and not including the table of CRC32 values. +- Zero or more NUL bytes. +- The trailer consists of the following: + - A copy of the 20-byte NewHash checksum at the end of the + corresponding packfile. + + - 20-byte NewHash checksum of all of the above. + +Loose object index +~~~~~~~~~~~~~~~~~~ +A new file $GIT_OBJECT_DIR/loose-object-idx contains information about +all loose objects. Its format is + + # loose-object-idx + (newhash-name SP sha1-name LF)* + +where the object names are in hexadecimal format. The file is not +sorted. + +The loose object index is protected against concurrent writes by a +lock file $GIT_OBJECT_DIR/loose-object-idx.lock. To add a new loose +object: + +1. Write the loose object to a temporary file, like today. +2. Open loose-object-idx.lock with O_CREAT | O_EXCL to acquire the lock. +3. Rename the loose object into place. +4. Open loose-object-idx with O_APPEND and write the new object +5. Unlink loose-object-idx.lock to release the lock. + +To remove entries (e.g. in "git pack-refs" or "git-prune"): + +1. Open loose-object-idx.lock with O_CREAT | O_EXCL to acquire the + lock. +2. Write the new content to loose-object-idx.lock. +3. Unlink any loose objects being removed. +4. Rename to replace loose-object-idx, releasing the lock. + +Translation table +~~~~~~~~~~~~~~~~~ +The index files support a bidirectional mapping between sha1-names +and newhash-names. The lookup proceeds similarly to ordinary object +lookups. For example, to convert a sha1-name to a newhash-name: + + 1. Look for the object in idx files. If a match is present in the + idx's sorted list of truncated sha1-names, then: + a. Read the corresponding entry in the sha1-name order to pack + name order mapping. + b. Read the corresponding entry in the full sha1-name table to + verify we found the right object. If it is, then + c. Read the corresponding entry in the full newhash-name table. + That is the object's newhash-name. + 2. Check for a loose object. Read lines from loose-object-idx until + we find a match. + +Step (1) takes the same amount of time as an ordinary object lookup: +O(number of packs * log(objects per pack)). Step (2) takes O(number of +loose objects) time. To maintain good performance it will be necessary +to keep the number of loose objects low. See the "Loose objects and +unreachable objects" section below for more details. + +Since all operations that make new objects (e.g., "git commit") add +the new objects to the corresponding index, this mapping is possible +for all objects in the object store. + +Reading an object's sha1-content +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The sha1-content of an object can be read by converting all newhash-names +its newhash-content references to sha1-names using the translation table. + +Fetch +~~~~~ +Fetching from a SHA-1 based server requires translating between SHA-1 +and NewHash based representations on the fly. + +SHA-1s named in the ref advertisement that are present on the client +can be translated to NewHash and looked up as local objects using the +translation table. + +Negotiation proceeds as today. Any "have"s generated locally are +converted to SHA-1 before being sent to the server, and SHA-1s +mentioned by the server are converted to NewHash when looking them up +locally. + +After negotiation, the server sends a packfile containing the +requested objects. We convert the packfile to NewHash format using +the following steps: + +1. index-pack: inflate each object in the packfile and compute its + SHA-1. Objects can contain deltas in OBJ_REF_DELTA format against + objects the client has locally. These objects can be looked up + using the translation table and their sha1-content read as + described above to resolve the deltas. +2. topological sort: starting at the "want"s from the negotiation + phase, walk through objects in the pack and emit a list of them, + excluding blobs, in reverse topologically sorted order, with each + object coming later in the list than all objects it references. + (This list only contains objects reachable from the "wants". If the + pack from the server contained additional extraneous objects, then + they will be discarded.) +3. convert to newhash: open a new (newhash) packfile. Read the topologically + sorted list just generated. For each object, inflate its + sha1-content, convert to newhash-content, and write it to the newhash + pack. Record the new sha1<->newhash mapping entry for use in the idx. +4. sort: reorder entries in the new pack to match the order of objects + in the pack the server generated and include blobs. Write a newhash idx + file +5. clean up: remove the SHA-1 based pack file, index, and + topologically sorted list obtained from the server in steps 1 + and 2. + +Step 3 requires every object referenced by the new object to be in the +translation table. This is why the topological sort step is necessary. + +As an optimization, step 1 could write a file describing what non-blob +objects each object it has inflated from the packfile references. This +makes the topological sort in step 2 possible without inflating the +objects in the packfile for a second time. The objects need to be +inflated again in step 3, for a total of two inflations. + +Step 4 is probably necessary for good read-time performance. "git +pack-objects" on the server optimizes the pack file for good data +locality (see Documentation/technical/pack-heuristics.txt). + +Details of this process are likely to change. It will take some +experimenting to get this to perform well. + +Push +~~~~ +Push is simpler than fetch because the objects referenced by the +pushed objects are already in the translation table. The sha1-content +of each object being pushed can be read as described in the "Reading +an object's sha1-content" section to generate the pack written by git +send-pack. + +Signed Commits +~~~~~~~~~~~~~~ +We add a new field "gpgsig-newhash" to the commit object format to allow +signing commits without relying on SHA-1. It is similar to the +existing "gpgsig" field. Its signed payload is the newhash-content of the +commit object with any "gpgsig" and "gpgsig-newhash" fields removed. + +This means commits can be signed +1. using SHA-1 only, as in existing signed commit objects +2. using both SHA-1 and NewHash, by using both gpgsig-newhash and gpgsig + fields. +3. using only NewHash, by only using the gpgsig-newhash field. + +Old versions of "git verify-commit" can verify the gpgsig signature in +cases (1) and (2) without modifications and view case (3) as an +ordinary unsigned commit. + +Signed Tags +~~~~~~~~~~~ +We add a new field "gpgsig-newhash" to the tag object format to allow +signing tags without relying on SHA-1. Its signed payload is the +newhash-content of the tag with its gpgsig-newhash field and "-----BEGIN PGP +SIGNATURE-----" delimited in-body signature removed. + +This means tags can be signed +1. using SHA-1 only, as in existing signed tag objects +2. using both SHA-1 and NewHash, by using gpgsig-newhash and an in-body + signature. +3. using only NewHash, by only using the gpgsig-newhash field. + +Mergetag embedding +~~~~~~~~~~~~~~~~~~ +The mergetag field in the sha1-content of a commit contains the +sha1-content of a tag that was merged by that commit. + +The mergetag field in the newhash-content of the same commit contains the +newhash-content of the same tag. + +Submodules +~~~~~~~~~~ +To convert recorded submodule pointers, you need to have the converted +submodule repository in place. The translation table of the submodule +can be used to look up the new hash. + +Loose objects and unreachable objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Fast lookups in the loose-object-idx require that the number of loose +objects not grow too high. + +"git gc --auto" currently waits for there to be 6700 loose objects +present before consolidating them into a packfile. We will need to +measure to find a more appropriate threshold for it to use. + +"git gc --auto" currently waits for there to be 50 packs present +before combining packfiles. Packing loose objects more aggressively +may cause the number of pack files to grow too quickly. This can be +mitigated by using a strategy similar to Martin Fick's exponential +rolling garbage collection script: +https://gerrit-review.googlesource.com/c/gerrit/+/35215 + +"git gc" currently expels any unreachable objects it encounters in +pack files to loose objects in an attempt to prevent a race when +pruning them (in case another process is simultaneously writing a new +object that refers to the about-to-be-deleted object). This leads to +an explosion in the number of loose objects present and disk space +usage due to the objects in delta form being replaced with independent +loose objects. Worse, the race is still present for loose objects. + +Instead, "git gc" will need to move unreachable objects to a new +packfile marked as UNREACHABLE_GARBAGE (using the PSRC field; see +below). To avoid the race when writing new objects referring to an +about-to-be-deleted object, code paths that write new objects will +need to copy any objects from UNREACHABLE_GARBAGE packs that they +refer to to new, non-UNREACHABLE_GARBAGE packs (or loose objects). +UNREACHABLE_GARBAGE are then safe to delete if their creation time (as +indicated by the file's mtime) is long enough ago. + +To avoid a proliferation of UNREACHABLE_GARBAGE packs, they can be +combined under certain circumstances. If "gc.garbageTtl" is set to +greater than one day, then packs created within a single calendar day, +UTC, can be coalesced together. The resulting packfile would have an +mtime before midnight on that day, so this makes the effective maximum +ttl the garbageTtl + 1 day. If "gc.garbageTtl" is less than one day, +then we divide the calendar day into intervals one-third of that ttl +in duration. Packs created within the same interval can be coalesced +together. The resulting packfile would have an mtime before the end of +the interval, so this makes the effective maximum ttl equal to the +garbageTtl * 4/3. + +This rule comes from Thirumala Reddy Mutchukota's JGit change +https://git.eclipse.org/r/90465. + +The UNREACHABLE_GARBAGE setting goes in the PSRC field of the pack +index. More generally, that field indicates where a pack came from: + + - 1 (PACK_SOURCE_RECEIVE) for a pack received over the network + - 2 (PACK_SOURCE_AUTO) for a pack created by a lightweight + "gc --auto" operation + - 3 (PACK_SOURCE_GC) for a pack created by a full gc + - 4 (PACK_SOURCE_UNREACHABLE_GARBAGE) for potential garbage + discovered by gc + - 5 (PACK_SOURCE_INSERT) for locally created objects that were + written directly to a pack file, e.g. from "git add ." + +This information can be useful for debugging and for "gc --auto" to +make appropriate choices about which packs to coalesce. + +Caveats +------- +Invalid objects +~~~~~~~~~~~~~~~ +The conversion from sha1-content to newhash-content retains any +brokenness in the original object (e.g., tree entry modes encoded with +leading 0, tree objects whose paths are not sorted correctly, and +commit objects without an author or committer). This is a deliberate +feature of the design to allow the conversion to round-trip. + +More profoundly broken objects (e.g., a commit with a truncated "tree" +header line) cannot be converted but were not usable by current Git +anyway. + +Shallow clone and submodules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Because it requires all referenced objects to be available in the +locally generated translation table, this design does not support +shallow clone or unfetched submodules. Protocol improvements might +allow lifting this restriction. + +Alternates +~~~~~~~~~~ +For the same reason, a newhash repository cannot borrow objects from a +sha1 repository using objects/info/alternates or +$GIT_ALTERNATE_OBJECT_REPOSITORIES. + +git notes +~~~~~~~~~ +The "git notes" tool annotates objects using their sha1-name as key. +This design does not describe a way to migrate notes trees to use +newhash-names. That migration is expected to happen separately (for +example using a file at the root of the notes tree to describe which +hash it uses). + +Server-side cost +~~~~~~~~~~~~~~~~ +Until Git protocol gains NewHash support, using NewHash based storage +on public-facing Git servers is strongly discouraged. Once Git +protocol gains NewHash support, NewHash based servers are likely not +to support SHA-1 compatibility, to avoid what may be a very expensive +hash reencode during clone and to encourage peers to modernize. + +The design described here allows fetches by SHA-1 clients of a +personal NewHash repository because it's not much more difficult than +allowing pushes from that repository. This support needs to be guarded +by a configuration option --- servers like git.kernel.org that serve a +large number of clients would not be expected to bear that cost. + +Meaning of signatures +~~~~~~~~~~~~~~~~~~~~~ +The signed payload for signed commits and tags does not explicitly +name the hash used to identify objects. If some day Git adopts a new +hash function with the same length as the current SHA-1 (40 +hexadecimal digit) or NewHash (64 hexadecimal digit) objects then the +intent behind the PGP signed payload in an object signature is +unclear: + + object e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7 + type commit + tag v2.12.0 + tagger Junio C Hamano <gitster@pobox.com> 1487962205 -0800 + + Git 2.12 + +Does this mean Git v2.12.0 is the commit with sha1-name +e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7 or the commit with +new-40-digit-hash-name e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7? + +Fortunately NewHash and SHA-1 have different lengths. If Git starts +using another hash with the same length to name objects, then it will +need to change the format of signed payloads using that hash to +address this issue. + +Object names on the command line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To support the transition (see Transition plan below), this design +supports four different modes of operation: + + 1. ("dark launch") Treat object names input by the user as SHA-1 and + convert any object names written to output to SHA-1, but store + objects using NewHash. This allows users to test the code with no + visible behavior change except for performance. This allows + allows running even tests that assume the SHA-1 hash function, to + sanity-check the behavior of the new mode. + + 2. ("early transition") Allow both SHA-1 and NewHash object names in + input. Any object names written to output use SHA-1. This allows + users to continue to make use of SHA-1 to communicate with peers + (e.g. by email) that have not migrated yet and prepares for mode 3. + + 3. ("late transition") Allow both SHA-1 and NewHash object names in + input. Any object names written to output use NewHash. In this + mode, users are using a more secure object naming method by + default. The disruption is minimal as long as most of their peers + are in mode 2 or mode 3. + + 4. ("post-transition") Treat object names input by the user as + NewHash and write output using NewHash. This is safer than mode 3 + because there is less risk that input is incorrectly interpreted + using the wrong hash function. + +The mode is specified in configuration. + +The user can also explicitly specify which format to use for a +particular revision specifier and for output, overriding the mode. For +example: + +git --output-format=sha1 log abac87a^{sha1}..f787cac^{newhash} + +Selection of a New Hash +----------------------- +In early 2005, around the time that Git was written, Xiaoyun Wang, +Yiqun Lisa Yin, and Hongbo Yu announced an attack finding SHA-1 +collisions in 2^69 operations. In August they published details. +Luckily, no practical demonstrations of a collision in full SHA-1 were +published until 10 years later, in 2017. + +The hash function NewHash to replace SHA-1 should be stronger than +SHA-1 was: we would like it to be trustworthy and useful in practice +for at least 10 years. + +Some other relevant properties: + +1. A 256-bit hash (long enough to match common security practice; not + excessively long to hurt performance and disk usage). + +2. High quality implementations should be widely available (e.g. in + OpenSSL). + +3. The hash function's properties should match Git's needs (e.g. Git + requires collision and 2nd preimage resistance and does not require + length extension resistance). + +4. As a tiebreaker, the hash should be fast to compute (fortunately + many contenders are faster than SHA-1). + +Some hashes under consideration are SHA-256, SHA-512/256, SHA-256x16, +K12, and BLAKE2bp-256. + +Transition plan +--------------- +Some initial steps can be implemented independently of one another: +- adding a hash function API (vtable) +- teaching fsck to tolerate the gpgsig-newhash field +- excluding gpgsig-* from the fields copied by "git commit --amend" +- annotating tests that depend on SHA-1 values with a SHA1 test + prerequisite +- using "struct object_id", GIT_MAX_RAWSZ, and GIT_MAX_HEXSZ + consistently instead of "unsigned char *" and the hardcoded + constants 20 and 40. +- introducing index v3 +- adding support for the PSRC field and safer object pruning + + +The first user-visible change is the introduction of the objectFormat +extension (without compatObjectFormat). This requires: +- implementing the loose-object-idx +- teaching fsck about this mode of operation +- using the hash function API (vtable) when computing object names +- signing objects and verifying signatures +- rejecting attempts to fetch from or push to an incompatible + repository + +Next comes introduction of compatObjectFormat: +- translating object names between object formats +- translating object content between object formats +- generating and verifying signatures in the compat format +- adding appropriate index entries when adding a new object to the + object store +- --output-format option +- ^{sha1} and ^{newhash} revision notation +- configuration to specify default input and output format (see + "Object names on the command line" above) + +The next step is supporting fetches and pushes to SHA-1 repositories: +- allow pushes to a repository using the compat format +- generate a topologically sorted list of the SHA-1 names of fetched + objects +- convert the fetched packfile to newhash format and generate an idx + file +- re-sort to match the order of objects in the fetched packfile + +The infrastructure supporting fetch also allows converting an existing +repository. In converted repositories and new clones, end users can +gain support for the new hash function without any visible change in +behavior (see "dark launch" in the "Object names on the command line" +section). In particular this allows users to verify NewHash signatures +on objects in the repository, and it should ensure the transition code +is stable in production in preparation for using it more widely. + +Over time projects would encourage their users to adopt the "early +transition" and then "late transition" modes to take advantage of the +new, more futureproof NewHash object names. + +When objectFormat and compatObjectFormat are both set, commands +generating signatures would generate both SHA-1 and NewHash signatures +by default to support both new and old users. + +In projects using NewHash heavily, users could be encouraged to adopt +the "post-transition" mode to avoid accidentally making implicit use +of SHA-1 object names. + +Once a critical mass of users have upgraded to a version of Git that +can verify NewHash signatures and have converted their existing +repositories to support verifying them, we can add support for a +setting to generate only NewHash signatures. This is expected to be at +least a year later. + +That is also a good moment to advertise the ability to convert +repositories to use NewHash only, stripping out all SHA-1 related +metadata. This improves performance by eliminating translation +overhead and security by avoiding the possibility of accidentally +relying on the safety of SHA-1. + +Updating Git's protocols to allow a server to specify which hash +functions it supports is also an important part of this transition. It +is not discussed in detail in this document but this transition plan +assumes it happens. :) + +Alternatives considered +----------------------- +Upgrading everyone working on a particular project on a flag day +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Projects like the Linux kernel are large and complex enough that +flipping the switch for all projects based on the repository at once +is infeasible. + +Not only would all developers and server operators supporting +developers have to switch on the same flag day, but supporting tooling +(continuous integration, code review, bug trackers, etc) would have to +be adapted as well. This also makes it difficult to get early feedback +from some project participants testing before it is time for mass +adoption. + +Using hash functions in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(e.g. https://public-inbox.org/git/22708.8913.864049.452252@chiark.greenend.org.uk/ ) +Objects newly created would be addressed by the new hash, but inside +such an object (e.g. commit) it is still possible to address objects +using the old hash function. +* You cannot trust its history (needed for bisectability) in the + future without further work +* Maintenance burden as the number of supported hash functions grows + (they will never go away, so they accumulate). In this proposal, by + comparison, converted objects lose all references to SHA-1. + +Signed objects with multiple hashes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Instead of introducing the gpgsig-newhash field in commit and tag objects +for newhash-content based signatures, an earlier version of this design +added "hash newhash <newhash-name>" fields to strengthen the existing +sha1-content based signatures. + +In other words, a single signature was used to attest to the object +content using both hash functions. This had some advantages: +* Using one signature instead of two speeds up the signing process. +* Having one signed payload with both hashes allows the signer to + attest to the sha1-name and newhash-name referring to the same object. +* All users consume the same signature. Broken signatures are likely + to be detected quickly using current versions of git. + +However, it also came with disadvantages: +* Verifying a signed object requires access to the sha1-names of all + objects it references, even after the transition is complete and + translation table is no longer needed for anything else. To support + this, the design added fields such as "hash sha1 tree <sha1-name>" + and "hash sha1 parent <sha1-name>" to the newhash-content of a signed + commit, complicating the conversion process. +* Allowing signed objects without a sha1 (for after the transition is + complete) complicated the design further, requiring a "nohash sha1" + field to suppress including "hash sha1" fields in the newhash-content + and signed payload. + +Lazily populated translation table +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Some of the work of building the translation table could be deferred to +push time, but that would significantly complicate and slow down pushes. +Calculating the sha1-name at object creation time at the same time it is +being streamed to disk and having its newhash-name calculated should be +an acceptable cost. + +Document History +---------------- + +2017-03-03 +bmwill@google.com, jonathantanmy@google.com, jrnieder@gmail.com, +sbeller@google.com + +Initial version sent to +http://public-inbox.org/git/20170304011251.GA26789@aiede.mtv.corp.google.com + +2017-03-03 jrnieder@gmail.com +Incorporated suggestions from jonathantanmy and sbeller: +* describe purpose of signed objects with each hash type +* redefine signed object verification using object content under the + first hash function + +2017-03-06 jrnieder@gmail.com +* Use SHA3-256 instead of SHA2 (thanks, Linus and brian m. carlson).[1][2] +* Make sha3-based signatures a separate field, avoiding the need for + "hash" and "nohash" fields (thanks to peff[3]). +* Add a sorting phase to fetch (thanks to Junio for noticing the need + for this). +* Omit blobs from the topological sort during fetch (thanks to peff). +* Discuss alternates, git notes, and git servers in the caveats + section (thanks to Junio Hamano, brian m. carlson[4], and Shawn + Pearce). +* Clarify language throughout (thanks to various commenters, + especially Junio). + +2017-09-27 jrnieder@gmail.com, sbeller@google.com +* use placeholder NewHash instead of SHA3-256 +* describe criteria for picking a hash function. +* include a transition plan (thanks especially to Brandon Williams + for fleshing these ideas out) +* define the translation table (thanks, Shawn Pearce[5], Jonathan + Tan, and Masaya Suzuki) +* avoid loose object overhead by packing more aggressively in + "git gc --auto" + +[1] http://public-inbox.org/git/CA+55aFzJtejiCjV0e43+9oR3QuJK2PiFiLQemytoLpyJWe6P9w@mail.gmail.com/ +[2] http://public-inbox.org/git/CA+55aFz+gkAsDZ24zmePQuEs1XPS9BP_s8O7Q4wQ7LV7X5-oDA@mail.gmail.com/ +[3] http://public-inbox.org/git/20170306084353.nrns455dvkdsfgo5@sigill.intra.peff.net/ +[4] http://public-inbox.org/git/20170304224936.rqqtkdvfjgyezsht@genre.crustytoothpaste.net +[5] https://public-inbox.org/git/CAJo=hJtoX9=AyLHHpUJS7fueV9ciZ_MNpnEPHUz8Whui6g9F0A@mail.gmail.com/ diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index b4d88af133..3a03e63eb0 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1556,7 +1556,7 @@ so on a different branch and then coming back), unstash the work-in-progress changes. ------------------------------------------------ -$ git stash save "work in progress for foo feature" +$ git stash push -m "work in progress for foo feature" ------------------------------------------------ This command will save your changes away to the `stash`, and |
