diff options
Diffstat (limited to 'Documentation')
56 files changed, 2563 insertions, 427 deletions
diff --git a/Documentation/.gitignore b/Documentation/.gitignore index c7096f11f1..3ef54e0adb 100644 --- a/Documentation/.gitignore +++ b/Documentation/.gitignore @@ -12,3 +12,4 @@ cmds-*.txt mergetools-*.txt manpage-base-url.xsl SubmittingPatches.txt +tmp-doc-diff/ diff --git a/Documentation/Makefile b/Documentation/Makefile index d079d7c73a..95f6a321f2 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -76,6 +76,7 @@ TECH_DOCS += technical/long-running-process-protocol TECH_DOCS += technical/pack-format TECH_DOCS += technical/pack-heuristics TECH_DOCS += technical/pack-protocol +TECH_DOCS += technical/partial-clone TECH_DOCS += technical/protocol-capabilities TECH_DOCS += technical/protocol-common TECH_DOCS += technical/protocol-v2 @@ -343,7 +344,7 @@ $(OBSOLETE_HTML): %.html : %.txto asciidoc.conf mv $@+ $@ manpage-base-url.xsl: manpage-base-url.xsl.in - sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@ + $(QUIET_GEN)sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@ %.1 %.5 %.7 : %.xml manpage-base-url.xsl $(QUIET_XMLTO)$(RM) $@ && \ diff --git a/Documentation/RelNotes/2.19.0.txt b/Documentation/RelNotes/2.19.0.txt index 2b45b6ff5c..a06ccf6e2a 100644 --- a/Documentation/RelNotes/2.19.0.txt +++ b/Documentation/RelNotes/2.19.0.txt @@ -15,6 +15,81 @@ UI, Workflows & Features otherwise working-tree-only application of a patch will add new paths to the index marked with the "intent-to-add" bit. + * "git grep" learned the "--column" option that gives not just the + line number but the column number of the hit. + + * The "-l" option in "git branch -l" is an unfortunate short-hand for + "--create-reflog", but many users, both old and new, somehow expect + it to be something else, perhaps "--list". This step warns when "-l" + is used as a short-hand for "--create-reflog" and warns about the + future repurposing of the it when it is used. + + * The userdiff pattern for .php has been updated. + + * The content-transfer-encoding of the message "git send-email" sends + out by default was 8bit, which can cause trouble when there is an + overlong line to bust RFC 5322/2822 limit. A new option 'auto' to + automatically switch to quoted-printable when there is such a line + in the payload has been introduced and is made the default. + + * "git checkout" and "git worktree add" learned to honor + checkout.defaultRemote when auto-vivifying a local branch out of a + remote tracking branch in a repository with multiple remotes that + have tracking branches that share the same names. + (merge 8d7b558bae ab/checkout-default-remote later to maint). + + * "git grep" learned the "--only-matching" option. + + * "git rebase --rebase-merges" mode now handles octopus merges as + well. + + * Add a server-side knob to skip commits in exponential/fibbonacci + stride in an attempt to cover wider swath of history with a smaller + number of iterations, potentially accepting a larger packfile + transfer, instead of going back one commit a time during common + ancestor discovery during the "git fetch" transaction. + (merge 42cc7485a2 jt/fetch-negotiator-skipping later to maint). + + * A new configuration variable core.usereplacerefs has been added, + primarily to help server installations that want to ignore the + replace mechanism altogether. + + * Teach "git tag -s" etc. a few configuration variables (gpg.format + that can be set to "openpgp" or "x509", and gpg.<format>.program + that is used to specify what program to use to deal with the format) + to allow x.509 certs with CMS via "gpgsm" to be used instead of + openpgp via "gnupg". + + * Many more strings are prepared for l10n. + + * "git p4 submit" learns to ask its own pre-submit hook if it should + continue with submitting. + + * The test performed at the receiving end of "git push" to prevent + bad objects from entering repository can be customized via + receive.fsck.* configuration variables; we now have gained a + counterpart to do the same on the "git fetch" side, with + fetch.fsck.* configuration variables. + + * "git pull --rebase=interactive" learned "i" as a short-hand for + "interactive". + + * "git instaweb" has been adjusted to run better with newer Apache on + RedHat based distros. + + * "git range-diff" is a reimplementation of "git tbdiff" that lets us + compare individual patches in two iterations of a topic. + + * The sideband code learned to optionally paint selected keywords at + the beginning of incoming lines on the receiving end. + + * "git branch --list" learned to take the default sort order from the + 'branch.sort' configuration variable, just like "git tag --list" + pays attention to 'tag.sort'. + + * "git worktree" command learned "--quiet" option to make it less + verbose. + Performance, Internal Implementation, Development Support etc. @@ -51,6 +126,148 @@ Performance, Internal Implementation, Development Support etc. * Build and test procedure for netrc credential helper (in contrib/) has been updated. + * Remove unused function definitions and declarations from ewah + bitmap subsystem. + + * Code preparation to make "git p4" closer to be usable with Python 3. + + * Tighten the API to make it harder to misuse in-tree .gitmodules + file, even though it shares the same syntax with configuration + files, to read random configuration items from it. + + * "git fast-import" has been updated to avoid attempting to create + delta against a zero-byte-long string, which is pointless. + + * The codebase has been updated to compile cleanly with -pedantic + option. + (merge 2b647a05d7 bb/pedantic later to maint). + + * The character display width table has been updated to match the + latest Unicode standard. + (merge 570951eea2 bb/unicode-11-width later to maint). + + * test-lint now looks for broken use of "VAR=VAL shell_func" in test + scripts. + + * Conversion from uchar[40] to struct object_id continues. + + * Recent "security fix" to pay attention to contents of ".gitmodules" + while accepting "git push" was a bit overly strict than necessary, + which has been adjusted. + + * "git fsck" learns to make sure the optional commit-graph file is in + a sane state. + + * "git diff --color-moved" feature has further been tweaked. + + * Code restructuring and a small fix to transport protocol v2 during + fetching. + + * Parsing of -L[<N>][,[<M>]] parameters "git blame" and "git log" + take has been tweaked. + + * lookup_commit_reference() and friends have been updated to find + in-core object for a specific in-core repository instance. + + * Various glitches in the heuristics of merge-recursive strategy have + been documented in new tests. + + * "git fetch" learned a new option "--negotiation-tip" to limit the + set of commits it tells the other end as "have", to reduce wasted + bandwidth and cycles, which would be helpful when the receiving + repository has a lot of refs that have little to do with the + history at the remote it is fetching from. + + * For a large tree, the index needs to hold many cache entries + allocated on heap. These cache entries are now allocated out of a + dedicated memory pool to amortize malloc(3) overhead. + + * Tests to cover various conflicting cases have been added for + merge-recursive. + + * Tests to cover conflict cases that involve submodules have been + added for merge-recursive. + + * Look for broken "&&" chains that are hidden in subshell, many of + which have been found and corrected. + + * The singleton commit-graph in-core instance is made per in-core + repository instance. + + * "make DEVELOPER=1 DEVOPTS=pedantic" allows developers to compile + with -pedantic option, which may catch more problematic program + constructs and potential bugs. + + * Preparatory code to later add json output for telemetry data has + been added. + + * Update the way we use Coccinelle to find out-of-style code that + need to be modernised. + + * It is too easy to misuse system API functions such as strcat(); + these selected functions are now forbidden in this codebase and + will cause a compilation failure. + + * Add a script (in contrib/) to help users of VSCode work better with + our codebase. + + * The Travis CI scripts were taught to ship back the test data from + failed tests. + (merge aea8879a6a sg/travis-retrieve-trash-upon-failure later to maint). + + * The parse-options machinery learned to refrain from enclosing + placeholder string inside a "<bra" and "ket>" pair automatically + without PARSE_OPT_LITERAL_ARGHELP. Existing help text for option + arguments that are not formatted correctly have been identified and + fixed. + (merge 5f0df44cd7 rs/parse-opt-lithelp later to maint). + + * Noiseword "extern" has been removed from function decls in the + header files. + + * A few atoms like %(objecttype) and %(objectsize) in the format + specifier of "for-each-ref --format=<format>" can be filled without + getting the full contents of the object, but just with the object + header. These cases have been optimized by calling + oid_object_info() API (instead of reading and inspecting the data). + + * The end result of documentation update has been made to be + inspected more easily to help developers. + + * The API to iterate over all objects learned to optionally list + objects in the order they appear in packfiles, which helps locality + of access if the caller accesses these objects while as objects are + enumerated. + + * Improve built-in facility to catch broken &&-chain in the tests. + + * The more library-ish parts of the codebase learned to work on the + in-core index-state instance that is passed in by their callers, + instead of always working on the singleton "the_index" instance. + + * A test prerequisite defined by various test scripts with slightly + different semantics has been consolidated into a single copy and + made into a lazily defined one. + (merge 6ec633059a wc/make-funnynames-shared-lazy-prereq later to maint). + + * After a partial clone, repeated fetches from promisor remote would + have accumulated many packfiles marked with .promisor bit without + getting them coalesced into fewer packfiles, hurting performance. + "git repack" now learned to repack them. + + * Partially revert the support for multiple hash functions to regain + hash comparison performance; we'd think of a way to do this better + in the next cycle. + + * "git help --config" (which is used in command line completion) + missed the configuration variables not described in the main + config.txt file but are described in another file that is included + by it, which has been corrected. + + * The test linter code has learned that the end of here-doc mark + "EOF" can be quoted in a double-quote pair, not just in a + single-quote pair. + Fixes since v2.18 ----------------- @@ -96,6 +313,303 @@ Fixes since v2.18 to the submodule was changed in the range of commits in the superproject, sometimes showing "(null)". This has been corrected. - * Code cleanup. + * Bugfix for "rebase -i" corner case regression. + (merge a9279c6785 pw/rebase-i-keep-reword-after-conflict later to maint). + + * Recently added "--base" option to "git format-patch" command did + not correctly generate prereq patch ids. + (merge 15b76c1fb3 xy/format-patch-prereq-patch-id-fix later to maint). + + * POSIX portability fix in Makefile to fix a glitch introduced a few + releases ago. + (merge 6600054e9b dj/runtime-prefix later to maint). + + * "git filter-branch" when used with the "--state-branch" option + still attempted to rewrite the commits whose filtered result is + known from the previous attempt (which is recorded on the state + branch); the command has been corrected not to waste cycles doing + so. + (merge 709cfe848a mb/filter-branch-optim later to maint). + + * Clarify that setting core.ignoreCase to deviate from reality would + not turn a case-incapable filesystem into a case-capable one. + (merge 48294b512a ms/core-icase-doc later to maint). + + * "fsck.skipList" did not prevent a blob object listed there from + being inspected for is contents (e.g. we recently started to + inspect the contents of ".gitmodules" for certain malicious + patterns), which has been corrected. + (merge fb16287719 rj/submodule-fsck-skip later to maint). + + * "git checkout --recurse-submodules another-branch" did not report + in which submodule it failed to update the working tree, which + resulted in an unhelpful error message. + (merge ba95d4e4bd sb/submodule-move-head-error-msg later to maint). + + * "git rebase" behaved slightly differently depending on which one of + the three backends gets used; this has been documented and an + effort to make them more uniform has begun. + (merge b00bf1c9a8 en/rebase-consistency later to maint). + + * The "--ignore-case" option of "git for-each-ref" (and its friends) + did not work correctly, which has been fixed. + (merge e674eb2528 jk/for-each-ref-icase later to maint). + + * "git fetch" failed to correctly validate the set of objects it + received when making a shallow history deeper, which has been + corrected. + (merge cf1e7c0770 jt/connectivity-check-after-unshallow later to maint). + + * Partial clone support of "git clone" has been updated to correctly + validate the objects it receives from the other side. The server + side has been corrected to send objects that are directly + requested, even if they may match the filtering criteria (e.g. when + doing a "lazy blob" partial clone). + (merge a7e67c11b8 jt/partial-clone-fsck-connectivity later to maint). + + * Handling of an empty range by "git cherry-pick" was inconsistent + depending on how the range ended up to be empty, which has been + corrected. + (merge c5e358d073 jk/empty-pick-fix later to maint). + + * "git reset --merge" (hence "git merge ---abort") and "git reset --hard" + had trouble working correctly in a sparsely checked out working + tree after a conflict, which has been corrected. + (merge b33fdfc34c mk/merge-in-sparse-checkout later to maint). + + * Correct a broken use of "VAR=VAL shell_func" in a test. + (merge 650161a277 jc/t3404-one-shot-export-fix later to maint). + + * "git rev-parse ':/substring'" did not consider the history leading + only to HEAD when looking for a commit with the given substring, + when the HEAD is detached. This has been fixed. + (merge 6b3351e799 wc/find-commit-with-pattern-on-detached-head later to maint). + + * Build doc update for Windows. + (merge ede8d89bb1 nd/command-list later to maint). + + * core.commentchar is now honored when preparing the list of commits + to replay in "rebase -i". + + * "git pull --rebase" on a corrupt HEAD caused a segfault. In + general we substitute an empty tree object when running the in-core + equivalent of the diff-index command, and the codepath has been + corrected to do so as well to fix this issue. + (merge 3506dc9445 jk/has-uncommitted-changes-fix later to maint). + + * httpd tests saw occasional breakage due to the way its access log + gets inspected by the tests, which has been updated to make them + less flaky. + (merge e8b3b2e275 sg/httpd-test-unflake later to maint). + + * Tests to cover more D/F conflict cases have been added for + merge-recursive. + + * "git gc --auto" opens file descriptors for the packfiles before + spawning "git repack/prune", which would upset Windows that does + not want a process to work on a file that is open by another + process. The issue has been worked around. + (merge 12e73a3ce4 kg/gc-auto-windows-workaround later to maint). + + * The recursive merge strategy did not properly ensure there was no + change between HEAD and the index before performing its operation, + which has been corrected. + (merge 55f39cf755 en/dirty-merge-fixes later to maint). + + * "git rebase" started exporting GIT_DIR environment variable and + exposing it to hook scripts when part of it got rewritten in C. + Instead of matching the old scripted Porcelains' behaviour, + compensate by also exporting GIT_WORK_TREE environment as well to + lessen the damage. This can harm existing hooks that want to + operate on different repository, but the current behaviour is + already broken for them anyway. + (merge ab5e67d751 bc/sequencer-export-work-tree-as-well later to maint). + + * "git send-email" when using in a batched mode that limits the + number of messages sent in a single SMTP session lost the contents + of the variable used to choose between tls/ssl, unable to send the + second and later batches, which has been fixed. + (merge 636f3d7ac5 jm/send-email-tls-auth-on-batch later to maint). + + * The lazy clone support had a few places where missing but promised + objects were not correctly tolerated, which have been fixed. + + * One of the "diff --color-moved" mode "dimmed_zebra" that was named + in an unusual way has been deprecated and replaced by + "dimmed-zebra". + (merge e3f2f5f9cd es/diff-color-moved-fix later to maint). + + * The wire-protocol v2 relies on the client to send "ref prefixes" to + limit the bandwidth spent on the initial ref advertisement. "git + clone" when learned to speak v2 forgot to do so, which has been + corrected. + (merge 402c47d939 bw/clone-ref-prefixes later to maint). + + * "git diff --histogram" had a bad memory usage pattern, which has + been rearranged to reduce the peak usage. + (merge 79cb2ebb92 sb/histogram-less-memory later to maint). + + * Code clean-up to use size_t/ssize_t when they are the right type. + (merge 7726d360b5 jk/size-t later to maint). + + * The wire-protocol v2 relies on the client to send "ref prefixes" to + limit the bandwidth spent on the initial ref advertisement. "git + fetch $remote branch:branch" that asks tags that point into the + history leading to the "branch" automatically followed sent to + narrow prefix and broke the tag following, which has been fixed. + (merge 2b554353a5 jt/tag-following-with-proto-v2-fix later to maint). + + * When the sparse checkout feature is in use, "git cherry-pick" and + other mergy operations lost the skip_worktree bit when a path that + is excluded from checkout requires content level merge, which is + resolved as the same as the HEAD version, without materializing the + merge result in the working tree, which made the path appear as + deleted. This has been corrected by preserving the skip_worktree + bit (and not materializing the file in the working tree). + (merge 2b75fb601c en/merge-recursive-skip-fix later to maint). + + * The "author-script" file "git rebase -i" creates got broken when + we started to move the command away from shell script, which is + getting fixed now. + (merge 5522bbac20 es/rebase-i-author-script-fix later to maint). + + * The automatic tree-matching in "git merge -s subtree" was broken 5 + years ago and nobody has noticed since then, which is now fixed. + (merge 2ec4150713 jk/merge-subtree-heuristics later to maint). + + * "git fetch $there refs/heads/s" ought to fetch the tip of the + branch 's', but when "refs/heads/refs/heads/s", i.e. a branch whose + name is "refs/heads/s" exists at the same time, fetched that one + instead by mistake. This has been corrected to honor the usual + disambiguation rules for abbreviated refnames. + (merge 60650a48c0 jt/refspec-dwim-precedence-fix later to maint). + + * Futureproofing a helper function that can easily be misused. + (merge 65bb21e77e es/want-color-fd-defensive later to maint). + + * The http-backend (used for smart-http transport) used to slurp the + whole input until EOF, without paying attention to CONTENT_LENGTH + that is supplied in the environment and instead expecting the Web + server to close the input stream. This has been fixed. + (merge eebfe40962 mk/http-backend-content-length later to maint). + + * "git merge --abort" etc. did not clean things up properly when + there were conflicted entries in the index in certain order that + are involved in D/F conflicts. This has been corrected. + (merge ad3762042a en/abort-df-conflict-fixes later to maint). + + * "git diff --indent-heuristic" had a bad corner case performance. + (merge 301ef85401 sb/indent-heuristic-optim later to maint). + + * The "--exec" option to "git rebase --rebase-merges" placed the exec + commands at wrong places, which has been corrected. + + * "git verify-tag" and "git verify-commit" have been taught to use + the exit status of underlying "gpg --verify" to signal bad or + untrusted signature they found. + (merge 4e5dc9ca17 jc/gpg-status later to maint). + + * "git mergetool" stopped and gave an extra prompt to continue after + the last path has been handled, which did not make much sense. + (merge d651a54b8a ng/mergetool-lose-final-prompt later to maint). + + * Among the three codepaths we use O_APPEND to open a file for + appending, one used for writing GIT_TRACE output requires O_APPEND + implementation that behaves sensibly when multiple processes are + writing to the same file. POSIX emulation used in the Windows port + has been updated to improve in this area. + (merge d641097589 js/mingw-o-append later to maint). + + * "git pull --rebase -v" in a repository with a submodule barfed as + an intermediate process did not understand what "-v(erbose)" flag + meant, which has been fixed. + (merge e84c3cf3dc sb/pull-rebase-submodule later to maint). + + * Recent update to "git config" broke updating variable in a + subsection, which has been corrected. + (merge bff7df7a87 sb/config-write-fix later to maint). + + * When "git rebase -i" is told to squash two or more commits into + one, it labeled the log message for each commit with its number. + It correctly called the first one "1st commit", but the next one + was "commit #1", which was off-by-one. This has been corrected. + (merge dd2e36ebac pw/rebase-i-squash-number-fix later to maint). + + * "git rebase -i", when a 'merge <branch>' insn in its todo list + fails, segfaulted, which has been (minimally) corrected. + (merge bc9238bb09 pw/rebase-i-merge-segv-fix later to maint). + + * "git cherry-pick --quit" failed to remove CHERRY_PICK_HEAD even + though we won't be in a cherry-pick session after it returns, which + has been corrected. + (merge 3e7dd99208 nd/cherry-pick-quit-fix later to maint). + + * In a recent update in 2.18 era, "git pack-objects" started + producing a larger than necessary packfiles by missing + opportunities to use large deltas. This has been corrected. + + * The meaning of the possible values the "core.checkStat" + configuration variable can take were not adequately documented, + which has been fixed. + (merge 9bf5d4c4e2 nd/config-core-checkstat-doc later to maint). + + * Recent "git rebase -i" update started to write bogusly formatted + author-script, with a matching broken reading code. These are + fixed. + + * Recent addition of "directory rename" heuristics to the + merge-recursive backend makes the command susceptible to false + positives and false negatives. In the context of "git am -3", + which does not know about surrounding unmodified paths and thus + cannot inform the merge machinery about the full trees involved, + this risk is particularly severe. As such, the heuristic is + disabled for "git am -3" to keep the machinery "more stupid but + predictable". + + * "git merge-base" in 2.19-rc1 has performance regression when the + (experimental) commit-graph feature is in use, which has been + mitigated. + + * Code cleanup, docfix, build fix, etc. (merge aee9be2ebe sg/update-ref-stdin-cleanup later to maint). (merge 037714252f jc/clean-after-sanity-tests later to maint). + (merge 5b26c3c941 en/merge-recursive-cleanup later to maint). + (merge 0dcbc0392e bw/config-refer-to-gitsubmodules-doc later to maint). + (merge bb4d000e87 bw/protocol-v2 later to maint). + (merge 928f0ab4ba vs/typofixes later to maint). + (merge d7f590be84 en/rebase-i-microfixes later to maint). + (merge 81d395cc85 js/rebase-recreate-merge later to maint). + (merge 51d1863168 tz/exclude-doc-smallfixes later to maint). + (merge a9aa3c0927 ds/commit-graph later to maint). + (merge 5cf8e06474 js/enhanced-version-info later to maint). + (merge 6aaded5509 tb/config-default later to maint). + (merge 022d2ac1f3 sb/blame-color later to maint). + (merge 5a06a20e0c bp/test-drop-caches-for-windows later to maint). + (merge dd61cc1c2e jk/ui-color-always-to-auto later to maint). + (merge 1e83b9bfdd sb/trailers-docfix later to maint). + (merge ab29f1b329 sg/fast-import-dump-refs-on-checkpoint-fix later to maint). + (merge 6a8ad880f0 jn/subtree-test-fixes later to maint). + (merge ffbd51cc60 nd/pack-objects-threading-doc later to maint). + (merge e9dac7be60 es/mw-to-git-chain-fix later to maint). + (merge fe583c6c7a rs/remote-mv-leakfix later to maint). + (merge 69885ab015 en/t3031-title-fix later to maint). + (merge 8578037bed nd/config-blame-sort later to maint). + (merge 8ad169c4ba hn/config-in-code-comment later to maint). + (merge b7446fcfdf ar/t4150-am-scissors-test-fix later to maint). + (merge a8132410ee js/typofixes later to maint). + (merge 388d0ff6e5 en/update-index-doc later to maint). + (merge e05aa688dd jc/update-index-doc later to maint). + (merge 10c600172c sg/t5310-empty-input-fix later to maint). + (merge 5641eb9465 jh/partial-clone-doc later to maint). + (merge 2711b1ad5e ab/submodule-relative-url-tests later to maint). + (merge ce528de023 ab/unconditional-free-and-null later to maint). + (merge bbc072f5d8 rs/opt-updates later to maint). + (merge 69d846f053 jk/use-compat-util-in-test-tool later to maint). + (merge 1820703045 js/larger-timestamps later to maint). + (merge c8b35b95e1 sg/t4051-fix later to maint). + (merge 30612cb670 sg/t0020-conversion-fix later to maint). + (merge 15da753709 sg/t7501-thinkofix later to maint). + (merge 79b04f9b60 sg/t3903-missing-fix later to maint). + (merge 2745817028 sg/t3420-autostash-fix later to maint). + (merge 7afb0d6777 sg/test-rebase-editor-fix later to maint). + (merge 6c6ce21baa es/freebsd-iconv-portability later to maint). diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 2488544407..ec8b205145 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -80,7 +80,9 @@ GitHub-Travis CI hints section for details. Do not forget to update the documentation to describe the updated behavior and make sure that the resulting documentation set formats -well. It is currently a liberal mixture of US and UK English norms for +well (try the Documentation/doc-diff script). + +We currently have a liberal mixture of US and UK English norms for spelling and grammar, which is somewhat unfortunate. A huge patch that touches the files all over the place only to correct the inconsistency is not welcome, though. Potential clashes with other changes that can @@ -298,7 +300,7 @@ smaller project it is a good discipline to follow it. The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have -the right to pass it on as a open-source patch. The rules are +the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify the below D-C-O: [[dco]] @@ -403,7 +405,7 @@ don't demand). +git log -p {litdd} _$area_you_are_modifying_+ would help you find out who they are. . You get comments and suggestions for improvements. You may - even get them in a "on top of your change" patch form. + even get them in an "on top of your change" patch form. . Polish, refine, and re-send to the list and the people who spend their time to improve your patch. Go back to step (2). diff --git a/Documentation/config.txt b/Documentation/config.txt index 978deecfee..ad0f4510c3 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -344,6 +344,16 @@ advice.*:: Advice shown when you used linkgit:git-checkout[1] to move to the detach HEAD state, to instruct how to create a local branch after the fact. + checkoutAmbiguousRemoteBranchName:: + Advice shown when the argument to + linkgit:git-checkout[1] ambiguously resolves to a + remote tracking branch on more than one remote in + situations where an unambiguous argument would have + otherwise caused a remote-tracking branch to be + checked out. See the `checkout.defaultRemote` + configuration variable for how to set a given remote + to used by default in some situations where this + advice would be printed. amWorkDir:: Advice that shows the location of the patch file when linkgit:git-am[1] fails to apply it. @@ -354,7 +364,7 @@ advice.*:: 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 + Advice shown if a hook is ignored because the hook is not set as executable. waitingForEditor:: Print a message to the terminal whenever Git is waiting for @@ -390,16 +400,19 @@ core.hideDotFiles:: default mode is 'dotGitOnly'. core.ignoreCase:: - If true, this option enables various workarounds to enable + Internal variable which enables various workarounds to enable Git to work better on filesystems that are not case sensitive, - like FAT. For example, if a directory listing finds - "makefile" when Git expects "Makefile", Git will assume + like APFS, HFS+, FAT, NTFS, etc. For example, if a directory listing + finds "makefile" when Git expects "Makefile", Git will assume it is really the same file, and continue to remember it as "Makefile". + The default is false, except linkgit:git-clone[1] or linkgit:git-init[1] will probe and set core.ignoreCase true if appropriate when the repository is created. ++ +Git relies on the proper configuration of this variable for your operating +and file system. Modifying this value may result in unexpected behavior. core.precomposeUnicode:: This option is only used by Mac OS implementation of Git. @@ -449,10 +462,20 @@ core.untrackedCache:: See linkgit:git-update-index[1]. `keep` by default. core.checkStat:: - Determines which stat fields to match between the index - and work tree. The user can set this to 'default' or - 'minimal'. Default (or explicitly 'default'), is to check - all fields, including the sub-second part of mtime and ctime. + When missing or is set to `default`, many fields in the stat + structure are checked to detect if a file has been modified + since Git looked at it. When this configuration variable is + set to `minimal`, sub-second part of mtime and ctime, the + uid and gid of the owner of the file, the inode number (and + the device number, if Git was compiled to use it), are + excluded from the check among these fields, leaving only the + whole-second part of mtime (and ctime, if `core.trustCtime` + is set) and the filesize to be checked. ++ +There are implementations of Git that do not leave usable values in +some fields (e.g. JGit); by excluding these fields from the +comparison, the `minimal` mode may help interoperability when the +same repository is used by these other systems at the same time. core.quotePath:: Commands that output paths (e.g. 'ls-files', 'diff'), will @@ -904,12 +927,20 @@ core.notesRef:: This setting defaults to "refs/notes/commits", and it can be overridden by the `GIT_NOTES_REF` environment variable. See linkgit:git-notes[1]. -gc.commitGraph:: - If true, then gc will rewrite the commit-graph file when - linkgit:git-gc[1] is run. When using linkgit:git-gc[1] - '--auto' the commit-graph will be updated if housekeeping is - required. Default is false. See linkgit:git-commit-graph[1] - for details. +core.commitGraph:: + If true, then git will read the commit-graph file (if it exists) + to parse the graph structure of commits. Defaults to false. See + linkgit:git-commit-graph[1] for more information. + +core.useReplaceRefs:: + If set to `false`, behave as if the `--no-replace-objects` + option was given on the command line. See linkgit:git[1] and + linkgit:git-replace[1] for more information. + +core.multiPackIndex:: + Use the multi-pack-index file to track multiple packfiles using a + single index. See link:technical/multi-pack-index.html[the + multi-pack-index design document]. core.sparseCheckout:: Enable "sparse checkout" feature. See section "Sparse checkout" in @@ -977,23 +1008,28 @@ 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.coloring:: + This determines the coloring scheme to be applied to blame + output. It can be 'repeatedLines', 'highlightRecent', + or 'none' which is the default. 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]. +blame.showEmail:: + Show the author email instead of author name in linkgit:git-blame[1]. + This option defaults to false. + +blame.showRoot:: + Do not treat root commits as boundaries in linkgit:git-blame[1]. + This option defaults to false. + branch.autoSetupMerge:: Tells 'git branch' and 'git checkout' to set up new branches so that linkgit:git-pull[1] will appropriately merge from the @@ -1021,6 +1057,12 @@ branch.autoSetupRebase:: branch to track another branch. This option defaults to never. +branch.sort:: + This variable controls the sort ordering of branches when displayed by + linkgit:git-branch[1]. Without the "--sort=<value>" option provided, the + value of this variable will be used as the default. + See linkgit:git-for-each-ref[1] field names for valid values. + branch.<name>.remote:: When on branch <name>, it tells 'git fetch' and 'git push' which remote to fetch from/push to. The remote to push to @@ -1101,6 +1143,30 @@ browser.<tool>.path:: browse HTML help (see `-w` option in linkgit:git-help[1]) or a working repository in gitweb (see linkgit:git-instaweb[1]). +checkout.defaultRemote:: + When you run 'git checkout <something>' and only have one + remote, it may implicitly fall back on checking out and + tracking e.g. 'origin/<something>'. This stops working as soon + as you have more than one remote with a '<something>' + reference. This setting allows for setting the name of a + preferred remote that should always win when it comes to + disambiguation. The typical use-case is to set this to + `origin`. ++ +Currently this is used by linkgit:git-checkout[1] when 'git checkout +<something>' will checkout the '<something>' branch on another remote, +and by linkgit:git-worktree[1] when 'git worktree add' refers to a +remote branch. This setting might be used for other checkout-like +commands or functionality in the future. + +checkout.optimizeNewBranch:: + Optimizes the performance of "git checkout -b <new_branch>" when + using sparse-checkout. When set to true, git will not update the + repo based on the current sparse-checkout settings. This means it + will not update the skip-worktree bit in the index nor add/remove + files in the working directory to reflect the current sparse checkout + settings nor will it show the local changes. + clean.requireForce:: A boolean to make git-clean do nothing unless given -f, -i or -n. Defaults to true. @@ -1115,6 +1181,28 @@ color.advice:: color.advice.hint:: Use customized color for hints. +color.blame.highlightRecent:: + This can be used to color the metadata of a blame line depending + on age of the line. ++ +This setting should be set to a comma-separated list of color and date settings, +starting and ending with a color, the dates should be set from oldest to newest. +The metadata will be colored given the colors if the the line was introduced +before the given timestamp, overwriting older timestamped colors. ++ +Instead of an absolute timestamp relative timestamps work as well, e.g. +2.weeks.ago is valid to address anything older than 2 weeks. ++ +It defaults to 'blue,12 month ago,white,1 month ago,red', which colors +everything older than one year blue, recent changes between one month and +one year old are kept white, and lines introduced within the last month are +colored red. + +color.blame.repeatedLines:: + Use the customized color for the part of git-blame output that + is repeated meta information per line (such as commit id, + author name, date and timezone). Defaults to cyan. + color.branch:: A boolean to enable/disable color in the output of linkgit:git-branch[1]. May be set to `always`, @@ -1142,13 +1230,6 @@ This does not affect linkgit:git-format-patch[1] or the 'git-diff-{asterisk}' plumbing commands. Can be overridden on the command line with the `--color[=<when>]` option. -diff.colorMoved:: - If set to either a valid `<mode>` or a true value, moved lines - in a diff are colored differently, for details of valid modes - see '--color-moved' in linkgit:git-diff[1]. If simply set to - true the default color mode will be used. When set to false, - moved lines are not colored. - color.diff.<slot>:: Use customized color for diff colorization. `<slot>` specifies which part of the patch to use the specified color, and is one @@ -1159,8 +1240,10 @@ color.diff.<slot>:: (highlighting whitespace errors), `oldMoved` (deleted lines), `newMoved` (added lines), `oldMovedDimmed`, `oldMovedAlternative`, `oldMovedAlternativeDimmed`, `newMovedDimmed`, `newMovedAlternative` - and `newMovedAlternativeDimmed` (See the '<mode>' - setting of '--color-moved' in linkgit:git-diff[1] for details). + `newMovedAlternativeDimmed` (See the '<mode>' + setting of '--color-moved' in linkgit:git-diff[1] for details), + `contextDimmed`, `oldDimmed`, `newDimmed`, `contextBold`, + `oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details). color.decorate.<slot>:: Use customized color for 'git log --decorate' output. `<slot>` is one @@ -1185,8 +1268,10 @@ color.grep.<slot>:: filename prefix (when not using `-h`) `function`;; function name lines (when using `-p`) -`linenumber`;; +`lineNumber`;; line number prefix (when using `-n`) +`column`;; + column number prefix (when using `--column`) `match`;; matching text (same as setting `matchContext` and `matchSelected`) `matchContext`;; @@ -1227,6 +1312,18 @@ color.push:: color.push.error:: Use customized color for push errors. +color.remote:: + If set, keywords at the start of the line are highlighted. The + keywords are "error", "warning", "hint" and "success", and are + matched case-insensitively. May be set to `always`, `false` (or + `never`) or `auto` (or `true`). If unset, then the value of + `color.ui` is used (`auto` by default). + +color.remote.<slot>:: + Use customized color for each remote keyword. `<slot>` may be + `hint`, `warning`, `success` or `error` which match the + corresponding keyword. + color.showBranch:: A boolean to enable/disable color in the output of linkgit:git-show-branch[1]. May be set to `always`, @@ -1255,33 +1352,6 @@ color.status.<slot>:: status short-format), or `unmerged` (files which have unmerged changes). -color.blame.repeatedLines:: - Use the customized color for the part of git-blame output that - is repeated meta information per line (such as commit id, - author name, date and timezone). Defaults to cyan. - -color.blame.highlightRecent:: - This can be used to color the metadata of a blame line depending - on age of the line. -+ -This setting should be set to a comma-separated list of color and date settings, -starting and ending with a color, the dates should be set from oldest to newest. -The metadata will be colored given the colors if the the line was introduced -before the given timestamp, overwriting older timestamped colors. -+ -Instead of an absolute timestamp relative timestamps work as well, e.g. -2.weeks.ago is valid to address anything older than 2 weeks. -+ -It defaults to 'blue,12 month ago,white,1 month ago,red', which colors -everything older than one year blue, recent changes between one month and -one year old are kept white, and lines introduced within the last month are -colored red. - -blame.coloring:: - This determines the coloring scheme to be applied to blame - output. It can be 'repeatedLines', 'highlightRecent', - or 'none' which is the default. - color.transport:: A boolean to enable/disable color when pushes are rejected. May be set to `always`, `false` (or `never`) or `auto` (or `true`), in which @@ -1461,10 +1531,19 @@ fetch.recurseSubmodules:: fetch.fsckObjects:: If it is set to true, git-fetch-pack will check all fetched - objects. It will abort in the case of a malformed object or a - broken link. The result of an abort are only dangling objects. - Defaults to false. If not set, the value of `transfer.fsckObjects` - is used instead. + objects. See `transfer.fsckObjects` for what's + checked. Defaults to false. If not set, the value of + `transfer.fsckObjects` is used instead. + +fetch.fsck.<msg-id>:: + Acts like `fsck.<msg-id>`, but is used by + linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See + the `fsck.<msg-id>` documentation for details. + +fetch.fsck.skipList:: + Acts like `fsck.skipList`, but is used by + linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See + the `fsck.skipList` documentation for details. fetch.unpackLimit:: If the number of objects fetched over the Git native @@ -1495,6 +1574,18 @@ fetch.output:: `full` and `compact`. Default value is `full`. See section OUTPUT in linkgit:git-fetch[1] for detail. +fetch.negotiationAlgorithm:: + Control how information about the commits in the local repository is + sent when negotiating the contents of the packfile to be sent by the + server. Set to "skipping" to use an algorithm that skips commits in an + effort to converge faster, but may result in a larger-than-necessary + packfile; The default is "default" which instructs Git to use the default algorithm + that never skips commits (unless the server has acknowledged it or one + of its descendants). + Unknown values will cause 'git fetch' to error out. ++ +See also the `--negotiation-tip` option for linkgit:git-fetch[1]. + format.attach:: Enable multipart/mixed attachments as the default for 'format-patch'. The value can also be a double quoted string @@ -1594,15 +1685,42 @@ filter.<driver>.smudge:: linkgit:gitattributes[5] for details. fsck.<msg-id>:: - Allows overriding the message type (error, warn or ignore) of a - specific message ID such as `missingEmail`. -+ -For convenience, fsck prefixes the error/warning with the message ID, -e.g. "missingEmail: invalid author/committer line - missing email" means -that setting `fsck.missingEmail = ignore` will hide that issue. -+ -This feature is intended to support working with legacy repositories -which cannot be repaired without disruptive changes. + During fsck git may find issues with legacy data which + wouldn't be generated by current versions of git, and which + wouldn't be sent over the wire if `transfer.fsckObjects` was + set. This feature is intended to support working with legacy + repositories containing such data. ++ +Setting `fsck.<msg-id>` will be picked up by linkgit:git-fsck[1], but +to accept pushes of such data set `receive.fsck.<msg-id>` instead, or +to clone or fetch it set `fetch.fsck.<msg-id>`. ++ +The rest of the documentation discusses `fsck.*` for brevity, but the +same applies for the corresponding `receive.fsck.*` and +`fetch.<msg-id>.*`. variables. ++ +Unlike variables like `color.ui` and `core.editor` the +`receive.fsck.<msg-id>` and `fetch.fsck.<msg-id>` variables will not +fall back on the `fsck.<msg-id>` configuration if they aren't set. To +uniformly configure the same fsck settings in different circumstances +all three of them they must all set to the same values. ++ +When `fsck.<msg-id>` is set, errors can be switched to warnings and +vice versa by configuring the `fsck.<msg-id>` setting where the +`<msg-id>` is the fsck message ID and the value is one of `error`, +`warn` or `ignore`. For convenience, fsck prefixes the error/warning +with the message ID, e.g. "missingEmail: invalid author/committer line +- missing email" means that setting `fsck.missingEmail = ignore` will +hide that issue. ++ +In general, it is better to enumerate existing objects with problems +with `fsck.skipList`, instead of listing the kind of breakages these +problematic objects share to be ignored, as doing the latter will +allow new instances of the same breakages go unnoticed. ++ +Setting an unknown `fsck.<msg-id>` value will cause fsck to die, but +doing the same for `receive.fsck.<msg-id>` and `fetch.fsck.<msg-id>` +will only cause git to warn. fsck.skipList:: The path to a sorted list of object names (i.e. one SHA-1 per @@ -1611,6 +1729,15 @@ fsck.skipList:: should be accepted despite early commits containing errors that can be safely ignored such as invalid committer email addresses. Note: corrupt objects cannot be skipped with this setting. ++ +Like `fsck.<msg-id>` this variable has corresponding +`receive.fsck.skipList` and `fetch.fsck.skipList` variants. ++ +Unlike variables like `color.ui` and `core.editor` the +`receive.fsck.skipList` and `fetch.fsck.skipList` variables will not +fall back on the `fsck.skipList` configuration if they aren't set. To +uniformly configure the same fsck settings in different circumstances +all three of them they must all set to the same values. gc.aggressiveDepth:: The depth parameter used in the delta compression @@ -1651,6 +1778,13 @@ this configuration variable is ignored, all packs except the base pack will be repacked. After this the number of packs should go below gc.autoPackLimit and gc.bigPackThreshold should be respected again. +gc.writeCommitGraph:: + If true, then gc will rewrite the commit-graph file when + linkgit:git-gc[1] is run. When using linkgit:git-gc[1] + '--auto' the commit-graph will be updated if housekeeping is + required. Default is false. See linkgit:git-commit-graph[1] + for details. + gc.logExpiry:: If the file gc.log exists, then `git gc --auto` won't run unless that file is more than 'gc.logExpiry' old. Default is @@ -1801,6 +1935,9 @@ gitweb.snapshot:: grep.lineNumber:: If set to true, enable `-n` option by default. +grep.column:: + If set to true, enable the `--column` option by default. + grep.patternType:: Set the default matching behavior. Using a value of 'basic', 'extended', 'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`, @@ -1831,6 +1968,16 @@ gpg.program:: signed, and the program is expected to send the result to its standard output. +gpg.format:: + Specifies which key format to use when signing with `--gpg-sign`. + Default is "openpgp" and another possible value is "x509". + +gpg.<format>.program:: + Use this to customize the program used for the signing format you + chose. (see `gpg.program` and `gpg.format`) `gpg.program` can still + be used as a legacy synonym for `gpg.openpgp.program`. The default + value for `gpg.x509.program` is "gpgsm". + gui.commitMsgWidth:: Defines how wide the commit message window is in the linkgit:git-gui[1]. "75" is the default. @@ -2537,6 +2684,21 @@ Note that changing the compression level will not automatically recompress all existing objects. You can force recompression by passing the -F option to linkgit:git-repack[1]. +pack.island:: + An extended regular expression configuring a set of delta + islands. See "DELTA ISLANDS" in linkgit:git-pack-objects[1] + for details. + +pack.islandCore:: + Specify an island name which gets to have its objects be + packed first. This creates a kind of pseudo-pack at the front + of one pack, so that the objects from the specified island are + hopefully faster to copy into any pack that should be served + to a user requesting these objects. In practice this means + that the island specified should likely correspond to what is + the most commonly cloned in the repo. See also "DELTA ISLANDS" + in linkgit:git-pack-objects[1]. + pack.deltaCacheSize:: The maximum memory in bytes used for caching deltas in linkgit:git-pack-objects[1] before writing them out to a pack. @@ -2694,6 +2856,8 @@ protocol.version:: * `1` - the original wire protocol with the addition of a version string in the initial response from the server. +* `2` - link:technical/protocol-v2.html[wire protocol version 2]. + -- pull.ff:: @@ -2884,32 +3048,21 @@ receive.certNonceSlop:: receive.fsckObjects:: If it is set to true, git-receive-pack will check all received - objects. It will abort in the case of a malformed object or a - broken link. The result of an abort are only dangling objects. - Defaults to false. If not set, the value of `transfer.fsckObjects` - is used instead. + objects. See `transfer.fsckObjects` for what's checked. + Defaults to false. If not set, the value of + `transfer.fsckObjects` is used instead. receive.fsck.<msg-id>:: - When `receive.fsckObjects` is set to true, errors can be switched - to warnings and vice versa by configuring the `receive.fsck.<msg-id>` - setting where the `<msg-id>` is the fsck message ID and the value - is one of `error`, `warn` or `ignore`. For convenience, fsck prefixes - the error/warning with the message ID, e.g. "missingEmail: invalid - author/committer line - missing email" means that setting - `receive.fsck.missingEmail = ignore` will hide that issue. -+ -This feature is intended to support working with legacy repositories -which would not pass pushing when `receive.fsckObjects = true`, allowing -the host to accept repositories with certain known issues but still catch -other issues. + Acts like `fsck.<msg-id>`, but is used by + linkgit:git-receive-pack[1] instead of + linkgit:git-fsck[1]. See the `fsck.<msg-id>` documentation for + details. receive.fsck.skipList:: - The path to a sorted list of object names (i.e. one SHA-1 per - line) that are known to be broken in a non-fatal way and should - be ignored. This feature is useful when an established project - should be accepted despite early commits containing errors that - can be safely ignored such as invalid committer email addresses. - Note: corrupt objects cannot be skipped with this setting. + Acts like `fsck.skipList`, but is used by + linkgit:git-receive-pack[1] instead of + linkgit:git-fsck[1]. See the `fsck.skipList` documentation for + details. receive.keepAlive:: After receiving the pack from the client, `receive-pack` may @@ -3082,6 +3235,10 @@ repack.packKeptObjects:: index is being written (either via `--write-bitmap-index` or `repack.writeBitmaps`). +repack.useDeltaIslands:: + If set to true, makes `git repack` act as if `--delta-islands` + was passed. Defaults to `false`. + repack.writeBitmaps:: When true, git will write a bitmap index when packing all objects to disk (e.g., when `git repack -a` is run). This @@ -3331,12 +3488,13 @@ submodule.<name>.ignore:: submodule.<name>.active:: Boolean value indicating if the submodule is of interest to git commands. This config option takes precedence over the - submodule.active config option. + submodule.active config option. See linkgit:gitsubmodules[7] for + details. submodule.active:: A repeated field which contains a pathspec used to match against a submodule's path to determine if the submodule is of interest to git - commands. + commands. See linkgit:gitsubmodules[7] for details. submodule.recurse:: Specifies if commands recurse into submodules by default. This @@ -3383,6 +3541,40 @@ transfer.fsckObjects:: When `fetch.fsckObjects` or `receive.fsckObjects` are not set, the value of this variable is used instead. Defaults to false. ++ +When set, the fetch or receive will abort in the case of a malformed +object or a link to a nonexistent object. In addition, various other +issues are checked for, including legacy issues (see `fsck.<msg-id>`), +and potential security issues like the existence of a `.GIT` directory +or a malicious `.gitmodules` file (see the release notes for v2.2.1 +and v2.17.1 for details). Other sanity and security checks may be +added in future releases. ++ +On the receiving side, failing fsckObjects will make those objects +unreachable, see "QUARANTINE ENVIRONMENT" in +linkgit:git-receive-pack[1]. On the fetch side, malformed objects will +instead be left unreferenced in the repository. ++ +Due to the non-quarantine nature of the `fetch.fsckObjects` +implementation it can not be relied upon to leave the object store +clean like `receive.fsckObjects` can. ++ +As objects are unpacked they're written to the object store, so there +can be cases where malicious objects get introduced even though the +"fetch" failed, only to have a subsequent "fetch" succeed because only +new incoming objects are checked, not those that have already been +written to the object store. That difference in behavior should not be +relied upon. In the future, such objects may be quarantined for +"fetch" as well. ++ +For now, the paranoid need to find some way to emulate the quarantine +environment if they'd like the same protection as "push". E.g. in the +case of an internal mirror do the mirroring in two steps, one to fetch +the untrusted objects, and then do a second "push" (which will use the +quarantine) to another internal repo, and have internal clients +consume this pushed-to repository, or embargo internal fetches and +only allow them once a full "fsck" has run (and no new fetches have +happened in the meantime). transfer.hideRefs:: String(s) `receive-pack` and `upload-pack` use to decide which @@ -3483,6 +3675,13 @@ Note that this configuration variable is ignored if it is seen in the repository-level config (this is a safety measure against fetching from untrusted repositories). +uploadpack.allowRefInWant:: + If this option is set, `upload-pack` will support the `ref-in-want` + feature of the protocol version 2 `fetch` command. This feature + is intended for the benefit of load-balanced servers which may + not have the same view of what OIDs their refs point to due to + replication delay. + url.<base>.insteadOf:: Any URL that starts with this value will be rewritten to start, instead, with <base>. In cases where some site serves a diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt index 77caa66c2f..85bca83c30 100644 --- a/Documentation/diff-config.txt +++ b/Documentation/diff-config.txt @@ -208,3 +208,15 @@ diff.wsErrorHighlight:: whitespace errors are colored with `color.diff.whitespace`. The command line option `--ws-error-highlight=<kind>` overrides this setting. + +diff.colorMoved:: + If set to either a valid `<mode>` or a true value, moved lines + in a diff are colored differently, for details of valid modes + see '--color-moved' in linkgit:git-diff[1]. If simply set to + true the default color mode will be used. When set to false, + moved lines are not colored. + +diff.colorMovedWS:: + When moved lines are colored using e.g. the `diff.colorMoved` setting, + this option controls the `<mode>` how spaces are treated + for details of valid modes see '--color-moved-ws' in linkgit:git-diff[1]. diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 41064909ee..0378cd574e 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -276,16 +276,46 @@ plain:: that are added somewhere else in the diff. This mode picks up any moved line, but it is not very useful in a review to determine if a block of code was moved without permutation. -zebra:: +blocks:: Blocks of moved text of at least 20 alphanumeric characters are detected greedily. The detected blocks are - painted using either the 'color.diff.{old,new}Moved' color or + painted using either the 'color.diff.{old,new}Moved' color. + Adjacent blocks cannot be told apart. +zebra:: + Blocks of moved text are detected as in 'blocks' mode. The blocks + are painted using either the 'color.diff.{old,new}Moved' color or 'color.diff.{old,new}MovedAlternative'. The change between the two colors indicates that a new block was detected. -dimmed_zebra:: +dimmed-zebra:: Similar to 'zebra', but additional dimming of uninteresting parts of moved code is performed. The bordering lines of two adjacent blocks are considered interesting, the rest is uninteresting. + `dimmed_zebra` is a deprecated synonym. +-- + +--color-moved-ws=<modes>:: + This configures how white spaces are ignored when performing the + move detection for `--color-moved`. +ifdef::git-diff[] + It can be set by the `diff.colorMovedWS` configuration setting. +endif::git-diff[] + These modes can be given as a comma separated list: ++ +-- +ignore-space-at-eol:: + Ignore changes in whitespace at EOL. +ignore-space-change:: + Ignore changes in amount of whitespace. This ignores whitespace + at line end, and considers all other sequences of one or + more whitespace characters to be equivalent. +ignore-all-space:: + Ignore whitespace when comparing lines. This ignores differences + even if one line has whitespace where the other line has none. +allow-indentation-change:: + Initially ignore any white spaces in the move detection, then + group the moved code blocks only into a block if the change in + whitespace is the same per line. This is incompatible with the + other modes. -- --word-diff[=<mode>]:: diff --git a/Documentation/doc-diff b/Documentation/doc-diff new file mode 100755 index 0000000000..dfd9418778 --- /dev/null +++ b/Documentation/doc-diff @@ -0,0 +1,130 @@ +#!/bin/sh +# +# Build two documentation trees and diff the resulting formatted output. +# Compared to a source diff, this can reveal mistakes in the formatting. +# For example: +# +# ./doc-diff origin/master HEAD +# +# would show the differences introduced by a branch based on master. + +OPTIONS_SPEC="\ +doc-diff [options] <from> <to> [-- <diff-options>] +doc-diff (-c|--clean) +-- +j=n parallel argument to pass to make +f force rebuild; do not rely on cached results +c,clean cleanup temporary working files +" +SUBDIRECTORY_OK=1 +. "$(git --exec-path)/git-sh-setup" + +parallel= +force= +clean= +while test $# -gt 0 +do + case "$1" in + -j) + parallel=$2; shift ;; + -c|--clean) + clean=t ;; + -f) + force=t ;; + --) + shift; break ;; + *) + usage ;; + esac + shift +done + +cd_to_toplevel +tmp=Documentation/tmp-doc-diff + +if test -n "$clean" +then + test $# -eq 0 || usage + git worktree remove --force "$tmp/worktree" 2>/dev/null + rm -rf "$tmp" + exit 0 +fi + +if test -z "$parallel" +then + parallel=$(getconf _NPROCESSORS_ONLN 2>/dev/null) + if test $? != 0 || test -z "$parallel" + then + parallel=1 + fi +fi + +test $# -gt 1 || usage +from=$1; shift +to=$1; shift + +from_oid=$(git rev-parse --verify "$from") || exit 1 +to_oid=$(git rev-parse --verify "$to") || exit 1 + +if test -n "$force" +then + rm -rf "$tmp" +fi + +# We'll do both builds in a single worktree, which lets "make" reuse +# results that don't differ between the two trees. +if ! test -d "$tmp/worktree" +then + git worktree add -f --detach "$tmp/worktree" "$from" && + dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g') && + ln -s "$dots/config.mak" "$tmp/worktree/config.mak" +fi + +# generate_render_makefile <srcdir> <dstdir> +generate_render_makefile () { + find "$1" -type f | + while read src + do + dst=$2/${src#$1/} + printf 'all:: %s\n' "$dst" + printf '%s: %s\n' "$dst" "$src" + printf '\t@echo >&2 " RENDER $(notdir $@)" && \\\n' + printf '\tmkdir -p $(dir $@) && \\\n' + printf '\tMANWIDTH=80 man $< >$@+ && \\\n' + printf '\tmv $@+ $@\n' + done +} + +# render_tree <committish_oid> +render_tree () { + # Skip install-man entirely if we already have an installed directory. + # We can't rely on make here, since "install-man" unconditionally + # copies the files (spending effort, but also updating timestamps that + # we then can't rely on during the render step). We use "mv" to make + # sure we don't get confused by a previous run that failed partway + # through. + if ! test -d "$tmp/installed/$1" + then + git -C "$tmp/worktree" checkout --detach "$1" && + make -j$parallel -C "$tmp/worktree" \ + GIT_VERSION=omitted \ + SOURCE_DATE_EPOCH=0 \ + DESTDIR="$PWD/$tmp/installed/$1+" \ + install-man && + mv "$tmp/installed/$1+" "$tmp/installed/$1" + fi && + + # As with "installed" above, we skip the render if it's already been + # done. So using make here is primarily just about running in + # parallel. + if ! test -d "$tmp/rendered/$1" + then + generate_render_makefile "$tmp/installed/$1" "$tmp/rendered/$1+" | + make -j$parallel -f - && + mv "$tmp/rendered/$1+" "$tmp/rendered/$1" + fi +} + +render_tree $from_oid && +render_tree $to_oid && +git -C $tmp/rendered diff --no-index "$@" $from_oid $to_oid diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 97d3217df9..fa0a3151b3 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -42,6 +42,25 @@ the current repository has the same history as the source repository. .git/shallow. This option updates .git/shallow and accept such refs. +--negotiation-tip=<commit|glob>:: + By default, Git will report, to the server, commits reachable + from all local refs to find common commits in an attempt to + reduce the size of the to-be-received packfile. If specified, + Git will only report commits reachable from the given tips. + This is useful to speed up fetches when the user knows which + local ref is likely to have commits in common with the + upstream ref being fetched. ++ +This option may be specified more than once; if so, Git will report +commits reachable from any of the given commits. ++ +The argument to this option may be a glob on ref names, a ref, or the (possibly +abbreviated) SHA-1 of a commit. Specifying a glob is equivalent to specifying +this option multiple times, one for each matching ref name. ++ +See also the `fetch.negotiationAlgorithm` configuration variable +documented in linkgit:git-config[1]. + ifndef::git-pull[] --dry-run:: Show what would be done, without making any changes. @@ -49,11 +68,16 @@ endif::git-pull[] -f:: --force:: - When 'git fetch' is used with `<rbranch>:<lbranch>` - refspec, it refuses to update the local branch - `<lbranch>` unless the remote branch `<rbranch>` it - fetches is a descendant of `<lbranch>`. This option - overrides that check. + When 'git fetch' is used with `<src>:<dst>` refspec it may + refuse to update the local branch as discussed +ifdef::git-pull[] + in the `<refspec>` part of the linkgit:git-fetch[1] + documentation. +endif::git-pull[] +ifndef::git-pull[] + in the `<refspec>` part below. +endif::git-pull[] + This option overrides that check. -k:: --keep:: diff --git a/Documentation/git-bisect-lk2009.txt b/Documentation/git-bisect-lk2009.txt index 78479b003e..0f9ef2f25e 100644 --- a/Documentation/git-bisect-lk2009.txt +++ b/Documentation/git-bisect-lk2009.txt @@ -1103,7 +1103,7 @@ _____________ Combining test suites, git bisect and other systems together ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We have seen that test suites an git bisect are very powerful when +We have seen that test suites and git bisect are very powerful when used together. It can be even more powerful if you can combine them with other systems. diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 02eccbb931..bf5316ffa9 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -14,7 +14,7 @@ SYNOPSIS [(--merged | --no-merged) [<commit>]] [--contains [<commit]] [--no-contains [<commit>]] [--points-at <object>] [--format=<format>] [<pattern>...] -'git branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>] +'git branch' [--track | --no-track] [-f] <branchname> [<start-point>] 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>] 'git branch' --unset-upstream [<branchname>] 'git branch' (-m | -M) [<oldbranch>] <newbranch> @@ -91,7 +91,6 @@ OPTIONS -D:: Shortcut for `--delete --force`. --l:: --create-reflog:: Create the branch's reflog. This activates recording of all changes made to the branch ref, enabling use of date @@ -155,14 +154,11 @@ This option is only applicable in non-verbose mode. --all:: List both remote-tracking branches and local branches. +-l:: --list:: List branches. With optional `<pattern>...`, e.g. `git branch --list 'maint-*'`, list only the branches that match the pattern(s). -+ -This should not be confused with `git branch -l <branchname>`, -which creates a branch named `<branchname>` with a reflog. -See `--create-reflog` above for details. -v:: -vv:: @@ -267,10 +263,11 @@ start-point is either a local or remote-tracking branch. order of the value. You may use the --sort=<key> option multiple times, in which case the last key becomes the primary key. The keys supported are the same as those in `git - for-each-ref`. Sort order defaults to sorting based on the + for-each-ref`. Sort order defaults to the value configured for the + `branch.sort` variable if exists, or to sorting based on the full refname (including `refs/...` prefix). This lists detached HEAD (if present) first, then local branches and - finally remote-tracking branches. + finally remote-tracking branches. See linkgit:git-config[1]. --points-at <object>:: diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index f90f09b03f..74013335a1 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -104,6 +104,16 @@ OPTIONS buffering; this is much more efficient when invoking `--batch-check` on a large number of objects. +--unordered:: + When `--batch-all-objects` is in use, visit objects in an + order which may be more efficient for accessing the object + contents than hash order. The exact details of the order are + unspecified, but if you do not require a specific order, this + should generally result in faster output, especially with + `--batch`. Note that `cat-file` will still show each object + only once, even if it is stored multiple times in the + repository. + --allow-unknown-type:: Allow -s or -t to query broken/corrupt objects of unknown type. diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index ca5fc9c798..9db02928c4 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -38,6 +38,15 @@ equivalent to $ git checkout -b <branch> --track <remote>/<branch> ------------ + +If the branch exists in multiple remotes and one of them is named by +the `checkout.defaultRemote` configuration variable, we'll use that +one for the purposes of disambiguation, even if the `<branch>` isn't +unique across all remotes. Set it to +e.g. `checkout.defaultRemote=origin` to always checkout remote +branches from there if `<branch>` is ambiguous but exists on the +'origin' remote. See also `checkout.defaultRemote` in +linkgit:git-config[1]. ++ You could omit <branch>, in which case the command degenerates to "check out the current branch", which is a glorified no-op with rather expensive side-effects to show only the tracking information, diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 18ddc78f42..8e240435be 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -453,6 +453,27 @@ http.sslverify false include::config.txt[] +BUGS +---- +When using the deprecated `[section.subsection]` syntax, changing a value +will result in adding a multi-line key instead of a change, if the subsection +is given with at least one uppercase character. For example when the config +looks like + +-------- + [section.subsection] + key = value1 +-------- + +and running `git config section.Subsection.key value2` will result in + +-------- + [section.subsection] + key = value1 + key = value2 +-------- + + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index 085d177d97..901faef1bf 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -57,7 +57,7 @@ OPTIONS `xx`; for example `%00` interpolates to `\0` (NUL), `%09` to `\t` (TAB) and `%0a` to `\n` (LF). ---color[=<when>]: +--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). diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index b41e1329a7..aba4c5febe 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -23,6 +23,8 @@ SYNOPSIS [(--reroll-count|-v) <n>] [--to=<email>] [--cc=<email>] [--[no-]cover-letter] [--quiet] [--notes[=<ref>]] + [--interdiff=<previous>] + [--range-diff=<previous> [--creation-factor=<percent>]] [--progress] [<common diff options>] [ <since> | <revision range> ] @@ -228,6 +230,33 @@ feeding the result to `git send-email`. containing the branch description, shortlog and the overall diffstat. You can fill in a description in the file before sending it out. +--interdiff=<previous>:: + As a reviewer aid, insert an interdiff into the cover letter, + or as commentary of the lone patch of a 1-patch series, showing + the differences between the previous version of the patch series and + the series currently being formatted. `previous` is a single revision + naming the tip of the previous series which shares a common base with + the series being formatted (for example `git format-patch + --cover-letter --interdiff=feature/v1 -3 feature/v2`). + +--range-diff=<previous>:: + As a reviewer aid, insert a range-diff (see linkgit:git-range-diff[1]) + into the cover letter, or as commentary of the lone patch of a + 1-patch series, showing the differences between the previous + version of the patch series and the series currently being formatted. + `previous` can be a single revision naming the tip of the previous + series if it shares a common base with the series being formatted (for + example `git format-patch --cover-letter --range-diff=feature/v1 -3 + feature/v2`), or a revision range if the two versions of the series are + disjoint (for example `git format-patch --cover-letter + --range-diff=feature/v1~3..feature/v1 -3 feature/v2`). + +--creation-factor=<percent>:: + Used with `--range-diff`, tweak the heuristic which matches up commits + between the previous and current series of patches by adjusting the + creation/deletion cost fudge factor. See linkgit:git-range-diff[1]) + for details. + --notes[=<ref>]:: Append the notes (see linkgit:git-notes[1]) for the commit after the three-dash line. diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 312409a607..a3049af1a3 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -13,11 +13,11 @@ SYNOPSIS [-v | --invert-match] [-h|-H] [--full-name] [-E | --extended-regexp] [-G | --basic-regexp] [-P | --perl-regexp] - [-F | --fixed-strings] [-n | --line-number] + [-F | --fixed-strings] [-n | --line-number] [--column] [-l | --files-with-matches] [-L | --files-without-match] [(-O | --open-files-in-pager) [<pager>]] [-z | --null] - [-c | --count] [--all-match] [-q | --quiet] + [ -o | --only-matching ] [-c | --count] [--all-match] [-q | --quiet] [--max-depth <depth>] [--color[=<when>] | --no-color] [--break] [--heading] [-p | --show-function] @@ -44,6 +44,9 @@ CONFIGURATION grep.lineNumber:: If set to true, enable `-n` option by default. +grep.column:: + If set to true, enable the `--column` option by default. + grep.patternType:: Set the default matching behavior. Using a value of 'basic', 'extended', 'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`, @@ -169,6 +172,10 @@ providing this option will cause it to die. --line-number:: Prefix the line number to matching lines. +--column:: + Prefix the 1-indexed byte-offset of the first match from the start of the + matching line. + -l:: --files-with-matches:: --name-only:: @@ -194,6 +201,11 @@ providing this option will cause it to die. Output \0 instead of the character that normally follows a file name. +-o:: +--only-matching:: + Print only the matched (non-empty) parts of a matching line, with each such + part on a separate output line. + -c:: --count:: Instead of showing every matched line, show the number of diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt index 032613c420..7b157441eb 100644 --- a/Documentation/git-imap-send.txt +++ b/Documentation/git-imap-send.txt @@ -68,8 +68,8 @@ imap.tunnel:: to the server. Required when imap.host is not set. imap.host:: - A URL identifying the server. Use a `imap://` prefix for non-secure - connections and a `imaps://` prefix for secure connections. + A URL identifying the server. Use an `imap://` prefix for non-secure + connections and an `imaps://` prefix for secure connections. Ignored when imap.tunnel is set, but required otherwise. imap.user:: diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt index 9111c47a1b..a5e8b36f62 100644 --- a/Documentation/git-interpret-trailers.txt +++ b/Documentation/git-interpret-trailers.txt @@ -56,8 +56,9 @@ least one Git-generated or user-configured trailer and consists of at least 25% trailers. The group must be preceded by one or more empty (or whitespace-only) lines. The group must either be at the end of the message or be the last -non-whitespace lines before a line that starts with '---'. Such three -minus signs start the patch part of the message. +non-whitespace lines before a line that starts with '---' (followed by a +space or the end of the line). Such three minus signs start the patch +part of the message. See also `--no-divider` below. When reading trailers, there can be whitespaces after the token, the separator and the value. There can also be whitespaces @@ -88,7 +89,8 @@ OPTIONS Specify where all new trailers will be added. A setting provided with '--where' overrides all configuration variables and applies to all '--trailer' options until the next occurrence of - '--where' or '--no-where'. + '--where' or '--no-where'. Possible values are `after`, `before`, + `end` or `start`. --if-exists <action>:: --no-if-exists:: @@ -96,7 +98,8 @@ OPTIONS least one trailer with the same <token> in the message. A setting provided with '--if-exists' overrides all configuration variables and applies to all '--trailer' options until the next occurrence of - '--if-exists' or '--no-if-exists'. + '--if-exists' or '--no-if-exists'. Possible actions are `addIfDifferent`, + `addIfDifferentNeighbor`, `add`, `replace` and `doNothing`. --if-missing <action>:: --no-if-missing:: @@ -104,7 +107,8 @@ OPTIONS trailer with the same <token> in the message. A setting provided with '--if-missing' overrides all configuration variables and applies to all '--trailer' options until the next occurrence of - '--if-missing' or '--no-if-missing'. + '--if-missing' or '--no-if-missing'. Possible actions are `doNothing` + or `add`. --only-trailers:: Output only the trailers, not any other parts of the input. @@ -122,6 +126,11 @@ OPTIONS A convenience alias for `--only-trailers --only-input --unfold`. +--no-divider:: + Do not treat `---` as the end of the commit message. Use this + when you know your input contains just the commit message itself + (and not an email or the output of `git format-patch`). + CONFIGURATION VARIABLES ----------------------- diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 6a5c00e2c2..eb36837f86 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] [--[no-]allow-unrelated-histories] - [--[no-]rerere-autoupdate] [-m <msg>] [<commit>...] + [--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] [<commit>...] 'git merge' --abort 'git merge' --continue @@ -75,6 +75,14 @@ The 'git fmt-merge-msg' command can be used to give a good default for automated 'git merge' invocations. The automated message can include the branch description. +-F <file>:: +--file=<file>:: + Read the commit message to be used for the merge commit (in + case one is created). ++ +If `--log` is specified, a shortlog of the commits being merged +will be appended to the specified message. + --[no-]rerere-autoupdate:: Allow the rerere mechanism to update the index with the result of auto-conflict resolution if possible. @@ -122,9 +130,9 @@ merge' may need to update. To avoid recording unrelated changes in the merge commit, 'git pull' and 'git merge' will also abort if there are any changes -registered in the index relative to the `HEAD` commit. (One -exception is when the changed index entries are in the state that -would result from the merge already.) +registered in the index relative to the `HEAD` commit. (Special +narrow exceptions to this rule may exist depending on which merge +strategy is in use, but generally, the index must match HEAD.) If all named commits are already ancestors of `HEAD`, 'git merge' will exit early with the message "Already up to date." diff --git a/Documentation/git-multi-pack-index.txt b/Documentation/git-multi-pack-index.txt new file mode 100644 index 0000000000..1f97e79912 --- /dev/null +++ b/Documentation/git-multi-pack-index.txt @@ -0,0 +1,56 @@ +git-multi-pack-index(1) +======================= + +NAME +---- +git-multi-pack-index - Write and verify multi-pack-indexes + + +SYNOPSIS +-------- +[verse] +'git multi-pack-index' [--object-dir=<dir>] <verb> + +DESCRIPTION +----------- +Write or verify a multi-pack-index (MIDX) file. + +OPTIONS +------- + +--object-dir=<dir>:: + Use given directory for the location of Git objects. We check + `<dir>/packs/multi-pack-index` for the current MIDX file, and + `<dir>/packs` for the pack-files to index. + +write:: + When given as the verb, write a new MIDX file to + `<dir>/packs/multi-pack-index`. + + +EXAMPLES +-------- + +* Write a MIDX file for the packfiles in the current .git folder. ++ +----------------------------------------------- +$ git multi-pack-index write +----------------------------------------------- + +* Write a MIDX file for the packfiles in an alternate object store. ++ +----------------------------------------------- +$ git multi-pack-index --object-dir <alt> write +----------------------------------------------- + + +SEE ALSO +-------- +See link:technical/multi-pack-index.html[The Multi-Pack-Index Design +Document] and link:technical/pack-format.html[The Multi-Pack-Index +Format] for more information on the multi-pack-index feature. + + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index e8dec1b3c8..df2b64dbb6 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -199,7 +199,7 @@ OPTIONS .git/NOTES_MERGE_REF symref is updated to the resulting commit. --abort:: - Abort/reset a in-progress 'git notes merge', i.e. a notes merge + Abort/reset an in-progress 'git notes merge', i.e. a notes merge with conflicts. This simply removes all files related to the notes merge. diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt index f0de3b891b..41780a5aa9 100644 --- a/Documentation/git-p4.txt +++ b/Documentation/git-p4.txt @@ -374,6 +374,14 @@ These options can be used to modify 'git p4 submit' behavior. been submitted. Implies --disable-rebase. Can also be set with git-p4.disableP4Sync. Sync with origin/master still goes ahead if possible. +Hook for submit +~~~~~~~~~~~~~~~ +The `p4-pre-submit` hook is executed if it exists and is executable. +The hook takes no parameters and nothing from standard input. Exiting with +non-zero status from this script prevents `git-p4 submit` from launching. + +One usage scenario is to run unit tests in the hook. + Rebase options ~~~~~~~~~~~~~~ These options can be used to modify 'git p4 rebase' behavior. diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index d95b472d16..40c825c381 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -289,6 +289,103 @@ Unexpected missing object will raise an error. --unpack-unreachable:: Keep unreachable objects in loose form. This implies `--revs`. +--delta-islands:: + Restrict delta matches based on "islands". See DELTA ISLANDS + below. + + +DELTA ISLANDS +------------- + +When possible, `pack-objects` tries to reuse existing on-disk deltas to +avoid having to search for new ones on the fly. This is an important +optimization for serving fetches, because it means the server can avoid +inflating most objects at all and just send the bytes directly from +disk. This optimization can't work when an object is stored as a delta +against a base which the receiver does not have (and which we are not +already sending). In that case the server "breaks" the delta and has to +find a new one, which has a high CPU cost. Therefore it's important for +performance that the set of objects in on-disk delta relationships match +what a client would fetch. + +In a normal repository, this tends to work automatically. The objects +are mostly reachable from the branches and tags, and that's what clients +fetch. Any deltas we find on the server are likely to be between objects +the client has or will have. + +But in some repository setups, you may have several related but separate +groups of ref tips, with clients tending to fetch those groups +independently. For example, imagine that you are hosting several "forks" +of a repository in a single shared object store, and letting clients +view them as separate repositories through `GIT_NAMESPACE` or separate +repos using the alternates mechanism. A naive repack may find that the +optimal delta for an object is against a base that is only found in +another fork. But when a client fetches, they will not have the base +object, and we'll have to find a new delta on the fly. + +A similar situation may exist if you have many refs outside of +`refs/heads/` and `refs/tags/` that point to related objects (e.g., +`refs/pull` or `refs/changes` used by some hosting providers). By +default, clients fetch only heads and tags, and deltas against objects +found only in those other groups cannot be sent as-is. + +Delta islands solve this problem by allowing you to group your refs into +distinct "islands". Pack-objects computes which objects are reachable +from which islands, and refuses to make a delta from an object `A` +against a base which is not present in all of `A`'s islands. This +results in slightly larger packs (because we miss some delta +opportunities), but guarantees that a fetch of one island will not have +to recompute deltas on the fly due to crossing island boundaries. + +When repacking with delta islands the delta window tends to get +clogged with candidates that are forbidden by the config. Repacking +with a big --window helps (and doesn't take as long as it otherwise +might because we can reject some object pairs based on islands before +doing any computation on the content). + +Islands are configured via the `pack.island` option, which can be +specified multiple times. Each value is a left-anchored regular +expressions matching refnames. For example: + +------------------------------------------- +[pack] +island = refs/heads/ +island = refs/tags/ +------------------------------------------- + +puts heads and tags into an island (whose name is the empty string; see +below for more on naming). Any refs which do not match those regular +expressions (e.g., `refs/pull/123`) is not in any island. Any object +which is reachable only from `refs/pull/` (but not heads or tags) is +therefore not a candidate to be used as a base for `refs/heads/`. + +Refs are grouped into islands based on their "names", and two regexes +that produce the same name are considered to be in the same +island. The names are computed from the regexes by concatenating any +capture groups from the regex, with a '-' dash in between. (And if +there are no capture groups, then the name is the empty string, as in +the above example.) This allows you to create arbitrary numbers of +islands. Only up to 14 such capture groups are supported though. + +For example, imagine you store the refs for each fork in +`refs/virtual/ID`, where `ID` is a numeric identifier. You might then +configure: + +------------------------------------------- +[pack] +island = refs/virtual/([0-9]+)/heads/ +island = refs/virtual/([0-9]+)/tags/ +island = refs/virtual/([0-9]+)/(pull)/ +------------------------------------------- + +That puts the heads and tags for each fork in their own island (named +"1234" or similar), and the pull refs for each go into their own +"1234-pull". + +Note that we pick a single island for each regex to go into, using "last +one wins" ordering (which allows repo-specific config to take precedence +over user-wide config, and so forth). + SEE ALSO -------- linkgit:git-rev-list[1] diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 55277a9781..a5fc54aeab 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -74,22 +74,57 @@ without any `<refspec>` on the command line. Otherwise, missing `:<dst>` means to update the same ref as the `<src>`. + The object referenced by <src> is used to update the <dst> reference -on the remote side. By default this is only allowed if <dst> is not -a tag (annotated or lightweight), and then only if it can fast-forward -<dst>. By having the optional leading `+`, you can tell Git to update -the <dst> ref even if it is not allowed by default (e.g., it is not a -fast-forward.) This does *not* attempt to merge <src> into <dst>. See -EXAMPLES below for details. -+ -`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`. -+ -Pushing an empty <src> allows you to delete the <dst> ref from -the remote repository. +on the remote side. Whether this is allowed depends on where in +`refs/*` the <dst> reference lives as described in detail below, in +those sections "update" means any modifications except deletes, which +as noted after the next few sections are treated differently. ++ +The `refs/heads/*` namespace will only accept commit objects, and +updates only if they can be fast-forwarded. ++ +The `refs/tags/*` namespace will accept any kind of object (as +commits, trees and blobs can be tagged), and any updates to them will +be rejected. ++ +It's possible to push any type of object to any namespace outside of +`refs/{tags,heads}/*`. In the case of tags and commits, these will be +treated as if they were the commits inside `refs/heads/*` for the +purposes of whether the update is allowed. ++ +I.e. a fast-forward of commits and tags outside `refs/{tags,heads}/*` +is allowed, even in cases where what's being fast-forwarded is not a +commit, but a tag object which happens to point to a new commit which +is a fast-forward of the commit the last tag (or commit) it's +replacing. Replacing a tag with an entirely different tag is also +allowed, if it points to the same commit, as well as pushing a peeled +tag, i.e. pushing the commit that existing tag object points to, or a +new tag object which an existing commit points to. ++ +Tree and blob objects outside of `refs/{tags,heads}/*` will be treated +the same way as if they were inside `refs/tags/*`, any update of them +will be rejected. ++ +All of the rules described above about what's not allowed as an update +can be overridden by adding an the optional leading `+` to a refspec +(or using `--force` command line option). The only exception to this +is that no amount of forcing will make the `refs/heads/*` namespace +accept a non-commit object. Hooks and configuration can also override +or amend these rules, see e.g. `receive.denyNonFastForwards` in +linkgit:git-config[1] and `pre-receive` and `update` in +linkgit:githooks[5]. ++ +Pushing an empty <src> allows you to delete the <dst> ref from the +remote repository. Deletions are always accepted without a leading `+` +in the refspec (or `--force`), except when forbidden by configuration +or hooks. See `receive.denyDeletes` in linkgit:git-config[1] and +`pre-receive` and `update` in linkgit:githooks[5]. + The special refspec `:` (or `+:` to allow non-fast-forward updates) directs Git to push "matching" branches: for every branch that exists on the local side, the remote side is updated if a branch of the same name already exists on the remote side. ++ +`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`. --all:: Push all branches (i.e. refs under `refs/heads/`); cannot be diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt new file mode 100644 index 0000000000..f693930fdb --- /dev/null +++ b/Documentation/git-range-diff.txt @@ -0,0 +1,252 @@ +git-range-diff(1) +================= + +NAME +---- +git-range-diff - Compare two commit ranges (e.g. two versions of a branch) + +SYNOPSIS +-------- +[verse] +'git range-diff' [--color=[<when>]] [--no-color] [<diff-options>] + [--no-dual-color] [--creation-factor=<factor>] + ( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> ) + +DESCRIPTION +----------- + +This command shows the differences between two versions of a patch +series, or more generally, two commit ranges (ignoring merge commits). + +To that end, it first finds pairs of commits from both commit ranges +that correspond with each other. Two commits are said to correspond when +the diff between their patches (i.e. the author information, the commit +message and the commit diff) is reasonably small compared to the +patches' size. See ``Algorithm`` below for details. + +Finally, the list of matching commits is shown in the order of the +second commit range, with unmatched commits being inserted just after +all of their ancestors have been shown. + + +OPTIONS +------- +--no-dual-color:: + When the commit diffs differ, `git range-diff` recreates the + original diffs' coloring, and adds outer -/+ diff markers with + the *background* being red/green to make it easier to see e.g. + when there was a change in what exact lines were added. ++ +Additionally, the commit diff lines that are only present in the first commit +range are shown "dimmed" (this can be overridden using the `color.diff.<slot>` +config setting where `<slot>` is one of `contextDimmed`, `oldDimmed` and +`newDimmed`), and the commit diff lines that are only present in the second +commit range are shown in bold (which can be overridden using the config +settings `color.diff.<slot>` with `<slot>` being one of `contextBold`, +`oldBold` or `newBold`). ++ +This is known to `range-diff` as "dual coloring". Use `--no-dual-color` +to revert to color all lines according to the outer diff markers +(and completely ignore the inner diff when it comes to color). + +--creation-factor=<percent>:: + Set the creation/deletion cost fudge factor to `<percent>`. + Defaults to 60. Try a larger value if `git range-diff` erroneously + considers a large change a total rewrite (deletion of one commit + and addition of another), and a smaller one in the reverse case. + See the ``Algorithm`` section below for an explanation why this is + needed. + +<range1> <range2>:: + Compare the commits specified by the two ranges, where + `<range1>` is considered an older version of `<range2>`. + +<rev1>...<rev2>:: + Equivalent to passing `<rev2>..<rev1>` and `<rev1>..<rev2>`. + +<base> <rev1> <rev2>:: + Equivalent to passing `<base>..<rev1>` and `<base>..<rev2>`. + Note that `<base>` does not need to be the exact branch point + of the branches. Example: after rebasing a branch `my-topic`, + `git range-diff my-topic@{u} my-topic@{1} my-topic` would + show the differences introduced by the rebase. + +`git range-diff` also accepts the regular diff options (see +linkgit:git-diff[1]), most notably the `--color=[<when>]` and +`--no-color` options. These options are used when generating the "diff +between patches", i.e. to compare the author, commit message and diff of +corresponding old/new commits. There is currently no means to tweak the +diff options passed to `git log` when generating those patches. + + +CONFIGURATION +------------- +This command uses the `diff.color.*` and `pager.range-diff` settings +(the latter is on by default). +See linkgit:git-config[1]. + + +EXAMPLES +-------- + +When a rebase required merge conflicts to be resolved, compare the changes +introduced by the rebase directly afterwards using: + +------------ +$ git range-diff @{u} @{1} @ +------------ + + +A typical output of `git range-diff` would look like this: + +------------ +-: ------- > 1: 0ddba11 Prepare for the inevitable! +1: c0debee = 2: cab005e Add a helpful message at the start +2: f00dbal ! 3: decafe1 Describe a bug + @@ -1,3 +1,3 @@ + Author: A U Thor <author@example.com> + + -TODO: Describe a bug + +Describe a bug + @@ -324,5 +324,6 + This is expected. + + -+What is unexpected is that it will also crash. + ++Unexpectedly, it also crashes. This is a bug, and the jury is + ++still out there how to fix it best. See ticket #314 for details. + + Contact +3: bedead < -: ------- TO-UNDO +------------ + +In this example, there are 3 old and 3 new commits, where the developer +removed the 3rd, added a new one before the first two, and modified the +commit message of the 2nd commit as well its diff. + +When the output goes to a terminal, it is color-coded by default, just +like regular `git diff`'s output. In addition, the first line (adding a +commit) is green, the last line (deleting a commit) is red, the second +line (with a perfect match) is yellow like the commit header of `git +show`'s output, and the third line colors the old commit red, the new +one green and the rest like `git show`'s commit header. + +A naive color-coded diff of diffs is actually a bit hard to read, +though, as it colors the entire lines red or green. The line that added +"What is unexpected" in the old commit, for example, is completely red, +even if the intent of the old commit was to add something. + +To help with that, `range` uses the `--dual-color` mode by default. In +this mode, the diff of diffs will retain the original diff colors, and +prefix the lines with -/+ markers that have their *background* red or +green, to make it more obvious that they describe how the diff itself +changed. + + +Algorithm +--------- + +The general idea is this: we generate a cost matrix between the commits +in both commit ranges, then solve the least-cost assignment. + +The cost matrix is populated thusly: for each pair of commits, both +diffs are generated and the "diff of diffs" is generated, with 3 context +lines, then the number of lines in that diff is used as cost. + +To avoid false positives (e.g. when a patch has been removed, and an +unrelated patch has been added between two iterations of the same patch +series), the cost matrix is extended to allow for that, by adding +fixed-cost entries for wholesale deletes/adds. + +Example: Let commits `1--2` be the first iteration of a patch series and +`A--C` the second iteration. Let's assume that `A` is a cherry-pick of +`2,` and `C` is a cherry-pick of `1` but with a small modification (say, +a fixed typo). Visualize the commits as a bipartite graph: + +------------ + 1 A + + 2 B + + C +------------ + +We are looking for a "best" explanation of the new series in terms of +the old one. We can represent an "explanation" as an edge in the graph: + + +------------ + 1 A + / + 2 --------' B + + C +------------ + +This explanation comes for "free" because there was no change. Similarly +`C` could be explained using `1`, but that comes at some cost c>0 +because of the modification: + +------------ + 1 ----. A + | / + 2 ----+---' B + | + `----- C + c>0 +------------ + +In mathematical terms, what we are looking for is some sort of a minimum +cost bipartite matching; `1` is matched to `C` at some cost, etc. The +underlying graph is in fact a complete bipartite graph; the cost we +associate with every edge is the size of the diff between the two +commits' patches. To explain also new commits, we introduce dummy nodes +on both sides: + +------------ + 1 ----. A + | / + 2 ----+---' B + | + o `----- C + c>0 + o o + + o o +------------ + +The cost of an edge `o--C` is the size of `C`'s diff, modified by a +fudge factor that should be smaller than 100%. The cost of an edge +`o--o` is free. The fudge factor is necessary because even if `1` and +`C` have nothing in common, they may still share a few empty lines and +such, possibly making the assignment `1--C`, `o--o` slightly cheaper +than `1--o`, `o--C` even if `1` and `C` have nothing in common. With the +fudge factor we require a much larger common part to consider patches as +corresponding. + +The overall time needed to compute this algorithm is the time needed to +compute n+m commit diffs and then n*m diffs of patches, plus the time +needed to compute the least-cost assigment between n and m diffs. Git +uses an implementation of the Jonker-Volgenant algorithm to solve the +assignment problem, which has cubic runtime complexity. The matching +found in this case will look like this: + +------------ + 1 ----. A + | / + 2 ----+---' B + .--+-----' + o -' `----- C + c>0 + o ---------- o + + o ---------- o +------------ + + +SEE ALSO +-------- +linkgit:git-log[1] + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 0e20a66e73..1fbc6ebcde 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -243,11 +243,15 @@ leave out at most one of A and B, in which case it defaults to HEAD. --keep-empty:: Keep the commits that do not change anything from its parents in the result. ++ +See also INCOMPATIBLE OPTIONS below. --allow-empty-message:: By default, rebasing commits with an empty message will fail. This option overrides that behavior, allowing commits with empty messages to be rebased. ++ +See also INCOMPATIBLE OPTIONS below. --skip:: Restart the rebasing process by skipping the current patch. @@ -271,6 +275,8 @@ branch on top of the <upstream> branch. Because of this, when a merge conflict happens, the side reported as 'ours' is the so-far rebased series, starting with <upstream>, and 'theirs' is the working branch. In other words, the sides are swapped. ++ +See also INCOMPATIBLE OPTIONS below. -s <strategy>:: --strategy=<strategy>:: @@ -280,8 +286,10 @@ other words, the sides are swapped. + Because 'git rebase' replays each commit from the working branch on top of the <upstream> branch using the given strategy, using -the 'ours' strategy simply discards all patches from the <branch>, +the 'ours' strategy simply empties all patches from the <branch>, which makes little sense. ++ +See also INCOMPATIBLE OPTIONS below. -X <strategy-option>:: --strategy-option=<strategy-option>:: @@ -289,6 +297,8 @@ which makes little sense. This implies `--merge` and, if no strategy has been specified, `-s recursive`. Note the reversal of 'ours' and 'theirs' as noted above for the `-m` option. ++ +See also INCOMPATIBLE OPTIONS below. -S[<keyid>]:: --gpg-sign[=<keyid>]:: @@ -324,17 +334,21 @@ which makes little sense. and after each change. When fewer lines of surrounding context exist they all must match. By default no context is ever ignored. ++ +See also INCOMPATIBLE OPTIONS below. --f:: +--no-ff:: --force-rebase:: - Force a rebase even if the current branch is up to date and - the command without `--force` would return without doing anything. +-f:: + Individually replay all rebased commits instead of fast-forwarding + over the unchanged ones. This ensures that the entire history of + the rebased branch is composed of new commits. + -You may find this (or --no-ff with an interactive rebase) helpful after -reverting a topic branch merge, as this option recreates the topic branch with -fresh commits so it can be remerged successfully without needing to "revert -the reversion" (see the -link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details). +You may find this helpful after reverting a topic branch merge, as this option +recreates the topic branch with fresh commits so it can be remerged +successfully without needing to "revert the reversion" (see the +link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for +details). --fork-point:: --no-fork-point:: @@ -355,19 +369,22 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`. --whitespace=<option>:: These flag are passed to the 'git apply' program (see linkgit:git-apply[1]) that applies the patch. - Incompatible with the --interactive option. ++ +See also INCOMPATIBLE OPTIONS below. --committer-date-is-author-date:: --ignore-date:: These flags are passed to 'git am' to easily change the dates of the rebased commits (see linkgit:git-am[1]). - Incompatible with the --interactive option. ++ +See also INCOMPATIBLE OPTIONS below. --signoff:: Add a Signed-off-by: trailer to all the rebased commits. Note that if `--interactive` is given then only commits marked to be - picked, edited or reworded will have the trailer added. Incompatible - with the `--preserve-merges` option. + picked, edited or reworded will have the trailer added. ++ +See also INCOMPATIBLE OPTIONS below. -i:: --interactive:: @@ -378,6 +395,8 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`. The commit list format can be changed by setting the configuration option rebase.instructionFormat. A customized instruction format will automatically have the long commit hash prepended to the format. ++ +See also INCOMPATIBLE OPTIONS below. -r:: --rebase-merges[=(rebase-cousins|no-rebase-cousins)]:: @@ -404,7 +423,7 @@ It is currently only possible to recreate the merge commits using the `recursive` merge strategy; Different merge strategies can be used only via explicit `exec git merge -s <strategy> [...]` commands. + -See also REBASING MERGES below. +See also REBASING MERGES and INCOMPATIBLE OPTIONS below. -p:: --preserve-merges:: @@ -415,6 +434,8 @@ See also REBASING MERGES below. This uses the `--interactive` machinery internally, but combining it with the `--interactive` option explicitly is generally not a good idea unless you know what you are doing (see BUGS below). ++ +See also INCOMPATIBLE OPTIONS below. -x <cmd>:: --exec <cmd>:: @@ -437,6 +458,8 @@ squash/fixup series. + This uses the `--interactive` machinery internally, but it can be run without an explicit `--interactive`. ++ +See also INCOMPATIBLE OPTIONS below. --root:: Rebase all commits reachable from <branch>, instead of @@ -447,6 +470,8 @@ without an explicit `--interactive`. When used together with both --onto and --preserve-merges, 'all' root commits will be rewritten to have <newbase> as parent instead. ++ +See also INCOMPATIBLE OPTIONS below. --autosquash:: --no-autosquash:: @@ -461,11 +486,11 @@ without an explicit `--interactive`. too. The recommended way to create fixup/squash commits is by using the `--fixup`/`--squash` options of linkgit:git-commit[1]. + -This option is only valid when the `--interactive` option is used. -+ If the `--autosquash` option is enabled by default using the configuration variable `rebase.autoSquash`, this option can be used to override and disable this setting. ++ +See also INCOMPATIBLE OPTIONS below. --autostash:: --no-autostash:: @@ -475,17 +500,73 @@ used to override and disable this setting. with care: the final stash application after a successful rebase might result in non-trivial conflicts. ---no-ff:: - With --interactive, cherry-pick all rebased commits instead of - fast-forwarding over the unchanged ones. This ensures that the - entire history of the rebased branch is composed of new commits. -+ -Without --interactive, this is a synonym for --force-rebase. -+ -You may find this helpful after reverting a topic branch merge, as this option -recreates the topic branch with fresh commits so it can be remerged -successfully without needing to "revert the reversion" (see the -link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details). +INCOMPATIBLE OPTIONS +-------------------- + +git-rebase has many flags that are incompatible with each other, +predominantly due to the fact that it has three different underlying +implementations: + + * one based on linkgit:git-am[1] (the default) + * one based on git-merge-recursive (merge backend) + * one based on linkgit:git-cherry-pick[1] (interactive backend) + +Flags only understood by the am backend: + + * --committer-date-is-author-date + * --ignore-date + * --whitespace + * --ignore-whitespace + * -C + +Flags understood by both merge and interactive backends: + + * --merge + * --strategy + * --strategy-option + * --allow-empty-message + +Flags only understood by the interactive backend: + + * --[no-]autosquash + * --rebase-merges + * --preserve-merges + * --interactive + * --exec + * --keep-empty + * --autosquash + * --edit-todo + * --root when used in combination with --onto + +Other incompatible flag pairs: + + * --preserve-merges and --interactive + * --preserve-merges and --signoff + * --preserve-merges and --rebase-merges + * --rebase-merges and --strategy + * --rebase-merges and --strategy-option + +BEHAVIORAL DIFFERENCES +----------------------- + + * empty commits: + + am-based rebase will drop any "empty" commits, whether the + commit started empty (had no changes relative to its parent to + start with) or ended empty (all changes were already applied + upstream in other commits). + + merge-based rebase does the same. + + interactive-based rebase will by default drop commits that + started empty and halt if it hits a commit that ended up empty. + The `--keep-empty` option exists for interactive rebases to allow + it to keep commits that started empty. + + * directory rename detection: + + merge-based and interactive-based rebases work fine with + directory rename detection. am-based rebases sometimes do not. include::merge-strategies.txt[] @@ -804,7 +885,7 @@ The ripple effect of a "hard case" recovery is especially bad: case" recovery too! REBASING MERGES ------------------ +--------------- The interactive rebase command was originally designed to handle individual patch series. As such, it makes sense to exclude merge @@ -879,8 +960,8 @@ rescheduled immediately, with a helpful message how to edit the todo list (this typically happens when a `reset` command was inserted into the todo list manually and contains a typo). -The `merge` command will merge the specified revision into whatever is -HEAD at that time. With `-C <original-commit>`, the commit message of +The `merge` command will merge the specified revision(s) into whatever +is HEAD at that time. With `-C <original-commit>`, the commit message of the specified merge commit will be used. When the `-C` is changed to a lower-case `-c`, the message will be opened in an editor after a successful merge so that the user can edit the message. @@ -889,7 +970,8 @@ If a `merge` command fails for any reason other than merge conflicts (i.e. when the merge operation did not even start), it is rescheduled immediately. At this time, the `merge` command will *always* use the `recursive` -merge strategy, with no way to choose a different one. To work around +merge strategy for regular merges, and `octopus` for octopus merges, +strategy, with no way to choose a different one. To work around this, an `exec` command can be used to call `git merge` explicitly, using the fact that the labels are worktree-local refs (the ref `refs/rewritten/onto` would correspond to the label `onto`, for example). diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index d90e7907f4..aa0cc8bd44 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -40,6 +40,11 @@ OPTIONS Note that users fetching over dumb protocols will have to fetch the whole new pack in order to get any contained object, no matter how many other objects in that pack they already have locally. ++ +Promisor packfiles are repacked separately: if there are packfiles that +have an associated ".promisor" file, these packfiles will be repacked +into another separate pack, and an empty ".promisor" file corresponding +to the new separate pack will be written. -A:: Same as `-a`, unless `-d` is used. Then any unreachable @@ -155,6 +160,11 @@ depth is 4095. being removed. In addition, any unreachable loose objects will be packed (and their loose counterparts removed). +-i:: +--delta-islands:: + Pass the `--delta-islands` option to `git-pack-objects`, see + linkgit:git-pack-objects[1]. + Configuration ------------- diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt index 031f31fa47..df310d2a58 100644 --- a/Documentation/git-rerere.txt +++ b/Documentation/git-rerere.txt @@ -211,6 +211,12 @@ would conflict the same way as the test merge you resolved earlier. 'git rerere' will be run by 'git rebase' to help you resolve this conflict. +[NOTE] 'git rerere' relies on the conflict markers in the file to +detect the conflict. If the file already contains lines that look the +same as lines with conflict markers, 'git rerere' may fail to record a +conflict resolution. To work around this, the `conflict-marker-size` +setting in linkgit:gitattributes[5] can be used. + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 4f3efde80c..465a4ecbed 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -137,15 +137,17 @@ Note that no attempts whatsoever are made to validate the encoding. Specify encoding of compose message. Default is the value of the 'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed. ---transfer-encoding=(7bit|8bit|quoted-printable|base64):: +--transfer-encoding=(7bit|8bit|quoted-printable|base64|auto):: Specify the transfer encoding to be used to send the message over SMTP. 7bit will fail upon encountering a non-ASCII message. quoted-printable can be useful when the repository contains files that contain carriage returns, but makes the raw patch email file (as saved from a MUA) much harder to inspect manually. base64 is even more fool proof, but also - even more opaque. Default is the value of the `sendemail.transferEncoding` - configuration value; if that is unspecified, git will use 8bit and not - add a Content-Transfer-Encoding header. + even more opaque. auto will use 8bit when possible, and quoted-printable + otherwise. ++ +Default is the value of the `sendemail.transferEncoding` configuration +value; if that is unspecified, default to `auto`. --xmailer:: --no-xmailer:: @@ -398,8 +400,11 @@ have been specified, in which case default to 'compose'. + -- * Invoke the sendemail-validate hook if present (see linkgit:githooks[5]). - * Warn of patches that contain lines longer than 998 characters; this - is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt. + * Warn of patches that contain lines longer than + 998 characters unless a suitable transfer encoding + ('auto', 'base64', or 'quoted-printable') is used; + this is due to SMTP limits as described by + http://www.ietf.org/rfc/rfc5322.txt. -- + Default is the value of `sendemail.validate`; if this is not set, diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index c4467ffb98..d9f422d560 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -106,7 +106,7 @@ 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 + --untracked-files=all is specified, in which case individual files in ignored directories are displayed. - 'no' - Show no ignored files. diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 7ea24fc942..b99029520d 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -452,7 +452,7 @@ Any other arguments are passed directly to 'git log' 'commit-diff':: Commits the diff of two tree-ish arguments from the - command-line. This command does not rely on being inside an `git svn + command-line. This command does not rely on being inside a `git svn init`-ed repository. This command takes three arguments, (a) the original tree to diff against, (b) the new tree result, (c) the URL of the target Subversion repository. The final argument diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 87c4288ffc..92f9c12b87 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -115,7 +115,7 @@ options for details. variable if it exists, or lexicographic order otherwise. See linkgit:git-config[1]. ---color[=<when>]: +--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). diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index 4e8e762e68..1c4d146a41 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -245,10 +245,10 @@ USING --CACHEINFO OR --INFO-ONLY current working directory. This is useful for minimum-checkout merging. -To pretend you have a file with mode and sha1 at path, say: +To pretend you have a file at path with mode and sha1, say: ---------------- -$ git update-index --cacheinfo <mode>,<sha1>,<path> +$ git update-index --add --cacheinfo <mode>,<sha1>,<path> ---------------- `--info-only` is used to register files without placing them in the object @@ -268,23 +268,20 @@ USING --INDEX-INFO multiple entry definitions from the standard input, and designed specifically for scripts. It can take inputs of three formats: - . mode SP sha1 TAB path -+ -The first format is what "git-apply --index-info" -reports, and used to reconstruct a partial tree -that is used for phony merge base tree when falling -back on 3-way merge. - . mode SP type SP sha1 TAB path + -The second format is to stuff 'git ls-tree' output -into the index file. +This format is to stuff `git ls-tree` output into the index. . mode SP sha1 SP stage TAB path + This format is to put higher order stages into the index file and matches 'git ls-files --stage' output. + . mode SP sha1 TAB path ++ +This format is no longer produced by any Git command, but is +and will continue to be supported by `update-index --index-info`. + To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the third format. diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index afc6576a14..e2ee9fc21b 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -60,6 +60,15 @@ with a matching name, treat as equivalent to: $ git worktree add --track -b <branch> <path> <remote>/<branch> ------------ + +If the branch exists in multiple remotes and one of them is named by +the `checkout.defaultRemote` configuration variable, we'll use that +one for the purposes of disambiguation, even if the `<branch>` isn't +unique across all remotes. Set it to +e.g. `checkout.defaultRemote=origin` to always checkout remote +branches from there if `<branch>` is ambiguous but exists on the +'origin' remote. See also `checkout.defaultRemote` in +linkgit:git-config[1]. ++ If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used, then, as a convenience, the new worktree is associated with a branch (call it `<branch>`) named after `$(basename <path>)`. If `<branch>` @@ -111,8 +120,16 @@ OPTIONS --force:: By default, `add` refuses to create a new working tree when `<commit-ish>` is a branch name and is already checked out by - another working tree and `remove` refuses to remove an unclean - working tree. This option overrides these safeguards. + another working tree, or if `<path>` is already assigned to some + working tree but is missing (for instance, if `<path>` was deleted + manually). This option overrides these safeguards. To add a missing but + locked working tree path, specify `--force` twice. ++ +`move` refuses to move a locked working tree unless `--force` is specified +twice. ++ +`remove` refuses to remove an unclean working tree unless `--force` is used. +To remove a locked working tree, specify `--force` twice. -b <new-branch>:: -B <new-branch>:: @@ -164,6 +181,10 @@ This can also be set up as the default behaviour by using the This format will remain stable across Git versions and regardless of user configuration. See below for details. +-q:: +--quiet:: + With 'add', suppress feedback messages. + -v:: --verbose:: With `prune`, report all removals. diff --git a/Documentation/git.txt b/Documentation/git.txt index dba7f0c18e..74a9d7edb4 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -599,8 +599,8 @@ trace messages into this file descriptor. + Alternatively, if the variable is set to an absolute path (starting with a '/' character), Git will interpret this -as a file path and will try to write the trace messages -into it. +as a file path and will try to append the trace messages +to it. + Unsetting the variable, or setting it to empty, "0" or "false" (case insensitive) disables trace messages. diff --git a/Documentation/giteveryday.txt b/Documentation/giteveryday.txt index 10c8ff93c0..9f2528fc8c 100644 --- a/Documentation/giteveryday.txt +++ b/Documentation/giteveryday.txt @@ -244,7 +244,7 @@ commands in addition to the ones needed by participants. This section can also be used by those who respond to `git request-pull` or pull-request on GitHub (www.github.com) to -integrate the work of others into their history. An sub-area +integrate the work of others into their history. A sub-area lieutenant for a repository will act both as a participant and as an integrator. diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index e3c283a174..959044347e 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -485,6 +485,13 @@ The exit status determines whether git will use the data from the hook to limit its search. On error, it will fall back to verifying all files and folders. +p4-pre-submit +~~~~~~~~~~~~~ + +This hook is invoked by `git-p4 submit`. It takes no parameters and nothing +from standard input. Exiting with non-zero status from this script prevent +`git-p4 submit` from launching. Run `git-p4 submit --help` for details. + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index ff5d7f9ed6..d107daaffd 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -7,7 +7,7 @@ gitignore - Specifies intentionally untracked files to ignore SYNOPSIS -------- -$HOME/.config/git/ignore, $GIT_DIR/info/exclude, .gitignore +$XDG_CONFIG_HOME/git/ignore, $GIT_DIR/info/exclude, .gitignore DESCRIPTION ----------- diff --git a/Documentation/gitrevisions.txt b/Documentation/gitrevisions.txt index 1f6cceaefb..d407b7dee1 100644 --- a/Documentation/gitrevisions.txt +++ b/Documentation/gitrevisions.txt @@ -19,9 +19,10 @@ walk the revision graph (such as linkgit:git-log[1]), all commits which are reachable from that commit. For commands that walk the revision graph one can also specify a range of revisions explicitly. -In addition, some Git commands (such as linkgit:git-show[1]) also take -revision parameters which denote other objects than commits, e.g. blobs -("files") or trees ("directories of files"). +In addition, some Git commands (such as linkgit:git-show[1] and +linkgit:git-push[1]) can also take revision parameters which denote +other objects than commits, e.g. blobs ("files") or trees +("directories of files"). include::revisions.txt[] diff --git a/Documentation/gitsubmodules.txt b/Documentation/gitsubmodules.txt index 3b9faabdbb..504c5f1a88 100644 --- a/Documentation/gitsubmodules.txt +++ b/Documentation/gitsubmodules.txt @@ -194,7 +194,7 @@ In the above config only the submodule 'bar' and 'baz' are active, Note that (c) is a historical artefact and will be ignored if the (a) and (b) specify that the submodule is not active. In other words, -if we have an `submodule.<name>.active` set to `false` or if the +if we have a `submodule.<name>.active` set to `false` or if the submodule's path is excluded in the pathspec in `submodule.active`, the url doesn't matter whether it is present or not. This is illustrated in the example that follows. diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 6c2d23dc48..0d2aa48c63 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -334,7 +334,7 @@ The optional colon that terminates the "magic signature" can be omitted if the pattern begins with a character that does not belong to "magic signature" symbol set and is not a colon. + -In the long form, the leading colon `:` is followed by a open +In the long form, the leading colon `:` is followed by an open parenthesis `(`, a comma-separated list of zero or more "magic words", and a close parentheses `)`, and the remainder is the pattern to match against the path. diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index c579793af5..7d3a60f5b9 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -33,11 +33,40 @@ name. it requests fetching everything up to the given tag. + The remote ref that matches <src> -is fetched, and if <dst> is not empty string, the local -ref that matches it is fast-forwarded using <src>. -If the optional plus `+` is used, the local ref -is updated even if it does not result in a fast-forward -update. +is fetched, and if <dst> is not an empty string, an attempt +is made to update the local ref that matches it. ++ +Whether that update is allowed without `--force` depends on the ref +namespace it's being fetched to, the type of object being fetched, and +whether the update is considered to be a fast-forward. Generally, the +same rules apply for fetching as when pushing, see the `<refspec>...` +section of linkgit:git-push[1] for what those are. Exceptions to those +rules particular to 'git fetch' are noted below. ++ +Until Git version 2.20, and unlike when pushing with +linkgit:git-push[1], any updates to `refs/tags/*` would be accepted +without `+` in the refspec (or `--force`). When fetching, we promiscuously +considered all tag updates from a remote to be forced fetches. Since +Git version 2.20, fetching to update `refs/tags/*` works the same way +as when pushing. I.e. any updates will be rejected without `+` in the +refspec (or `--force`). ++ +Unlike when pushing with linkgit:git-push[1], any updates outside of +`refs/{tags,heads}/*` will be accepted without `+` in the refspec (or +`--force`), whether that's swapping e.g. a tree object for a blob, or +a commit for another commit that's doesn't have the previous commit as +an ancestor etc. ++ +Unlike when pushing with linkgit:git-push[1], there is no +configuration which'll amend these rules, and nothing like a +`pre-fetch` hook analogous to the `pre-receive` hook. ++ +As with pushing with linkgit:git-push[1], all of the rules described +above about what's not allowed as an update can be overridden by +adding an the optional leading `+` to a refspec (or using `--force` +command line option). The only exception to this is that no amount of +forcing will make the `refs/heads/*` namespace accept a non-commit +object. + [NOTE] When the remote branch you want to fetch is known to diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index 7d1bd44094..72daa20e76 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -184,7 +184,8 @@ existing tag object. A colon, followed by a slash, followed by a text, names a commit whose commit message matches the specified regular expression. This name returns the youngest matching commit which is - reachable from any ref. The regular expression can match any part of the + reachable from any ref, including HEAD. + The regular expression can match any part of the commit message. To match messages starting with a string, one can use e.g. ':/^foo'. The special sequence ':/!' is reserved for modifiers to what is matched. ':/!-foo' performs a negative match, while ':/!!foo' matches a diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt index 4f44ca24f6..5abb8e8b1f 100644 --- a/Documentation/technical/api-directory-listing.txt +++ b/Documentation/technical/api-directory-listing.txt @@ -54,7 +54,7 @@ The notable options are: this case, the contents are returned as individual entries. + If this is set, files and directories that explicitly match an ignore -pattern are reported. Implicity ignored directories (directories that +pattern are reported. Implicitly 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. diff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt index e7cbb7c13a..45f0df600f 100644 --- a/Documentation/technical/api-gitattributes.txt +++ b/Documentation/technical/api-gitattributes.txt @@ -146,7 +146,7 @@ To get the values of all attributes associated with a file: * Iterate over the `attr_check.items[]` array to examine the attribute names and values. The name of the attribute - described by a `attr_check.items[]` object can be retrieved via + described by an `attr_check.items[]` object can be retrieved via `git_attr_name(check->items[i].attr)`. (Please note that no items will be returned for unset attributes, so `ATTR_UNSET()` will return false for all returned `attr_check.items[]` objects.) diff --git a/Documentation/technical/commit-graph-format.txt b/Documentation/technical/commit-graph-format.txt index ad6af8105c..cc0474ba3e 100644 --- a/Documentation/technical/commit-graph-format.txt +++ b/Documentation/technical/commit-graph-format.txt @@ -18,9 +18,9 @@ metadata, including: the graph file. These positional references are stored as unsigned 32-bit integers -corresponding to the array position withing the list of commit OIDs. We -use the most-significant bit for special purposes, so we can store at most -(1 << 31) - 1 (around 2 billion) commits. +corresponding to the array position within the list of commit OIDs. Due +to some special constants we use to track parents, we can store at most +(1 << 30) + (1 << 29) + (1 << 28) - 1 (around 1.8 billion) commits. == Commit graph files have the following format: @@ -70,10 +70,10 @@ CHUNK DATA: OID Lookup (ID: {'O', 'I', 'D', 'L'}) (N * H bytes) The OIDs for all commits in the graph, sorted in ascending order. - Commit Data (ID: {'C', 'G', 'E', 'T' }) (N * (H + 16) bytes) + Commit Data (ID: {'C', 'D', 'A', 'T' }) (N * (H + 16) bytes) * The first H bytes are for the OID of the root tree. * The next 8 bytes are for the positions of the first two parents - of the ith commit. Stores value 0xffffffff if no parent in that + of the ith commit. Stores value 0x7000000 if no parent in that position. If there are more than two parents, the second value has its most-significant bit on and the other bits store an array position into the Large Edge List chunk. diff --git a/Documentation/technical/directory-rename-detection.txt b/Documentation/technical/directory-rename-detection.txt new file mode 100644 index 0000000000..1c0086e287 --- /dev/null +++ b/Documentation/technical/directory-rename-detection.txt @@ -0,0 +1,115 @@ +Directory rename detection +========================== + +Rename detection logic in diffcore-rename that checks for renames of +individual files is aggregated and analyzed in merge-recursive for cases +where combinations of renames indicate that a full directory has been +renamed. + +Scope of abilities +------------------ + +It is perhaps easiest to start with an example: + + * When all of x/a, x/b and x/c have moved to z/a, z/b and z/c, it is + likely that x/d added in the meantime would also want to move to z/d by + taking the hint that the entire directory 'x' moved to 'z'. + +More interesting possibilities exist, though, such as: + + * one side of history renames x -> z, and the other renames some file to + x/e, causing the need for the merge to do a transitive rename. + + * one side of history renames x -> z, but also renames all files within + x. For example, x/a -> z/alpha, x/b -> z/bravo, etc. + + * both 'x' and 'y' being merged into a single directory 'z', with a + directory rename being detected for both x->z and y->z. + + * not all files in a directory being renamed to the same location; + i.e. perhaps most the files in 'x' are now found under 'z', but a few + are found under 'w'. + + * a directory being renamed, which also contained a subdirectory that was + renamed to some entirely different location. (And perhaps the inner + directory itself contained inner directories that were renamed to yet + other locations). + + * combinations of the above; see t/t6043-merge-rename-directories.sh for + various interesting cases. + +Limitations -- applicability of directory renames +------------------------------------------------- + +In order to prevent edge and corner cases resulting in either conflicts +that cannot be represented in the index or which might be too complex for +users to try to understand and resolve, a couple basic rules limit when +directory rename detection applies: + + 1) If a given directory still exists on both sides of a merge, we do + not consider it to have been renamed. + + 2) If a subset of to-be-renamed files have a file or directory in the + way (or would be in the way of each other), "turn off" the directory + rename for those specific sub-paths and report the conflict to the + user. + + 3) If the other side of history did a directory rename to a path that + your side of history renamed away, then ignore that particular + rename from the other side of history for any implicit directory + renames (but warn the user). + +Limitations -- detailed rules and testcases +------------------------------------------- + +t/t6043-merge-rename-directories.sh contains extensive tests and commentary +which generate and explore the rules listed above. It also lists a few +additional rules: + + a) If renames split a directory into two or more others, the directory + with the most renames, "wins". + + b) Avoid directory-rename-detection for a path, if that path is the + source of a rename on either side of a merge. + + c) Only apply implicit directory renames to directories if the other side + of history is the one doing the renaming. + +Limitations -- support in different commands +-------------------------------------------- + +Directory rename detection is supported by 'merge' and 'cherry-pick'. +Other git commands which users might be surprised to see limited or no +directory rename detection support in: + + * diff + + Folks have requested in the past that `git diff` detect directory + renames and somehow simplify its output. It is not clear whether this + would be desirable or how the output should be simplified, so this was + simply not implemented. Further, to implement this, directory rename + detection logic would need to move from merge-recursive to + diffcore-rename. + + * am + + git-am tries to avoid a full three way merge, instead calling + git-apply. That prevents us from detecting renames at all, which may + defeat the directory rename detection. There is a fallback, though; if + the initial git-apply fails and the user has specified the -3 option, + git-am will fall back to a three way merge. However, git-am lacks the + necessary information to do a "real" three way merge. Instead, it has + to use build_fake_ancestor() to get a merge base that is missing files + whose rename may have been important to detect for directory rename + detection to function. + + * rebase + + Since am-based rebases work by first generating a bunch of patches + (which no longer record what the original commits were and thus don't + have the necessary info from which we can find a real merge-base), and + then calling git-am, this implies that am-based rebases will not always + successfully detect directory renames either (see the 'am' section + above). merged-based rebases (rebase -m) and cherry-pick-based rebases + (rebase -i) are not affected by this shortcoming, and fully support + directory rename detection. diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt index 4ab6cd1012..bc2ace2a6e 100644 --- a/Documentation/technical/hash-function-transition.txt +++ b/Documentation/technical/hash-function-transition.txt @@ -59,14 +59,11 @@ 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. +1. The transition to SHA-256 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 + b. A SHA-256 repository can communicate with SHA-1 Git servers (push/fetch). - c. Users can use SHA-1 and NewHash identifiers for objects + c. Users can use SHA-1 and SHA-256 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. @@ -79,7 +76,7 @@ Where NewHash is a strong 256-bit hash function to replace SHA-1 (see Non-Goals --------- -1. Add NewHash support to Git protocol. This is valuable and the +1. Add SHA-256 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. @@ -87,26 +84,26 @@ Non-Goals 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 +5. Shallow clones and fetches into a SHA-256 repository. (This will + change when we add SHA-256 support to Git protocol.) +6. Skip fetching some submodules of a project into a SHA-256 + repository. (This also depends on SHA-256 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. +extension enabled use SHA-256 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. +SHA-256 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 +Alongside the packfile, a SHA-256 repository stores a bidirectional +mapping between SHA-256 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 +mapping to allow naming objects using either their SHA-1 and SHA-256 names interchangeably. "git cat-file" and "git hash-object" gain options to display an object @@ -116,7 +113,7 @@ 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 +SHA-256 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. @@ -125,19 +122,19 @@ Detailed Design --------------- Repository format extension ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A NewHash repository uses repository format version `1` (see +A SHA-256 repository uses repository format version `1` (see Documentation/technical/repository-version.txt) with extensions `objectFormat` and `compatObjectFormat`: [core] repositoryFormatVersion = 1 [extensions] - objectFormat = newhash + objectFormat = sha256 compatObjectFormat = sha1 The combination of setting `core.repositoryFormatVersion=1` and populating `extensions.*` ensures that all versions of Git later than -`v0.99.9l` will die instead of trying to operate on the NewHash +`v0.99.9l` will die instead of trying to operate on the SHA-256 repository, instead producing an error message. # Between v0.99.9l and v2.7.0 @@ -155,36 +152,36 @@ 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 +hexadecimal digit sha256-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. +The sha256-name of an object is the SHA-256 of the concatenation of its +type, length, a nul byte, and the object's sha256-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 +by sha1 and sha256 differ because an object named by sha256-name refers to +other objects by their sha256-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 +The sha256-content of an object is the same as its sha1-content, except +that objects referenced by the object are named using their sha256-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. +other object, its sha1-content and sha256-content are the same. -The format allows round-trip conversion between newhash-content and +The format allows round-trip conversion between sha256-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 +today. The content that is compressed and stored uses sha256-content instead of sha1-content. Pack index @@ -255,10 +252,10 @@ network byte order): 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 + - A copy of the 20-byte SHA-256 checksum at the end of the corresponding packfile. - - 20-byte NewHash checksum of all of the above. + - 20-byte SHA-256 checksum of all of the above. Loose object index ~~~~~~~~~~~~~~~~~~ @@ -266,7 +263,7 @@ 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)* + (sha256-name SP sha1-name LF)* where the object names are in hexadecimal format. The file is not sorted. @@ -292,8 +289,8 @@ To remove entries (e.g. in "git pack-refs" or "git-prune"): 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: +and sha256-names. The lookup proceeds similarly to ordinary object +lookups. For example, to convert a sha1-name to a sha256-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: @@ -301,8 +298,8 @@ lookups. For example, to convert a sha1-name to a newhash-name: 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. + c. Read the corresponding entry in the full sha256-name table. + That is the object's sha256-name. 2. Check for a loose object. Read lines from loose-object-idx until we find a match. @@ -318,25 +315,25 @@ 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. +The sha1-content of an object can be read by converting all sha256-names +its sha256-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. +and SHA-256 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 +can be translated to SHA-256 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 +mentioned by the server are converted to SHA-256 when looking them up locally. After negotiation, the server sends a packfile containing the -requested objects. We convert the packfile to NewHash format using +requested objects. We convert the packfile to SHA-256 format using the following steps: 1. index-pack: inflate each object in the packfile and compute its @@ -351,12 +348,12 @@ the following steps: (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 +3. convert to sha256: open a new (sha256) 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. + sha1-content, convert to sha256-content, and write it to the sha256 + pack. Record the new sha1<->sha256 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 + in the pack the server generated and include blobs. Write a sha256 idx file 5. clean up: remove the SHA-1 based pack file, index, and topologically sorted list obtained from the server in steps 1 @@ -388,16 +385,16 @@ send-pack. Signed Commits ~~~~~~~~~~~~~~ -We add a new field "gpgsig-newhash" to the commit object format to allow +We add a new field "gpgsig-sha256" 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. +existing "gpgsig" field. Its signed payload is the sha256-content of the +commit object with any "gpgsig" and "gpgsig-sha256" 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 +2. using both SHA-1 and SHA-256, by using both gpgsig-sha256 and gpgsig fields. -3. using only NewHash, by only using the gpgsig-newhash field. +3. using only SHA-256, by only using the gpgsig-sha256 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 @@ -405,24 +402,24 @@ ordinary unsigned commit. Signed Tags ~~~~~~~~~~~ -We add a new field "gpgsig-newhash" to the tag object format to allow +We add a new field "gpgsig-sha256" 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 +sha256-content of the tag with its gpgsig-sha256 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 +2. using both SHA-1 and SHA-256, by using gpgsig-sha256 and an in-body signature. -3. using only NewHash, by only using the gpgsig-newhash field. +3. using only SHA-256, by only using the gpgsig-sha256 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. +The mergetag field in the sha256-content of the same commit contains the +sha256-content of the same tag. Submodules ~~~~~~~~~~ @@ -497,7 +494,7 @@ Caveats ------- Invalid objects ~~~~~~~~~~~~~~~ -The conversion from sha1-content to newhash-content retains any +The conversion from sha1-content to sha256-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 @@ -516,7 +513,7 @@ allow lifting this restriction. Alternates ~~~~~~~~~~ -For the same reason, a newhash repository cannot borrow objects from a +For the same reason, a sha256 repository cannot borrow objects from a sha1 repository using objects/info/alternates or $GIT_ALTERNATE_OBJECT_REPOSITORIES. @@ -524,20 +521,20 @@ 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 +sha256-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 +Until Git protocol gains SHA-256 support, using SHA-256 based storage on public-facing Git servers is strongly discouraged. Once Git -protocol gains NewHash support, NewHash based servers are likely not +protocol gains SHA-256 support, SHA-256 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 +personal SHA-256 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. @@ -547,7 +544,7 @@ 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 +hexadecimal digit) or SHA-256 (64 hexadecimal digit) objects then the intent behind the PGP signed payload in an object signature is unclear: @@ -562,7 +559,7 @@ 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 +Fortunately SHA-256 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. @@ -574,24 +571,24 @@ 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 + objects using SHA-256. 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 + 2. ("early transition") Allow both SHA-1 and SHA-256 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 + 3. ("late transition") Allow both SHA-1 and SHA-256 object names in + input. Any object names written to output use SHA-256. 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 + SHA-256 and write output using SHA-256. This is safer than mode 3 because there is less risk that input is incorrectly interpreted using the wrong hash function. @@ -601,27 +598,31 @@ 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} +git --output-format=sha1 log abac87a^{sha1}..f787cac^{sha256} -Selection of a New Hash ------------------------ +Choice of 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. +Git v2.13.0 and later subsequently moved to a hardened SHA-1 +implementation by default that mitigates the SHAttered attack, but +SHA-1 is still believed to be weak. + +The hash to replace this hardened 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). +2. High quality implementations should be widely available (e.g., in + OpenSSL and Apple CommonCrypto). 3. The hash function's properties should match Git's needs (e.g. Git requires collision and 2nd preimage resistance and does not require @@ -630,14 +631,13 @@ Some other relevant properties: 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. +We choose SHA-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 +- teaching fsck to tolerate the gpgsig-sha256 field - excluding gpgsig-* from the fields copied by "git commit --amend" - annotating tests that depend on SHA-1 values with a SHA1 test prerequisite @@ -664,7 +664,7 @@ Next comes introduction of compatObjectFormat: - adding appropriate index entries when adding a new object to the object store - --output-format option -- ^{sha1} and ^{newhash} revision notation +- ^{sha1} and ^{sha256} revision notation - configuration to specify default input and output format (see "Object names on the command line" above) @@ -672,7 +672,7 @@ 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 +- convert the fetched packfile to sha256 format and generate an idx file - re-sort to match the order of objects in the fetched packfile @@ -680,30 +680,30 @@ 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 +section). In particular this allows users to verify SHA-256 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. +new, more futureproof SHA-256 object names. When objectFormat and compatObjectFormat are both set, commands -generating signatures would generate both SHA-1 and NewHash signatures +generating signatures would generate both SHA-1 and SHA-256 signatures by default to support both new and old users. -In projects using NewHash heavily, users could be encouraged to adopt +In projects using SHA-256 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 +can verify SHA-256 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 +setting to generate only SHA-256 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 +repositories to use SHA-256 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. @@ -742,16 +742,16 @@ using the old hash function. 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 +Instead of introducing the gpgsig-sha256 field in commit and tag objects +for sha256-content based signatures, an earlier version of this design +added "hash sha256 <sha256-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. + attest to the sha1-name and sha256-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. @@ -760,11 +760,11 @@ However, it also came with disadvantages: 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 + and "hash sha1 parent <sha1-name>" to the sha256-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 + field to suppress including "hash sha1" fields in the sha256-content and signed payload. Lazily populated translation table @@ -772,7 +772,7 @@ 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 +being streamed to disk and having its sha256-name calculated should be an acceptable cost. Document History @@ -814,6 +814,12 @@ Incorporated suggestions from jonathantanmy and sbeller: * avoid loose object overhead by packing more aggressively in "git gc --auto" +Later history: + + See the history of this file in git.git for the history of subsequent + edits. This document history is no longer being maintained as it + would now be superfluous to the commit log + [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/ diff --git a/Documentation/technical/http-protocol.txt b/Documentation/technical/http-protocol.txt index 64f49d0bbb..9c5b6f0fac 100644 --- a/Documentation/technical/http-protocol.txt +++ b/Documentation/technical/http-protocol.txt @@ -338,11 +338,11 @@ server advertises capability `allow-tip-sha1-in-want` or request_end request_end = "0000" / "done" - want_list = PKT-LINE(want NUL cap_list LF) + want_list = PKT-LINE(want SP cap_list LF) *(want_pkt) want_pkt = PKT-LINE(want LF) want = "want" SP id - cap_list = *(SP capability) SP + cap_list = capability *(SP capability) have_list = *PKT-LINE("have" SP id LF) diff --git a/Documentation/technical/multi-pack-index.txt b/Documentation/technical/multi-pack-index.txt new file mode 100644 index 0000000000..d7e57639f7 --- /dev/null +++ b/Documentation/technical/multi-pack-index.txt @@ -0,0 +1,109 @@ +Multi-Pack-Index (MIDX) Design Notes +==================================== + +The Git object directory contains a 'pack' directory containing +packfiles (with suffix ".pack") and pack-indexes (with suffix +".idx"). The pack-indexes provide a way to lookup objects and +navigate to their offset within the pack, but these must come +in pairs with the packfiles. This pairing depends on the file +names, as the pack-index differs only in suffix with its pack- +file. While the pack-indexes provide fast lookup per packfile, +this performance degrades as the number of packfiles increases, +because abbreviations need to inspect every packfile and we are +more likely to have a miss on our most-recently-used packfile. +For some large repositories, repacking into a single packfile +is not feasible due to storage space or excessive repack times. + +The multi-pack-index (MIDX for short) stores a list of objects +and their offsets into multiple packfiles. It contains: + +- A list of packfile names. +- A sorted list of object IDs. +- A list of metadata for the ith object ID including: + - A value j referring to the jth packfile. + - An offset within the jth packfile for the object. +- If large offsets are required, we use another list of large + offsets similar to version 2 pack-indexes. + +Thus, we can provide O(log N) lookup time for any number +of packfiles. + +Design Details +-------------- + +- The MIDX is stored in a file named 'multi-pack-index' in the + .git/objects/pack directory. This could be stored in the pack + directory of an alternate. It refers only to packfiles in that + same directory. + +- The pack.multiIndex config setting must be on to consume MIDX files. + +- The file format includes parameters for the object ID hash + function, so a future change of hash algorithm does not require + a change in format. + +- The MIDX keeps only one record per object ID. If an object appears + in multiple packfiles, then the MIDX selects the copy in the most- + recently modified packfile. + +- If there exist packfiles in the pack directory not registered in + the MIDX, then those packfiles are loaded into the `packed_git` + list and `packed_git_mru` cache. + +- The pack-indexes (.idx files) remain in the pack directory so we + can delete the MIDX file, set core.midx to false, or downgrade + without any loss of information. + +- The MIDX file format uses a chunk-based approach (similar to the + commit-graph file) that allows optional data to be added. + +Future Work +----------- + +- Add a 'verify' subcommand to the 'git midx' builtin to verify the + contents of the multi-pack-index file match the offsets listed in + the corresponding pack-indexes. + +- The multi-pack-index allows many packfiles, especially in a context + where repacking is expensive (such as a very large repo), or + unexpected maintenance time is unacceptable (such as a high-demand + build machine). However, the multi-pack-index needs to be rewritten + in full every time. We can extend the format to be incremental, so + writes are fast. By storing a small "tip" multi-pack-index that + points to large "base" MIDX files, we can keep writes fast while + still reducing the number of binary searches required for object + lookups. + +- The reachability bitmap is currently paired directly with a single + packfile, using the pack-order as the object order to hopefully + compress the bitmaps well using run-length encoding. This could be + extended to pair a reachability bitmap with a multi-pack-index. If + the multi-pack-index is extended to store a "stable object order" + (a function Order(hash) = integer that is constant for a given hash, + even as the multi-pack-index is updated) then a reachability bitmap + could point to a multi-pack-index and be updated independently. + +- Packfiles can be marked as "special" using empty files that share + the initial name but replace ".pack" with ".keep" or ".promisor". + We can add an optional chunk of data to the multi-pack-index that + records flags of information about the packfiles. This allows new + states, such as 'repacked' or 'redeltified', that can help with + pack maintenance in a multi-pack environment. It may also be + helpful to organize packfiles by object type (commit, tree, blob, + etc.) and use this metadata to help that maintenance. + +- The partial clone feature records special "promisor" packs that + may point to objects that are not stored locally, but available + on request to a server. The multi-pack-index does not currently + track these promisor packs. + +Related Links +------------- +[0] https://bugs.chromium.org/p/git/issues/detail?id=6 + Chromium work item for: Multi-Pack Index (MIDX) + +[1] https://public-inbox.org/git/20180107181459.222909-1-dstolee@microsoft.com/ + An earlier RFC for the multi-pack-index feature + +[2] https://public-inbox.org/git/alpine.DEB.2.20.1803091557510.23109@alexmv-linux/ + Git Merge 2018 Contributor's summit notes (includes discussion of MIDX) diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt index 70a99fd142..cab5bdd2ff 100644 --- a/Documentation/technical/pack-format.txt +++ b/Documentation/technical/pack-format.txt @@ -252,3 +252,80 @@ Pack file entry: <+ corresponding packfile. 20-byte SHA-1-checksum of all of the above. + +== multi-pack-index (MIDX) files have the following format: + +The multi-pack-index files refer to multiple pack-files and loose objects. + +In order to allow extensions that add extra data to the MIDX, we organize +the body into "chunks" and provide a lookup table at the beginning of the +body. The header includes certain length values, such as the number of packs, +the number of base MIDX files, hash lengths and types. + +All 4-byte numbers are in network order. + +HEADER: + + 4-byte signature: + The signature is: {'M', 'I', 'D', 'X'} + + 1-byte version number: + Git only writes or recognizes version 1. + + 1-byte Object Id Version + Git only writes or recognizes version 1 (SHA1). + + 1-byte number of "chunks" + + 1-byte number of base multi-pack-index files: + This value is currently always zero. + + 4-byte number of pack files + +CHUNK LOOKUP: + + (C + 1) * 12 bytes providing the chunk offsets: + First 4 bytes describe chunk id. Value 0 is a terminating label. + Other 8 bytes provide offset in current file for chunk to start. + (Chunks are provided in file-order, so you can infer the length + using the next chunk position if necessary.) + + The remaining data in the body is described one chunk at a time, and + these chunks may be given in any order. Chunks are required unless + otherwise specified. + +CHUNK DATA: + + Packfile Names (ID: {'P', 'N', 'A', 'M'}) + Stores the packfile names as concatenated, null-terminated strings. + Packfiles must be listed in lexicographic order for fast lookups by + name. This is the only chunk not guaranteed to be a multiple of four + bytes in length, so should be the last chunk for alignment reasons. + + OID Fanout (ID: {'O', 'I', 'D', 'F'}) + The ith entry, F[i], stores the number of OIDs with first + byte at most i. Thus F[255] stores the total + number of objects. + + OID Lookup (ID: {'O', 'I', 'D', 'L'}) + The OIDs for all objects in the MIDX are stored in lexicographic + order in this chunk. + + Object Offsets (ID: {'O', 'O', 'F', 'F'}) + Stores two 4-byte values for every object. + 1: The pack-int-id for the pack storing this object. + 2: The offset within the pack. + If all offsets are less than 2^31, then the large offset chunk + will not exist and offsets are stored as in IDX v1. + If there is at least one offset value larger than 2^32-1, then + the large offset chunk must exist. If the large offset chunk + exists and the 31st bit is on, then removing that bit reveals + the row in the large offsets containing the 8-byte offset of + this object. + + [Optional] Object Large Offsets (ID: {'L', 'O', 'F', 'F'}) + 8-byte offsets into large packfiles. + +TRAILER: + + 20-byte SHA1-checksum of the above contents. diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index 7fee6b780a..6ac774d5f6 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -50,7 +50,8 @@ Each Extra Parameter takes the form of `<key>=<value>` or `<key>`. Servers that receive any such Extra Parameters MUST ignore all unrecognized keys. Currently, the only Extra Parameter recognized is -"version=1". +"version" with a value of '1' or '2'. See protocol-v2.txt for more +information on protocol version 2. Git Transport ------------- @@ -284,7 +285,9 @@ information is sent back to the client in the next step. The client can optionally request that pack-objects omit various objects from the packfile using one of several filtering techniques. These are intended for use with partial clone and partial fetch -operations. See `rev-list` for possible "filter-spec" values. +operations. An object that does not meet a filter-spec value is +omitted unless explicitly requested in a 'want' line. See `rev-list` +for possible filter-spec values. Once all the 'want's and 'shallow's (and optional 'deepen') are transferred, clients MUST send a flush-pkt, to tell the server side diff --git a/Documentation/technical/partial-clone.txt b/Documentation/technical/partial-clone.txt index 0bed2472c8..1ef66bd788 100644 --- a/Documentation/technical/partial-clone.txt +++ b/Documentation/technical/partial-clone.txt @@ -69,24 +69,24 @@ Design Details - A new pack-protocol capability "filter" is added to the fetch-pack and upload-pack negotiation. - - This uses the existing capability discovery mechanism. - See "filter" in Documentation/technical/pack-protocol.txt. ++ +This uses the existing capability discovery mechanism. +See "filter" in Documentation/technical/pack-protocol.txt. - Clients pass a "filter-spec" to clone and fetch which is passed to the server to request filtering during packfile construction. - - There are various filters available to accommodate different situations. - See "--filter=<filter-spec>" in Documentation/rev-list-options.txt. ++ +There are various filters available to accommodate different situations. +See "--filter=<filter-spec>" in Documentation/rev-list-options.txt. - On the server pack-objects applies the requested filter-spec as it creates "filtered" packfiles for the client. - - These filtered packfiles are *incomplete* in the traditional sense because - they may contain objects that reference objects not contained in the - packfile and that the client doesn't already have. For example, the - filtered packfile may contain trees or tags that reference missing blobs - or commits that reference missing trees. ++ +These filtered packfiles are *incomplete* in the traditional sense because +they may contain objects that reference objects not contained in the +packfile and that the client doesn't already have. For example, the +filtered packfile may contain trees or tags that reference missing blobs +or commits that reference missing trees. - On the client these incomplete packfiles are marked as "promisor packfiles" and treated differently by various commands. @@ -104,47 +104,47 @@ Handling Missing Objects to repository corruption. To differentiate these cases, the local repository specially indicates such filtered packfiles obtained from the promisor remote as "promisor packfiles". - - These promisor packfiles consist of a "<name>.promisor" file with - arbitrary contents (like the "<name>.keep" files), in addition to - their "<name>.pack" and "<name>.idx" files. ++ +These promisor packfiles consist of a "<name>.promisor" file with +arbitrary contents (like the "<name>.keep" files), in addition to +their "<name>.pack" and "<name>.idx" files. - The local repository considers a "promisor object" to be an object that it knows (to the best of its ability) that the promisor remote has promised that it has, either because the local repository has that object in one of its promisor packfiles, or because another promisor object refers to it. - - When Git encounters a missing object, Git can see if it a promisor object - and handle it appropriately. If not, Git can report a corruption. - - This means that there is no need for the client to explicitly maintain an - expensive-to-modify list of missing objects.[a] ++ +When Git encounters a missing object, Git can see if it a promisor object +and handle it appropriately. If not, Git can report a corruption. ++ +This means that there is no need for the client to explicitly maintain an +expensive-to-modify list of missing objects.[a] - Since almost all Git code currently expects any referenced object to be present locally and because we do not want to force every command to do a dry-run first, a fallback mechanism is added to allow Git to attempt to dynamically fetch missing objects from the promisor remote. - - When the normal object lookup fails to find an object, Git invokes - fetch-object to try to get the object from the server and then retry - the object lookup. This allows objects to be "faulted in" without - complicated prediction algorithms. - - For efficiency reasons, no check as to whether the missing object is - actually a promisor object is performed. - - Dynamic object fetching tends to be slow as objects are fetched one at - a time. ++ +When the normal object lookup fails to find an object, Git invokes +fetch-object to try to get the object from the server and then retry +the object lookup. This allows objects to be "faulted in" without +complicated prediction algorithms. ++ +For efficiency reasons, no check as to whether the missing object is +actually a promisor object is performed. ++ +Dynamic object fetching tends to be slow as objects are fetched one at +a time. - `checkout` (and any other command using `unpack-trees`) has been taught to bulk pre-fetch all required missing blobs in a single batch. - `rev-list` has been taught to print missing objects. - - This can be used by other commands to bulk prefetch objects. - For example, a "git log -p A..B" may internally want to first do - something like "git rev-list --objects --quiet --missing=print A..B" - and prefetch those objects in bulk. ++ +This can be used by other commands to bulk prefetch objects. +For example, a "git log -p A..B" may internally want to first do +something like "git rev-list --objects --quiet --missing=print A..B" +and prefetch those objects in bulk. - `fsck` has been updated to be fully aware of promisor objects. @@ -154,11 +154,11 @@ Handling Missing Objects - The global variable "fetch_if_missing" is used to control whether an object lookup will attempt to dynamically fetch a missing object or report an error. - - We are not happy with this global variable and would like to remove it, - but that requires significant refactoring of the object code to pass an - additional flag. We hope that concurrent efforts to add an ODB API can - encompass this. ++ +We are not happy with this global variable and would like to remove it, +but that requires significant refactoring of the object code to pass an +additional flag. We hope that concurrent efforts to add an ODB API can +encompass this. Fetching Missing Objects @@ -168,10 +168,10 @@ Fetching Missing Objects transport_fetch_refs(), setting a new transport option TRANS_OPT_NO_DEPENDENTS to indicate that only the objects themselves are desired, not any object that they refer to. - - Because some transports invoke fetch_pack() in the same process, fetch_pack() - has been updated to not use any object flags when the corresponding argument - (no_dependents) is set. ++ +Because some transports invoke fetch_pack() in the same process, fetch_pack() +has been updated to not use any object flags when the corresponding argument +(no_dependents) is set. - The local repository sends a request with the hashes of all requested objects as "want" lines, and does not perform any packfile negotiation. @@ -187,13 +187,13 @@ Current Limitations - The remote used for a partial clone (or the first partial fetch following a regular clone) is marked as the "promisor remote". - - We are currently limited to a single promisor remote and only that - remote may be used for subsequent partial fetches. - - We accept this limitation because we believe initial users of this - feature will be using it on repositories with a strong single central - server. ++ +We are currently limited to a single promisor remote and only that +remote may be used for subsequent partial fetches. ++ +We accept this limitation because we believe initial users of this +feature will be using it on repositories with a strong single central +server. - Dynamic object fetching will only ask the promisor remote for missing objects. We assume that the promisor remote has a complete view of the @@ -221,13 +221,13 @@ Future Work - Allow more than one promisor remote and define a strategy for fetching missing objects from specific promisor remotes or of iterating over the set of promisor remotes until a missing object is found. - - A user might want to have multiple geographically-close cache servers - for fetching missing blobs while continuing to do filtered `git-fetch` - commands from the central server, for example. - - Or the user might want to work in a triangular work flow with multiple - promisor remotes that each have an incomplete view of the repository. ++ +A user might want to have multiple geographically-close cache servers +for fetching missing blobs while continuing to do filtered `git-fetch` +commands from the central server, for example. ++ +Or the user might want to work in a triangular work flow with multiple +promisor remotes that each have an incomplete view of the repository. - Allow repack to work on promisor packfiles (while keeping them distinct from non-promisor packfiles). @@ -238,25 +238,25 @@ Future Work - Investigate use of a long-running process to dynamically fetch a series of objects, such as proposed in [5,6] to reduce process startup and overhead costs. - - It would be nice if pack protocol V2 could allow that long-running - process to make a series of requests over a single long-running - connection. ++ +It would be nice if pack protocol V2 could allow that long-running +process to make a series of requests over a single long-running +connection. - Investigate pack protocol V2 to avoid the info/refs broadcast on each connection with the server to dynamically fetch missing objects. - Investigate the need to handle loose promisor objects. - - Objects in promisor packfiles are allowed to reference missing objects - that can be dynamically fetched from the server. An assumption was - made that loose objects are only created locally and therefore should - not reference a missing object. We may need to revisit that assumption - if, for example, we dynamically fetch a missing tree and store it as a - loose object rather than a single object packfile. - - This does not necessarily mean we need to mark loose objects as promisor; - it may be sufficient to relax the object lookup or is-promisor functions. ++ +Objects in promisor packfiles are allowed to reference missing objects +that can be dynamically fetched from the server. An assumption was +made that loose objects are only created locally and therefore should +not reference a missing object. We may need to revisit that assumption +if, for example, we dynamically fetch a missing tree and store it as a +loose object rather than a single object packfile. ++ +This does not necessarily mean we need to mark loose objects as promisor; +it may be sufficient to relax the object lookup or is-promisor functions. Non-Tasks @@ -265,13 +265,13 @@ Non-Tasks - Every time the subject of "demand loading blobs" comes up it seems that someone suggests that the server be allowed to "guess" and send additional objects that may be related to the requested objects. - - No work has gone into actually doing that; we're just documenting that - it is a common suggestion. We're not sure how it would work and have - no plans to work on it. - - It is valid for the server to send more objects than requested (even - for a dynamic object fetch), but we are not building on that. ++ +No work has gone into actually doing that; we're just documenting that +it is a common suggestion. We're not sure how it would work and have +no plans to work on it. ++ +It is valid for the server to send more objects than requested (even +for a dynamic object fetch), but we are not building on that. Footnotes @@ -282,43 +282,43 @@ Footnotes This would essentially be a sorted linear list of OIDs that the were omitted by the server during a clone or subsequent fetches. - This file would need to be loaded into memory on every object lookup. - It would need to be read, updated, and re-written (like the .git/index) - on every explicit "git fetch" command *and* on any dynamic object fetch. +This file would need to be loaded into memory on every object lookup. +It would need to be read, updated, and re-written (like the .git/index) +on every explicit "git fetch" command *and* on any dynamic object fetch. - The cost to read, update, and write this file could add significant - overhead to every command if there are many missing objects. For example, - if there are 100M missing blobs, this file would be at least 2GiB on disk. +The cost to read, update, and write this file could add significant +overhead to every command if there are many missing objects. For example, +if there are 100M missing blobs, this file would be at least 2GiB on disk. - With the "promisor" concept, we *infer* a missing object based upon the - type of packfile that references it. +With the "promisor" concept, we *infer* a missing object based upon the +type of packfile that references it. Related Links ------------- -[0] https://bugs.chromium.org/p/git/issues/detail?id=2 - Chromium work item for: Partial Clone +[0] https://crbug.com/git/2 + Bug#2: Partial Clone -[1] https://public-inbox.org/git/20170113155253.1644-1-benpeart@microsoft.com/ - Subject: [RFC] Add support for downloading blobs on demand +[1] https://public-inbox.org/git/20170113155253.1644-1-benpeart@microsoft.com/ + + Subject: [RFC] Add support for downloading blobs on demand + Date: Fri, 13 Jan 2017 10:52:53 -0500 -[2] https://public-inbox.org/git/cover.1506714999.git.jonathantanmy@google.com/ - Subject: [PATCH 00/18] Partial clone (from clone to lazy fetch in 18 patches) +[2] https://public-inbox.org/git/cover.1506714999.git.jonathantanmy@google.com/ + + Subject: [PATCH 00/18] Partial clone (from clone to lazy fetch in 18 patches) + Date: Fri, 29 Sep 2017 13:11:36 -0700 -[3] https://public-inbox.org/git/20170426221346.25337-1-jonathantanmy@google.com/ - Subject: Proposal for missing blob support in Git repos +[3] https://public-inbox.org/git/20170426221346.25337-1-jonathantanmy@google.com/ + + Subject: Proposal for missing blob support in Git repos + Date: Wed, 26 Apr 2017 15:13:46 -0700 -[4] https://public-inbox.org/git/1488999039-37631-1-git-send-email-git@jeffhostetler.com/ - Subject: [PATCH 00/10] RFC Partial Clone and Fetch +[4] https://public-inbox.org/git/1488999039-37631-1-git-send-email-git@jeffhostetler.com/ + + Subject: [PATCH 00/10] RFC Partial Clone and Fetch + Date: Wed, 8 Mar 2017 18:50:29 +0000 -[5] https://public-inbox.org/git/20170505152802.6724-1-benpeart@microsoft.com/ - Subject: [PATCH v7 00/10] refactor the filter process code into a reusable module +[5] https://public-inbox.org/git/20170505152802.6724-1-benpeart@microsoft.com/ + + Subject: [PATCH v7 00/10] refactor the filter process code into a reusable module + Date: Fri, 5 May 2017 11:27:52 -0400 -[6] https://public-inbox.org/git/20170714132651.170708-1-benpeart@microsoft.com/ - Subject: [RFC/PATCH v2 0/1] Add support for downloading blobs on demand +[6] https://public-inbox.org/git/20170714132651.170708-1-benpeart@microsoft.com/ + + Subject: [RFC/PATCH v2 0/1] Add support for downloading blobs on demand + Date: Fri, 14 Jul 2017 09:26:50 -0400 diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt index 49bda76d23..09e4e0273f 100644 --- a/Documentation/technical/protocol-v2.txt +++ b/Documentation/technical/protocol-v2.txt @@ -64,9 +64,8 @@ When using the http:// or https:// transport a client makes a "smart" info/refs request as described in `http-protocol.txt` and requests that v2 be used by supplying "version=2" in the `Git-Protocol` header. - C: Git-Protocol: version=2 - C: C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0 + C: Git-Protocol: version=2 A v2 server would reply: @@ -299,12 +298,21 @@ included in the client's request: for use with partial clone and partial fetch operations. See `rev-list` for possible "filter-spec" values. +If the 'ref-in-want' feature is advertised, the following argument can +be included in the client's request as well as the potential addition of +the 'wanted-refs' section in the server's response as explained below. + + want-ref <ref> + Indicates to the server that the client wants to retrieve a + particular ref, where <ref> is the full name of a ref on the + server. + The response of `fetch` is broken into a number of sections separated by delimiter packets (0001), with each section beginning with its section header. output = *section - section = (acknowledgments | shallow-info | packfile) + section = (acknowledgments | shallow-info | wanted-refs | packfile) (flush-pkt | delim-pkt) acknowledgments = PKT-LINE("acknowledgments" LF) @@ -319,6 +327,10 @@ header. shallow = "shallow" SP obj-id unshallow = "unshallow" SP obj-id + wanted-refs = PKT-LINE("wanted-refs" LF) + *PKT-LINE(wanted-ref LF) + wanted-ref = obj-id SP refname + packfile = PKT-LINE("packfile" LF) *PKT-LINE(%x01-03 *%x00-ff) @@ -379,6 +391,19 @@ header. * This section is only included if a packfile section is also included in the response. + wanted-refs section + * This section is only included if the client has requested a + ref using a 'want-ref' line and if a packfile section is also + included in the response. + + * Always begins with the section header "wanted-refs". + + * The server will send a ref listing ("<oid> <refname>") for + each reference requested using 'want-ref' lines. + + * The server MUST NOT send any refs which were not requested + using 'want-ref' lines. + packfile section * This section is only included if the client has sent 'want' lines in its request and either requested that no more diff --git a/Documentation/technical/rerere.txt b/Documentation/technical/rerere.txt new file mode 100644 index 0000000000..aa22d7ace8 --- /dev/null +++ b/Documentation/technical/rerere.txt @@ -0,0 +1,186 @@ +Rerere +====== + +This document describes the rerere logic. + +Conflict normalization +---------------------- + +To ensure recorded conflict resolutions can be looked up in the rerere +database, even when branches are merged in a different order, +different branches are merged that result in the same conflict, or +when different conflict style settings are used, rerere normalizes the +conflicts before writing them to the rerere database. + +Different conflict styles and branch names are normalized by stripping +the labels from the conflict markers, and removing the common ancestor +version from the `diff3` conflict style. Branches that are merged +in different order are normalized by sorting the conflict hunks. More +on each of those steps in the following sections. + +Once these two normalization operations are applied, a conflict ID is +calculated based on the normalized conflict, which is later used by +rerere to look up the conflict in the rerere database. + +Removing the common ancestor version +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Say we have three branches AB, AC and AC2. The common ancestor of +these branches has a file with a line containing the string "A" (for +brevity this is called "line A" in the rest of the document). In +branch AB this line is changed to "B", in AC, this line is changed to +"C", and branch AC2 is forked off of AC, after the line was changed to +"C". + +Forking a branch ABAC off of branch AB and then merging AC into it, we +get a conflict like the following: + + <<<<<<< HEAD + B + ======= + C + >>>>>>> AC + +Doing the analogous with AC2 (forking a branch ABAC2 off of branch AB +and then merging branch AC2 into it), using the diff3 conflict style, +we get a conflict like the following: + + <<<<<<< HEAD + B + ||||||| merged common ancestors + A + ======= + C + >>>>>>> AC2 + +By resolving this conflict, to leave line D, the user declares: + + After examining what branches AB and AC did, I believe that making + line A into line D is the best thing to do that is compatible with + what AB and AC wanted to do. + +As branch AC2 refers to the same commit as AC, the above implies that +this is also compatible what AB and AC2 wanted to do. + +By extension, this means that rerere should recognize that the above +conflicts are the same. To do this, the labels on the conflict +markers are stripped, and the common ancestor version is removed. The above +examples would both result in the following normalized conflict: + + <<<<<<< + B + ======= + C + >>>>>>> + +Sorting hunks +~~~~~~~~~~~~~ + +As before, lets imagine that a common ancestor had a file with line A +its early part, and line X in its late part. And then four branches +are forked that do these things: + + - AB: changes A to B + - AC: changes A to C + - XY: changes X to Y + - XZ: changes X to Z + +Now, forking a branch ABAC off of branch AB and then merging AC into +it, and forking a branch ACAB off of branch AC and then merging AB +into it, would yield the conflict in a different order. The former +would say "A became B or C, what now?" while the latter would say "A +became C or B, what now?" + +As a reminder, the act of merging AC into ABAC and resolving the +conflict to leave line D means that the user declares: + + After examining what branches AB and AC did, I believe that + making line A into line D is the best thing to do that is + compatible with what AB and AC wanted to do. + +So the conflict we would see when merging AB into ACAB should be +resolved the same way---it is the resolution that is in line with that +declaration. + +Imagine that similarly previously a branch XYXZ was forked from XY, +and XZ was merged into it, and resolved "X became Y or Z" into "X +became W". + +Now, if a branch ABXY was forked from AB and then merged XY, then ABXY +would have line B in its early part and line Y in its later part. +Such a merge would be quite clean. We can construct 4 combinations +using these four branches ((AB, AC) x (XY, XZ)). + +Merging ABXY and ACXZ would make "an early A became B or C, a late X +became Y or Z" conflict, while merging ACXY and ABXZ would make "an +early A became C or B, a late X became Y or Z". We can see there are +4 combinations of ("B or C", "C or B") x ("X or Y", "Y or X"). + +By sorting, the conflict is given its canonical name, namely, "an +early part became B or C, a late part becames X or Y", and whenever +any of these four patterns appear, and we can get to the same conflict +and resolution that we saw earlier. + +Without the sorting, we'd have to somehow find a previous resolution +from combinatorial explosion. + +Conflict ID calculation +~~~~~~~~~~~~~~~~~~~~~~~ + +Once the conflict normalization is done, the conflict ID is calculated +as the sha1 hash of the conflict hunks appended to each other, +separated by <NUL> characters. The conflict markers are stripped out +before the sha1 is calculated. So in the example above, where we +merge branch AC which changes line A to line C, into branch AB, which +changes line A to line C, the conflict ID would be +SHA1('B<NUL>C<NUL>'). + +If there are multiple conflicts in one file, the sha1 is calculated +the same way with all hunks appended to each other, in the order in +which they appear in the file, separated by a <NUL> character. + +Nested conflicts +~~~~~~~~~~~~~~~~ + +Nested conflicts are handled very similarly to "simple" conflicts. +Similar to simple conflicts, the conflict is first normalized by +stripping the labels from conflict markers, stripping the common ancestor +version, and the sorting the conflict hunks, both for the outer and the +inner conflict. This is done recursively, so any number of nested +conflicts can be handled. + +Note that this only works for conflict markers that "cleanly nest". If +there are any unmatched conflict markers, rerere will fail to handle +the conflict and record a conflict resolution. + +The only difference is in how the conflict ID is calculated. For the +inner conflict, the conflict markers themselves are not stripped out +before calculating the sha1. + +Say we have the following conflict for example: + + <<<<<<< HEAD + 1 + ======= + <<<<<<< HEAD + 3 + ======= + 2 + >>>>>>> branch-2 + >>>>>>> branch-3~ + +After stripping out the labels of the conflict markers, and sorting +the hunks, the conflict would look as follows: + + <<<<<<< + 1 + ======= + <<<<<<< + 2 + ======= + 3 + >>>>>>> + >>>>>>> + +and finally the conflict ID would be calculated as: +`sha1('1<NUL><<<<<<<\n3\n=======\n2\n>>>>>>><NUL>')` |