Merge branch 'nd/checkout-m-doc-update'
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 10:28:10 +0000 (19:28 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 10:28:10 +0000 (19:28 +0900)
Doc about the above.

* nd/checkout-m-doc-update:
  checkout.txt: note about losing staged changes with --merge

247 files changed:
.clang-format
.github/CONTRIBUTING.md
.github/PULL_REQUEST_TEMPLATE.md
.gitignore
.travis.yml
Documentation/.gitignore
Documentation/Makefile
Documentation/RelNotes/2.22.0.txt [new file with mode: 0644]
Documentation/asciidoctor-extensions.rb
Documentation/config/branch.txt
Documentation/config/diff.txt
Documentation/config/fsck.txt
Documentation/config/gc.txt
Documentation/config/gpg.txt
Documentation/config/pull.txt
Documentation/config/rebase.txt
Documentation/config/user.txt
Documentation/diff-format.txt
Documentation/diff-generate-patch.txt
Documentation/diff-options.txt
Documentation/doc-diff
Documentation/git-add.txt
Documentation/git-am.txt
Documentation/git-branch.txt
Documentation/git-checkout.txt
Documentation/git-cherry-pick.txt
Documentation/git-clean.txt
Documentation/git-commit-tree.txt
Documentation/git-config.txt
Documentation/git-diff-tree.txt
Documentation/git-fsck.txt
Documentation/git-gc.txt
Documentation/git-grep.txt
Documentation/git-http-backend.txt
Documentation/git-ls-remote.txt
Documentation/git-merge.txt
Documentation/git-notes.txt
Documentation/git-rebase.txt
Documentation/git-reset.txt
Documentation/git-revert.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-worktree.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/githooks.txt
Documentation/gitignore.txt
Documentation/gitremote-helpers.txt
Documentation/gitweb.conf.txt
Documentation/glossary-content.txt
Documentation/merge-options.txt
Documentation/pretty-formats.txt
Documentation/rev-list-options.txt
Documentation/technical/api-trace2.txt [new file with mode: 0644]
Documentation/technical/directory-rename-detection.txt
Documentation/technical/pack-protocol.txt
Documentation/technical/protocol-capabilities.txt
GIT-VERSION-GEN
Makefile
RelNotes
apply.c
attr.c
bisect.c
blame.c
builtin/am.c
builtin/blame.c
builtin/branch.c
builtin/checkout.c
builtin/commit-tree.c
builtin/commit.c
builtin/diff-tree.c
builtin/diff.c
builtin/fetch.c
builtin/fsck.c
builtin/help.c
builtin/init-db.c
builtin/log.c
builtin/merge.c
builtin/pack-objects.c
builtin/pack-redundant.c
builtin/prune-packed.c
builtin/prune.c
builtin/pull.c
builtin/rebase.c
builtin/receive-pack.c
builtin/replace.c
builtin/reset.c
builtin/rev-list.c
builtin/submodule--helper.c
builtin/update-index.c
builtin/worktree.c
cache.h
check-racy.c [deleted file]
ci/run-windows-build.sh [deleted file]
combine-diff.c
common-main.c
compat/bswap.h
compat/mingw.c
compat/mingw.h
compat/win32/trace2_win32_process_info.c [new file with mode: 0644]
config.c
config.mak.dev
config.mak.uname
connect.c
contrib/completion/git-completion.bash
contrib/subtree/git-subtree.sh
convert.c
date.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
editor.c
entry.c
exec-cmd.c
fetch-pack.c
git-compat-util.h
git-legacy-rebase.sh [deleted file]
git-send-email.perl
git-submodule.sh
git.c
gitk-git/po/bg.po
help.c
ident.c
line-log.c
list-objects-filter-options.c
log-tree.c
merge-recursive.c
pack-objects.c
pack-objects.h
pager.c
parse-options-cb.c
parse-options.c
parse-options.h
path.c
pkt-line.c
pkt-line.h
pretty.c
protocol.c
reachable.c
read-cache.c
ref-filter.c
refs/files-backend.c
remote-curl.c
repository.c
repository.h
revision.c
revision.h
run-command.c
run-command.h
sequencer.c
setup.c
sh-i18n--envsubst.c
sha1-name.c
sha1collisiondetection
sha1dc/sha1.c
split-index.c
strbuf.c
strbuf.h
sub-process.c
submodule-config.c
submodule.c
t/README
t/helper/test-parse-options.c
t/helper/test-tool.c
t/helper/test-tool.h
t/helper/test-trace2.c [new file with mode: 0644]
t/perf/p5304-prune.sh [new file with mode: 0755]
t/perf/perf-lib.sh
t/t0001-init.sh
t/t0210-trace2-normal.sh [new file with mode: 0755]
t/t0210/scrub_normal.perl [new file with mode: 0644]
t/t0211-trace2-perf.sh [new file with mode: 0755]
t/t0211/scrub_perf.perl [new file with mode: 0644]
t/t0212-trace2-event.sh [new file with mode: 0755]
t/t0212/parse_events.perl [new file with mode: 0644]
t/t1060-object-corruption.sh
t/t1415-worktree-refs.sh
t/t1450-fsck.sh
t/t1700-split-index.sh
t/t2023-checkout-m.sh
t/t2025-checkout-no-overlay.sh [new file with mode: 0755]
t/t2400-worktree-add.sh [moved from t/t2025-worktree-add.sh with 100% similarity]
t/t2401-worktree-prune.sh [moved from t/t2026-worktree-prune.sh with 100% similarity]
t/t2402-worktree-list.sh [moved from t/t2027-worktree-list.sh with 100% similarity]
t/t2403-worktree-move.sh [moved from t/t2028-worktree-move.sh with 100% similarity]
t/t2404-worktree-config.sh [moved from t/t2029-worktree-config.sh with 100% similarity]
t/t3203-branch-output.sh
t/t3400-rebase.sh
t/t3404-rebase-interactive.sh
t/t3429-rebase-edit-todo.sh
t/t3600-rm.sh
t/t4014-format-patch.sh
t/t4038-diff-combined.sh
t/t4053-diff-no-index.sh
t/t4150-am.sh
t/t4205-log-pretty-formats.sh
t/t4211-line-log.sh
t/t5304-prune.sh
t/t5323-pack-redundant.sh [new file with mode: 0755]
t/t5400-send-pack.sh
t/t5500-fetch-pack.sh
t/t5503-tagfollow.sh
t/t5512-ls-remote.sh
t/t5515-fetch-merge-logic.sh
t/t5516-fetch-push.sh
t/t5539-fetch-http-shallow.sh
t/t5541-http-push-smart.sh
t/t5551-http-fetch-smart.sh
t/t5552-skipping-fetch-negotiator.sh
t/t5601-clone.sh
t/t5700-protocol-v1.sh
t/t5702-protocol-v2.sh
t/t6030-bisect-porcelain.sh
t/t7406-submodule-update.sh
t/t7517-per-repo-email.sh
t/t7800-difftool.sh
t/t9902-completion.sh
t/test-lib-functions.sh
t/test-lib.sh
trace2.c [new file with mode: 0644]
trace2.h [new file with mode: 0644]
trace2/tr2_cfg.c [new file with mode: 0644]
trace2/tr2_cfg.h [new file with mode: 0644]
trace2/tr2_cmd_name.c [new file with mode: 0644]
trace2/tr2_cmd_name.h [new file with mode: 0644]
trace2/tr2_dst.c [new file with mode: 0644]
trace2/tr2_dst.h [new file with mode: 0644]
trace2/tr2_sid.c [new file with mode: 0644]
trace2/tr2_sid.h [new file with mode: 0644]
trace2/tr2_tbuf.c [new file with mode: 0644]
trace2/tr2_tbuf.h [new file with mode: 0644]
trace2/tr2_tgt.h [new file with mode: 0644]
trace2/tr2_tgt_event.c [new file with mode: 0644]
trace2/tr2_tgt_normal.c [new file with mode: 0644]
trace2/tr2_tgt_perf.c [new file with mode: 0644]
trace2/tr2_tls.c [new file with mode: 0644]
trace2/tr2_tls.h [new file with mode: 0644]
trailer.c
trailer.h
transport-helper.c
transport.c
unpack-trees.c
usage.c
worktree.c
wt-status.c
xdiff-interface.c

index de1c8b5..41d4cd2 100644 (file)
@@ -149,7 +149,7 @@ Cpp11BracedListStyle: false
 
 # A list of macros that should be interpreted as foreach loops instead of as
 # function calls.
-ForEachMacros: ['for_each_string_list_item']
+ForEachMacros: ['for_each_string_list_item', 'for_each_wanted_builtin', 'for_each_builtin', 'for_each_ut']
 
 # The maximum number of consecutive empty lines to keep.
 MaxEmptyLinesToKeep: 1
index 64e605a..e7b4e2f 100644 (file)
@@ -5,7 +5,7 @@ Git community does not use github.com for their contributions. Instead, we use
 a mailing list (git@vger.kernel.org) for code submissions, code
 reviews, and bug reports.
 
-Nevertheless, you can use [submitGit](http://submitgit.herokuapp.com/) to
+Nevertheless, you can use [GitGitGadget](https://gitgitgadget.github.io/) to
 conveniently send your Pull Requests commits to our mailing list.
 
 Please read ["A note from the maintainer"](https://git.kernel.org/pub/scm/git/git.git/plain/MaintNotes?h=todo)
index adba13e..952c7c3 100644 (file)
@@ -1,7 +1,7 @@
 Thanks for taking the time to contribute to Git! Please be advised that the
 Git community does not use github.com for their contributions. Instead, we use
 a mailing list (git@vger.kernel.org) for code submissions, code reviews, and
-bug reports. Nevertheless, you can use submitGit to conveniently send your Pull
-Requests commits to our mailing list.
+bug reports. Nevertheless, you can use GitGitGadget (https://gitgitgadget.github.io/)
+to conveniently send your Pull Requests commits to our mailing list.
 
 Please read the "guidelines for contributing" linked above!
index 7374587..5cb84f1 100644 (file)
@@ -82,7 +82,6 @@
 /git-init-db
 /git-interpret-trailers
 /git-instaweb
-/git-legacy-rebase
 /git-log
 /git-ls-files
 /git-ls-remote
index 36cbdea..ffb1bc4 100644 (file)
@@ -21,16 +21,6 @@ matrix:
       compiler:
       addons:
       before_install:
-    - env: jobname=Windows
-      os: linux
-      compiler:
-      addons:
-      before_install:
-      script:
-        - >
-          test "$TRAVIS_REPO_SLUG" != "git/git" ||
-          ci/run-windows-build.sh $TRAVIS_BRANCH $(git rev-parse HEAD)
-      after_failure:
     - env: jobname=Linux32
       os: linux
       compiler:
index 3ef54e0..bf2bf27 100644 (file)
@@ -13,3 +13,4 @@ mergetools-*.txt
 manpage-base-url.xsl
 SubmittingPatches.txt
 tmp-doc-diff/
+GIT-ASCIIDOCFLAGS
index 26a2342..4e4dd7e 100644 (file)
@@ -331,6 +331,15 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
                show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
        date >$@
 
+TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK))
+
+GIT-ASCIIDOCFLAGS: FORCE
+       @FLAGS='$(TRACK_ASCIIDOCFLAGS)'; \
+           if test x"$$FLAGS" != x"`cat GIT-ASCIIDOCFLAGS 2>/dev/null`" ; then \
+               echo >&2 "    * new asciidoc flags"; \
+               echo "$$FLAGS" >GIT-ASCIIDOCFLAGS; \
+            fi
+
 clean:
        $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
        $(RM) *.texi *.texi+ *.texi++ git.info gitman.info
@@ -340,13 +349,14 @@ clean:
        $(RM) SubmittingPatches.txt
        $(RM) $(cmds_txt) $(mergetools_txt) *.made
        $(RM) manpage-base-url.xsl
+       $(RM) GIT-ASCIIDOCFLAGS
 
-$(MAN_HTML): %.html : %.txt asciidoc.conf
+$(MAN_HTML): %.html : %.txt asciidoc.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_HTML) -d manpage -o $@+ $< && \
        mv $@+ $@
 
-$(OBSOLETE_HTML): %.html : %.txto asciidoc.conf
+$(OBSOLETE_HTML): %.html : %.txto asciidoc.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_HTML) -o $@+ $< && \
        mv $@+ $@
@@ -354,16 +364,16 @@ $(OBSOLETE_HTML): %.html : %.txto asciidoc.conf
 manpage-base-url.xsl: manpage-base-url.xsl.in
        $(QUIET_GEN)sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@
 
-%.1 %.5 %.7 : %.xml manpage-base-url.xsl
+%.1 %.5 %.7 : %.xml manpage-base-url.xsl $(wildcard manpage*.xsl)
        $(QUIET_XMLTO)$(RM) $@ && \
        $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
 
-%.xml : %.txt asciidoc.conf
+%.xml : %.txt asciidoc.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_XML) -d manpage -o $@+ $< && \
        mv $@+ $@
 
-user-manual.xml: user-manual.txt user-manual.conf
+user-manual.xml: user-manual.txt user-manual.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_XML) -d book -o $@+ $< && \
        mv $@+ $@
@@ -373,7 +383,8 @@ technical/api-index.txt: technical/api-index-skel.txt \
        $(QUIET_GEN)cd technical && '$(SHELL_PATH_SQ)' ./api-index.sh
 
 technical/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
-$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt asciidoc.conf
+$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt \
+       asciidoc.conf GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt
 
 SubmittingPatches.txt: SubmittingPatches
@@ -430,7 +441,7 @@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
 WEBDOC_DEST = /pub/software/scm/git/docs
 
 howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
-$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
+$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        sed -e '1,/^$$/d' $< | \
        $(TXT_TO_HTML) - >$@+ && \
diff --git a/Documentation/RelNotes/2.22.0.txt b/Documentation/RelNotes/2.22.0.txt
new file mode 100644 (file)
index 0000000..5673c06
--- /dev/null
@@ -0,0 +1,189 @@
+Git 2.22 Release Notes
+======================
+
+Updates since v2.21
+-------------------
+
+UI, Workflows & Features
+
+ * "git checkout --no-overlay" can be used to trigger a new mode of
+   checking out paths out of the tree-ish, that allows paths that
+   match the pathspec that are in the current index and working tree
+   and are not in the tree-ish.
+
+ * The %(trailers) formatter in "git log --format=..."  now allows to
+   optionally pick trailers selectively by keyword, show only values,
+   etc.
+
+ * Four new configuration variables {author,committer}.{name,email}
+   have been introduced to override user.{name,email} in more specific
+   cases.
+
+ * Command-line completion (in contrib/) learned to tab-complete the
+   "git submodule absorbgitdirs" subcommand.
+
+ * "git branch" learned a new subcommand "--show-current".
+
+ * Output from "diff --cc" did not show the original paths when the
+   merge involved renames.  A new option adds the paths in the
+   original trees to the output.
+
+ * The command line completion (in contrib/) has been taught to
+   complete more subcommand parameters.
+
+ * The final report from "git bisect" used to show the suspected
+   culprit using a raw "diff-tree", with which there is no output for
+   a merge commit.  This has been updated to use a more modern and
+   human readable output that still is concise enough.
+
+ * "git rebase --rebase-merges" replaces its old "--preserve-merges"
+   option; the latter is now marked as deprecated.
+
+ * Error message given while cloning with --recurse-submodules has
+   been updated.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The diff machinery, one of the oldest parts of the system, which
+   long predates the parse-options API, uses fairly long and complex
+   handcrafted option parser.  This is being rewritten to use the
+   parse-options API.
+
+ * The implementation of pack-redundant has been updated for
+   performance in a repository with many packfiles.
+
+ * A more structured way to obtain execution trace has been added.
+
+ * "git prune" has been taught to take advantage of reachability
+   bitmap when able.
+
+ * The command line parser of "git commit-tree" has been rewritten to
+   use the parse-options API.
+
+ * Suggest GitGitGadget instead of submitGit as a way to submit
+   patches based on GitHub PR to us.
+
+
+Fixes since v2.21
+-----------------
+
+ * "git prune-packed" did not notice and complain against excess
+   arguments given from the command line, which now it does.
+   (merge 9b0bd87ed2 rj/prune-packed-excess-args later to maint).
+
+ * Split-index fix.
+   (merge 6e37c8ed3c nd/split-index-null-base-fix later to maint).
+
+ * "git diff --no-index" may still want to access Git goodies like
+   --ext-diff and --textconv, but so far these have been ignored,
+   which has been corrected.
+   (merge 287ab28bfa jk/diff-no-index-initialize later to maint).
+
+ * Unify RPC code for smart http in protocol v0/v1 and v2, which fixes
+   a bug in the latter (lack of authentication retry) and generally
+   improves the code base.
+   (merge a97d00799a jt/http-auth-proto-v2-fix later to maint).
+
+ * The include file compat/bswap.h has been updated so that it is safe
+   to (accidentally) include it more than once.
+   (merge 33aa579a55 jk/guard-bswap-header later to maint).
+
+ * The set of header files used by "make hdr-check" unconditionally
+   included sha256/gcrypt.h, even when it is not used, causing the
+   make target to fail.  We now skip it when GCRYPT_SHA256 is not in
+   use.
+   (merge f23aa18e7f rj/hdr-check-gcrypt-fix later to maint).
+
+ * The Makefile uses 'find' utility to enumerate all the *.h header
+   files, which is expensive on platforms with slow filesystems; it
+   now optionally uses "ls-files" if working within a repository,
+   which is a trick similar to how all sources are enumerated to run
+   ETAGS on.
+   (merge 92b88eba9f js/find-lib-h-with-ls-files-when-possible later to maint).
+
+ * "git rebase" that was reimplemented in C did not set ORIG_HEAD
+   correctly, which has been corrected.
+   (merge cbd29ead92 js/rebase-orig-head-fix later to maint).
+
+ * Dev support.
+   (merge f545737144 js/stress-test-ui-tweak later to maint).
+
+ * CFLAGS now can be tweaked when invoking Make while using
+   DEVELOPER=YesPlease; this did not work well before.
+   (merge 6d5d4b4e93 ab/makefile-help-devs-more later to maint).
+
+ * "git fsck --connectivity-only" omits computation necessary to sift
+   the objects that are not reachable from any of the refs into
+   unreachable and dangling.  This is now enabled when dangling
+   objects are requested (which is done by default, but can be
+   overridden with the "--no-dangling" option).
+   (merge 8d8c2a5aef jk/fsck-doc later to maint).
+
+ * On platforms where "git fetch" is killed with SIGPIPE (e.g. OSX),
+   the upload-pack that runs on the other end that hangs up after
+   detecting an error could cause "git fetch" to die with a signal,
+   which led to a flakey test.  "git fetch" now ignores SIGPIPE during
+   the network portion of its operation (this is not a problem as we
+   check the return status from our write(2)s).
+   (merge 143588949c jk/no-sigpipe-during-network-transport later to maint).
+
+ * A recent update broke "is this object available to us?" check for
+   well-known objects like an empty tree (which should yield "yes",
+   even when there is no on-disk object for an empty tree), which has
+   been corrected.
+   (merge f06ab027ef jk/virtual-objects-do-exist later to maint).
+
+ * The setup code has been cleaned up to avoid leaks around the
+   repository_format structure.
+   (merge e8805af1c3 ma/clear-repository-format later to maint).
+
+ * "git config --type=color ..." is meant to replace "git config --get-color"
+   but there is a slight difference that wasn't documented, which is
+   now fixed.
+   (merge cd8e7593b9 jk/config-type-color-ends-with-lf later to maint).
+
+ * When the "clean" filter can reduce the size of a huge file in the
+   working tree down to a small "token" (a la Git LFS), there is no
+   point in allocating a huge scratch area upfront, but the buffer is
+   sized based on the original file size.  The convert mechanism now
+   allocates very minimum and reallocates as it receives the output
+   from the clean filter process.
+   (merge 02156ab031 jh/resize-convert-scratch-buffer later to maint).
+
+ * "git rebase" uses the refs/rewritten/ hierarchy to store its
+   intermediate states, which inherently makes the hierarchy per
+   worktree, but it didn't quite work well.
+   (merge b9317d55a3 nd/rewritten-ref-is-per-worktree later to maint).
+
+ * "git log -L<from>,<to>:<path>" with "-s" did not suppress the patch
+   output as it should.  This has been corrected.
+   (merge 05314efaea jk/line-log-with-patch later to maint).
+
+ * "git worktree add" used to do a "find an available name with stat
+   and then mkdir", which is race-prone.  This has been fixed by using
+   mkdir and reacting to EEXIST in a loop.
+   (merge 7af01f2367 ms/worktree-add-atomic-mkdir later to maint).
+
+ * Build update for SHA-1 with collision detection.
+   (merge 07a20f569b jk/sha1dc later to maint).
+
+ * Code cleanup, docfix, build fix, etc.
+   (merge 11f470aee7 jc/test-yes-doc later to maint).
+   (merge 90503a240b js/doc-symref-in-proto-v1 later to maint).
+   (merge 5c326d1252 jk/unused-params later to maint).
+   (merge 68cabbfda3 dl/doc-submodule-wo-subcommand later to maint).
+   (merge 9903623761 ab/receive-pack-use-after-free-fix later to maint).
+   (merge 1ede45e44b en/merge-options-doc later to maint).
+   (merge 3e14dd2c8e rd/doc-hook-used-in-sample later to maint).
+   (merge c271dc28fd nd/no-more-check-racy later to maint).
+   (merge e6e15194a8 yb/utf-16le-bom-spellfix later to maint).
+   (merge bb101aaf0c rd/attr.c-comment-typofix later to maint).
+   (merge 716a5af812 rd/gc-prune-doc-fix later to maint).
+   (merge 50b206371d js/untravis-windows later to maint).
+   (merge dbf47215e3 js/rebase-recreate-merge later to maint).
+   (merge 56cb2d30f8 dl/reset-doc-no-wrt-abbrev later to maint).
+   (merge 64eca306a2 ja/dir-rename-doc-markup-fix later to maint).
+   (merge af91b0230c dl/ignore-docs later to maint).
+   (merge 59a06e947b ra/t3600-test-path-funcs later to maint).
+   (merge e041d0781b ar/t4150-remove-cruft later to maint).
index ec83b49..0089e0c 100644 (file)
@@ -11,12 +11,12 @@ module Git
       def process(parent, target, attrs)
         if parent.document.basebackend? 'html'
           prefix = parent.document.attr('git-relative-html-prefix')
-          %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>\n)
+          %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>)
         elsif parent.document.basebackend? 'docbook'
           "<citerefentry>\n" \
             "<refentrytitle>#{target}</refentrytitle>" \
             "<manvolnum>#{attrs[1]}</manvolnum>\n" \
-          "</citerefentry>\n"
+          "</citerefentry>"
         end
       end
     end
index 019d60e..8f4b3fa 100644 (file)
@@ -85,9 +85,9 @@ When `merges`, pass the `--rebase-merges` option to 'git rebase'
 so that the local merge commits are included in the rebase (see
 linkgit:git-rebase[1] for details).
 +
-When preserve, also pass `--preserve-merges` along to 'git rebase'
-so that locally committed merge commits will not be flattened
-by running 'git pull'.
+When `preserve` (deprecated in favor of `merges`), also pass
+`--preserve-merges` along to 'git rebase' so that locally committed merge
+commits will not be flattened by running 'git pull'.
 +
 When the value is `interactive`, the rebase is run in interactive mode.
 +
index e48bb98..2c4c9ba 100644 (file)
@@ -10,7 +10,7 @@ diff.autoRefreshIndex::
 
 diff.dirstat::
        A comma separated list of `--dirstat` parameters specifying the
-       default behavior of the `--dirstat` option to linkgit:git-diff[1]`
+       default behavior of the `--dirstat` option to linkgit:git-diff[1]
        and friends. The defaults can be overridden on the command line
        (using `--dirstat=<param1,param2,...>`). The fallback defaults
        (when not changed by `diff.dirstat`) are `changes,noncumulative,3`.
@@ -73,7 +73,7 @@ diff.external::
        environment variable.  The command is called with parameters
        as described under "git Diffs" in linkgit:git[1].  Note: if
        you want to use an external diff program only on a subset of
-       your files, you might want to use linkgit:gitattributes[5] instead.
+       your files, you might want to use linkgit:gitattributes[5] instead.
 
 diff.ignoreSubmodules::
        Sets the default value of --ignore-submodules. Note that this
index 879c5a2..450e8c3 100644 (file)
@@ -23,9 +23,9 @@ 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.
+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
index c6fbb8a..73c08b0 100644 (file)
@@ -19,7 +19,7 @@ gc.autoPackLimit::
        When there are more than this many packs that are not
        marked with `*.keep` file in the repository, `git gc
        --auto` consolidates them into one larger pack.  The
-       default value is 50.  Setting this to 0 disables it.
+       default value is 50.  Setting this to 0 disables it.
 
 gc.autoDetach::
        Make `git gc --auto` return immediately and run in background
index 590fe0d..f999f8e 100644 (file)
@@ -16,5 +16,5 @@ gpg.format::
 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
+       be used as a legacy synonym for `gpg.openpgp.program`. The default
        value for `gpg.x509.program` is "gpgsm".
index bb23a99..b87cab3 100644 (file)
@@ -18,9 +18,9 @@ When `merges`, pass the `--rebase-merges` option to 'git rebase'
 so that the local merge commits are included in the rebase (see
 linkgit:git-rebase[1] for details).
 +
-When preserve, also pass `--preserve-merges` along to 'git rebase'
-so that locally committed merge commits will not be flattened
-by running 'git pull'.
+When `preserve` (deprecated in favor of `merges`), also pass
+`--preserve-merges` along to 'git rebase' so that locally committed merge
+commits will not be flattened by running 'git pull'.
 +
 When the value is `interactive`, the rebase is run in interactive mode.
 +
index 331d250..d98e32d 100644 (file)
@@ -1,16 +1,9 @@
 rebase.useBuiltin::
-       Set to `false` to use the legacy shellscript implementation of
-       linkgit:git-rebase[1]. Is `true` by default, which means use
-       the built-in rewrite of it in C.
-+
-The C rewrite is first included with Git version 2.20. This option
-serves an an escape hatch to re-enable the legacy version in case any
-bugs are found in the rewrite. This option and the shellscript version
-of linkgit:git-rebase[1] will be removed in some future release.
-+
-If you find some reason to set this option to `false` other than
-one-off testing you should report the behavior difference as a bug in
-git.
+       Unused configuration variable. Used in Git versions 2.20 and
+       2.21 as an escape hatch to enable the legacy shellscript
+       implementation of rebase. Now the built-in rewrite of it in C
+       is always used. Setting this will emit a warning, to alert any
+       remaining users that setting this now does nothing.
 
 rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
index b5b2ba1..0557cbb 100644 (file)
@@ -1,12 +1,19 @@
-user.email::
-       Your email address to be recorded in any newly created commits.
-       Can be overridden by the `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_EMAIL`, and
-       `EMAIL` environment variables.  See linkgit:git-commit-tree[1].
-
 user.name::
-       Your full name to be recorded in any newly created commits.
-       Can be overridden by the `GIT_AUTHOR_NAME` and `GIT_COMMITTER_NAME`
-       environment variables.  See linkgit:git-commit-tree[1].
+user.email::
+author.name::
+author.email::
+committer.name::
+committer.email::
+       The `user.name` and `user.email` variables determine what ends
+       up in the `author` and `committer` field of commit
+       objects.
+       If you need the `author` or `committer` to be different, the
+       `author.name`, `author.email`, `committer.name` or
+       `committer.email` variables can be set.
+       Also, all of these can be overridden by the `GIT_AUTHOR_NAME`,
+       `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`,
+       `GIT_COMMITTER_EMAIL` and `EMAIL` environment variables.
+       See linkgit:git-commit-tree[1] for more information.
 
 user.useConfigOnly::
        Instruct Git to avoid trying to guess defaults for `user.email`
index cdcc17f..4d846d7 100644 (file)
@@ -95,12 +95,26 @@ from the format described above in the following way:
 . there are more "src" modes and "src" sha1
 . status is concatenated status characters for each parent
 . no optional "score" number
-. single path, only for "dst"
+. tab-separated pathname(s) of the file
 
-Example:
+For `-c` and `--cc`, only the destination or final path is shown even
+if the file was renamed on any side of history.  With
+`--combined-all-paths`, the name of the path in each parent is shown
+followed by the name of the path in the merge commit.
+
+Examples for `-c` and `--cc` without `--combined-all-paths`:
+------------------------------------------------
+::100644 100644 100644 fabadb8 cc95eb0 4866510 MM      desc.c
+::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM      bar.sh
+::100644 100644 100644 e07d6c5 9042e82 ee91881 RR      phooey.c
+------------------------------------------------
+
+Examples when `--combined-all-paths` added to either `-c` or `--cc`:
 
 ------------------------------------------------
-::100644 100644 100644 fabadb8 cc95eb0 4866510 MM      describe.c
+::100644 100644 100644 fabadb8 cc95eb0 4866510 MM      desc.c  desc.c  desc.c
+::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM      foo.sh  bar.sh  bar.sh
+::100644 100644 100644 e07d6c5 9042e82 ee91881 RR      fooey.c fuey.c  phooey.c
 ------------------------------------------------
 
 Note that 'combined diff' lists only files which were modified from
index 231105c..f10ca41 100644 (file)
@@ -143,6 +143,19 @@ copying detection) are designed to work with diff of two
 Similar to two-line header for traditional 'unified' diff
 format, `/dev/null` is used to signal created or deleted
 files.
++
+However, if the --combined-all-paths option is provided, instead of a
+two-line from-file/to-file you get a N+1 line from-file/to-file header,
+where N is the number of parents in the merge commit
+
+       --- a/file
+       --- a/file
+       --- a/file
+       +++ b/file
++
+This extended format can be useful if rename or copy detection is
+active, to allow you to see the original name of the file in different
+parents.
 
 4.   Chunk header format is modified to prevent people from
      accidentally feeding it to `patch -p1`. Combined diff format
index 554a340..09faee3 100644 (file)
@@ -36,11 +36,21 @@ endif::git-format-patch[]
 -U<n>::
 --unified=<n>::
        Generate diffs with <n> lines of context instead of
-       the usual three.
+       the usual three. Implies `--patch`.
 ifndef::git-format-patch[]
        Implies `-p`.
 endif::git-format-patch[]
 
+--output=<file>::
+       Output to a specific file instead of stdout.
+
+--output-indicator-new=<char>::
+--output-indicator-old=<char>::
+--output-indicator-context=<char>::
+       Specify the character used to indicate new, old or context
+       lines in the generated patch. Normally they are '+', '-' and
+       ' ' respectively.
+
 ifndef::git-format-patch[]
 --raw::
 ifndef::git-log[]
@@ -148,6 +158,7 @@ These parameters can also be set individually with `--stat-width=<width>`,
        number of modified files, as well as number of added and deleted
        lines.
 
+-X[<param1,param2,...>]::
 --dirstat[=<param1,param2,...>]::
        Output the distribution of relative amount of changes for each
        sub-directory. The behavior of `--dirstat` can be customized by
@@ -192,6 +203,12 @@ directories with less than 10% of the total amount of changed files,
 and accumulating child directory counts in the parent directories:
 `--dirstat=files,10,cumulative`.
 
+--cumulative::
+       Synonym for --dirstat=cumulative
+
+--dirstat-by-file[=<param1,param2>...]::
+       Synonym for --dirstat=files,param1,param2...
+
 --summary::
        Output a condensed summary of extended header information
        such as creations, renames and mode changes.
@@ -386,6 +403,9 @@ endif::git-format-patch[]
        Turn off rename detection, even when the configuration
        file gives the default to do so.
 
+--[no-]rename-empty::
+       Whether to use empty blobs as rename source.
+
 ifndef::git-format-patch[]
 --check::
        Warn if changes introduce conflict markers or whitespace errors.
@@ -416,7 +436,7 @@ endif::git-format-patch[]
 
 --binary::
        In addition to `--full-index`, output a binary diff that
-       can be applied with `git-apply`.
+       can be applied with `git-apply`. Implies `--patch`.
 
 --abbrev[=<n>]::
        Instead of showing the full 40-byte hexadecimal object
index 32c83dd..3355be4 100755 (executable)
@@ -12,9 +12,16 @@ 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
+j=n                    parallel argument to pass to make
+f                      force rebuild; do not rely on cached results
+c,clean                        cleanup temporary working files
+from-asciidoc          use asciidoc with the 'from'-commit
+from-asciidoctor       use asciidoctor with the 'from'-commit
+asciidoc               use asciidoc with both commits
+to-asciidoc            use asciidoc with the 'to'-commit
+to-asciidoctor         use asciidoctor with the 'to'-commit
+asciidoctor            use asciidoctor with both commits
+cut-header-footer      cut away header and footer
 "
 SUBDIRECTORY_OK=1
 . "$(git --exec-path)/git-sh-setup"
@@ -22,6 +29,9 @@ SUBDIRECTORY_OK=1
 parallel=
 force=
 clean=
+from_program=
+to_program=
+cut_header_footer=
 while test $# -gt 0
 do
        case "$1" in
@@ -31,6 +41,22 @@ do
                clean=t ;;
        -f)
                force=t ;;
+       --from-asciidoctor)
+               from_program=-asciidoctor ;;
+       --to-asciidoctor)
+               to_program=-asciidoctor ;;
+       --asciidoctor)
+               from_program=-asciidoctor
+               to_program=-asciidoctor ;;
+       --from-asciidoc)
+               from_program=-asciidoc ;;
+       --to-asciidoc)
+               to_program=-asciidoc ;;
+       --asciidoc)
+               from_program=-asciidoc
+               to_program=-asciidoc ;;
+       --cut-header-footer)
+               cut_header_footer=-cut-header-footer ;;
        --)
                shift; break ;;
        *)
@@ -79,6 +105,22 @@ then
        ln -s "$dots/config.mak" "$tmp/worktree/config.mak"
 fi
 
+construct_makemanflags () {
+       if test "$1" = "-asciidoc"
+       then
+               echo USE_ASCIIDOCTOR=
+       elif test "$1" = "-asciidoctor"
+       then
+               echo USE_ASCIIDOCTOR=YesPlease
+       fi
+}
+
+from_makemanflags=$(construct_makemanflags "$from_program") &&
+to_makemanflags=$(construct_makemanflags "$to_program") &&
+
+from_dir=$from_oid$from_program$cut_header_footer &&
+to_dir=$to_oid$to_program$cut_header_footer &&
+
 # generate_render_makefile <srcdir> <dstdir>
 generate_render_makefile () {
        find "$1" -type f |
@@ -94,7 +136,7 @@ generate_render_makefile () {
        done
 }
 
-# render_tree <committish_oid>
+# render_tree <committish_oid> <directory_name> <makemanflags>
 render_tree () {
        # Skip install-man entirely if we already have an installed directory.
        # We can't rely on make here, since "install-man" unconditionally
@@ -102,28 +144,44 @@ render_tree () {
        # 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"
+       oid=$1 &&
+       dname=$2 &&
+       makemanflags=$3 &&
+       if ! test -d "$tmp/installed/$dname"
        then
-               git -C "$tmp/worktree" checkout --detach "$1" &&
+               git -C "$tmp/worktree" checkout --detach "$oid" &&
                make -j$parallel -C "$tmp/worktree" \
+                       $makemanflags \
                        GIT_VERSION=omitted \
                        SOURCE_DATE_EPOCH=0 \
-                       DESTDIR="$tmp/installed/$1+" \
+                       DESTDIR="$tmp/installed/$dname+" \
                        install-man &&
-               mv "$tmp/installed/$1+" "$tmp/installed/$1"
+               mv "$tmp/installed/$dname+" "$tmp/installed/$dname"
        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"
+       if ! test -d "$tmp/rendered/$dname"
        then
-               generate_render_makefile "$tmp/installed/$1" "$tmp/rendered/$1+" |
+               generate_render_makefile "$tmp/installed/$dname" \
+                       "$tmp/rendered/$dname+" |
                make -j$parallel -f - &&
-               mv "$tmp/rendered/$1+" "$tmp/rendered/$1"
+               mv "$tmp/rendered/$dname+" "$tmp/rendered/$dname"
+
+               if test "$cut_header_footer" = "-cut-header-footer"
+               then
+                       for f in $(find "$tmp/rendered/$dname" -type f)
+                       do
+                               tail -n +3 "$f" | head -n -2 |
+                               sed -e '1{/^$/d}' -e '${/^$/d}' >"$f+" &&
+                               mv "$f+" "$f" ||
+                               return 1
+                       done
+               fi
        fi
 }
 
-render_tree $from_oid &&
-render_tree $to_oid &&
-git -C $tmp/rendered diff --no-index "$@" $from_oid $to_oid
+render_tree $from_oid $from_dir $from_makemanflags &&
+render_tree $to_oid $to_dir $to_makemanflags &&
+git -C $tmp/rendered diff --no-index "$@" $from_dir $to_dir
index 37bcab9..8b0e4c7 100644 (file)
@@ -193,15 +193,6 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files.
        for command-line options).
 
 
-CONFIGURATION
--------------
-
-The optional configuration variable `core.excludesFile` indicates a path to a
-file containing patterns of file names to exclude from git-add, similar to
-$GIT_DIR/info/exclude.  Patterns in the exclude file are used in addition to
-those in info/exclude.  See linkgit:gitignore[5].
-
-
 EXAMPLES
 --------
 
index 6f6c34b..fc3b993 100644 (file)
@@ -99,6 +99,11 @@ default.   You can use `--no-utf8` to override this.
        am.threeWay configuration variable. For more information,
        see am.threeWay in linkgit:git-config[1].
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 --ignore-space-change::
 --ignore-whitespace::
 --whitespace=<option>::
index 3bd83a7..0cd87dd 100644 (file)
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git branch' [--color[=<when>] | --no-color] [-r | -a]
-       [--list] [-v [--abbrev=<length> | --no-abbrev]]
+       [--list] [--show-current] [-v [--abbrev=<length> | --no-abbrev]]
        [--column[=<options>] | --no-column] [--sort=<key>]
        [(--merged | --no-merged) [<commit>]]
        [--contains [<commit]] [--no-contains [<commit>]]
@@ -160,6 +160,10 @@ This option is only applicable in non-verbose mode.
        branch --list 'maint-*'`, list only the branches that match
        the pattern(s).
 
+--show-current::
+       Print the name of the current branch. In detached HEAD state,
+       nothing is printed.
+
 -v::
 -vv::
 --verbose::
index 3ea4579..877e5f5 100644 (file)
@@ -262,6 +262,9 @@ When switching branches with `--merge`, staged changes may be lost.
 This means that you can use `git checkout -p` to selectively discard
 edits from your current working tree. See the ``Interactive Mode''
 section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
++
+Note that this option uses the no overlay mode by default (see also
+`--[no-]overlay`), and currently doesn't support overlay mode.
 
 --ignore-other-worktrees::
        `git checkout` refuses when the wanted ref is already checked
@@ -282,6 +285,13 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
        Do not attempt to create a branch if a remote tracking branch
        of the same name exists.
 
+--[no-]overlay::
+       In the default overlay mode, `git checkout` never
+       removes files from the index or the working tree.  When
+       specifying `--no-overlay`, files that appear in the index and
+       working tree, but not in <tree-ish> are removed, to make them
+       match <tree-ish> exactly.
+
 <branch>::
        Branch to checkout; if it refers to a branch (i.e., a name that,
        when prepended with "refs/heads/", is a valid ref), then that
index b8cfeec..d64e724 100644 (file)
@@ -148,6 +148,11 @@ effect to your index in a row.
        Pass the merge strategy-specific option through to the
        merge strategy.  See linkgit:git-merge[1] for details.
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 SEQUENCER SUBCOMMANDS
 ---------------------
 include::sequencer.txt[]
index 03056da..db876f7 100644 (file)
@@ -55,14 +55,13 @@ OPTIONS
 
 -e <pattern>::
 --exclude=<pattern>::
-       In addition to those found in .gitignore (per directory) and
-       $GIT_DIR/info/exclude, also consider these patterns to be in the
-       set of the ignore rules in effect.
+       Use the given exclude pattern in addition to the standard ignore rules
+       (see linkgit:gitignore[5]).
 
 -x::
-       Don't use the standard ignore rules read from .gitignore (per
-       directory) and $GIT_DIR/info/exclude, but do still use the ignore
-       rules given with `-e` options.  This allows removing all untracked
+       Don't use the standard ignore rules (see linkgit:gitignore[5]), but
+       still use the ignore rules given with `-e` options from the command
+       line.  This allows removing all untracked
        files, including build products.  This can be used (possibly in
        conjunction with 'git reset') to create a pristine
        working directory to test a clean build.
index 002dae6..4b90b9c 100644 (file)
@@ -23,6 +23,10 @@ Creates a new commit object based on the provided tree object and
 emits the new commit object id on stdout. The log message is read
 from the standard input, unless `-m` or `-F` options are given.
 
+The `-m` and `-F` options can be given any number of times, in any
+order. The commit log message will be composed in the order in which
+the options are given.
+
 A commit object may have any number of parents. With exactly one
 parent, it is an ordinary commit. Having more than one parent makes
 the commit a merge between several lines of history. Initial (root)
@@ -41,7 +45,7 @@ state was.
 OPTIONS
 -------
 <tree>::
-       An existing tree object
+       An existing tree object.
 
 -p <parent>::
        Each `-p` indicates the id of a parent commit object.
@@ -52,7 +56,8 @@ OPTIONS
 
 -F <file>::
        Read the commit log message from the given file. Use `-` to read
-       from the standard input.
+       from the standard input. This can be given more than once and the
+       content of each file becomes its own paragraph.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
index 1bfe9f5..ff9310f 100644 (file)
@@ -126,7 +126,7 @@ See also <<FILES>>.
 
 --local::
        For writing options: write to the repository `.git/config` file.
-       This is the default behavior.
+       This is the default behavior.
 +
 For reading options: read only from the repository `.git/config` rather than
 from all available files.
@@ -240,7 +240,9 @@ Valid `<type>`'s include:
        output.  The optional `default` parameter is used instead, if
        there is no color configured for `name`.
 +
-`--type=color [--default=<default>]` is preferred over `--get-color`.
+`--type=color [--default=<default>]` is preferred over `--get-color`
+(but note that `--get-color` will omit the trailing newline printed by
+`--type=color`).
 
 -e::
 --edit::
index 43daa7c..24f32e8 100644 (file)
@@ -10,8 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
-             [-t] [-r] [-c | --cc] [--root] [<common diff options>]
-             <tree-ish> [<tree-ish>] [<path>...]
+             [-t] [-r] [-c | --cc] [--combined-all-paths] [--root]
+             [<common diff options>] <tree-ish> [<tree-ish>] [<path>...]
 
 DESCRIPTION
 -----------
@@ -105,6 +105,13 @@ include::pretty-options.txt[]
        itself and the commit log message is not shown, just like in any other
        "empty diff" case.
 
+--combined-all-paths::
+       This flag causes combined diffs (used for merge commits) to
+       list the name of the file from all parents.  It thus only has
+       effect when -c or --cc are specified, and is likely only
+       useful if filename changes are detected (i.e. when either
+       rename or copy detection have been requested).
+
 --always::
        Show the commit itself and the commit log message even
        if the diff itself is empty.
index 55950d9..e0eae64 100644 (file)
@@ -62,9 +62,17 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs
        with --no-full.
 
 --connectivity-only::
-       Check only the connectivity of tags, commits and tree objects. By
-       avoiding to unpack blobs, this speeds up the operation, at the
-       expense of missing corrupt objects or other problematic issues.
+       Check only the connectivity of reachable objects, making sure
+       that any objects referenced by a reachable tag, commit, or tree
+       is present. This speeds up the operation by avoiding reading
+       blobs entirely (though it does still check that referenced blobs
+       exist). This will detect corruption in commits and trees, but
+       not do any semantic checks (e.g., for format errors). Corruption
+       in blob objects will not be detected at all.
++
+Unreachable tags, commits, and trees will also be accessed to find the
+tips of dangling segments of history. Use `--no-dangling` if you don't
+care about this output and want to speed it up further.
 
 --strict::
        Enable more strict checking, namely to catch a file mode
index a744249..a7c1b0f 100644 (file)
@@ -76,7 +76,7 @@ be performed as well.
 --prune=<date>::
        Prune loose objects older than date (default is 2 weeks ago,
        overridable by the config variable `gc.pruneExpire`).
-       --prune=all prunes loose objects regardless of their age and
+       --prune=now prunes loose objects regardless of their age and
        increases the risk of corruption if another process is writing to
        the repository concurrently; see "NOTES" below. --prune is on by
        default.
index 84fe236..2d27969 100644 (file)
@@ -88,7 +88,7 @@ OPTIONS
        mechanism. Only useful with `--untracked`.
 
 --exclude-standard::
-       Do not pay attention to ignored files specified via the `.gitignore`
+       Do not pay attention to ignored files specified via the `.gitignore`
        mechanism.  Only useful when searching files in the current directory
        with `--no-index`.
 
index bb0db19..558966a 100644 (file)
@@ -162,7 +162,7 @@ ScriptAliasMatch ^/git/[^/]*(.*) /usr/libexec/git-core/git-http-backend/storage.
 
 Accelerated static Apache 2.x::
        Similar to the above, but Apache can be used to return static
-       files that are stored on disk.  On many systems this may
+       files that are stored on disk.  On many systems this may
        be more efficient as Apache can ask the kernel to copy the
        file contents from the file system directly to the network:
 +
index b9fd377..0b057cb 100644 (file)
@@ -31,7 +31,7 @@ OPTIONS
        displayed.
 
 --refs::
-       Do not show peeled tags or pseudorefs like HEAD in the output.
+       Do not show peeled tags or pseudorefs like `HEAD` in the output.
 
 -q::
 --quiet::
index 4cc8646..6294dbc 100644 (file)
@@ -83,7 +83,8 @@ invocations. The automated message can include the branch description.
 If `--log` is specified, a shortlog of the commits being merged
 will be appended to the specified message.
 
---[no-]rerere-autoupdate::
+--rerere-autoupdate::
+--no-rerere-autoupdate::
        Allow the rerere mechanism to update the index with the
        result of auto-conflict resolution if possible.
 
index df2b64d..f56a5a9 100644 (file)
@@ -146,7 +146,7 @@ OPTIONS
 
 -C <object>::
 --reuse-message=<object>::
-       Take the given blob object (for example, another note) as the
+       Take the given blob object (for example, another note) as the
        note message. (Use `git notes copy <object>` instead to
        copy notes between objects.)
 
index 5629ba4..f5e6ae3 100644 (file)
@@ -300,6 +300,11 @@ See also INCOMPATIBLE OPTIONS below.
 +
 See also INCOMPATIBLE OPTIONS below.
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
        GPG-sign commits. The `keyid` argument is optional and
@@ -410,14 +415,14 @@ See also INCOMPATIBLE OPTIONS below.
 +
 By default, or when `no-rebase-cousins` was specified, commits which do not
 have `<upstream>` as direct ancestor will keep their original branch point,
-i.e. commits that would be excluded by gitlink:git-log[1]'s
+i.e. commits that would be excluded by linkgit:git-log[1]'s
 `--ancestry-path` option will keep their original ancestry by default. If
 the `rebase-cousins` mode is turned on, such commits are instead rebased
 onto `<upstream>` (or `<onto>`, if specified).
 +
-The `--rebase-merges` mode is similar in spirit to `--preserve-merges`, but
-in contrast to that option works well in interactive rebases: commits can be
-reordered, inserted and dropped at will.
+The `--rebase-merges` mode is similar in spirit to the deprecated
+`--preserve-merges`, but in contrast to that option works well in interactive
+rebases: commits can be reordered, inserted and dropped at will.
 +
 It is currently only possible to recreate the merge commits using the
 `recursive` merge strategy; Different merge strategies can be used only via
@@ -427,9 +432,10 @@ See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
 
 -p::
 --preserve-merges::
-       Recreate merge commits instead of flattening the history by replaying
-       commits a merge commit introduces. Merge conflict resolutions or manual
-       amendments to merge commits are not preserved.
+       [DEPRECATED: use `--rebase-merges` instead] Recreate merge commits
+       instead of flattening the history by replaying commits a merge commit
+       introduces. Merge conflict resolutions or manual amendments to merge
+       commits are not preserved.
 +
 This uses the `--interactive` machinery internally, but combining it
 with the `--interactive` option explicitly is generally not a good
@@ -1020,11 +1026,11 @@ merge cmake
 
 BUGS
 ----
-The todo list presented by `--preserve-merges --interactive` does not
-represent the topology of the revision graph.  Editing commits and
-rewording their commit messages should work fine, but attempts to
-reorder commits tend to produce counterintuitive results. Use
-`--rebase-merges` in such scenarios instead.
+The todo list presented by the deprecated `--preserve-merges --interactive`
+does not represent the topology of the revision graph (use `--rebase-merges`
+instead).  Editing commits and rewording their commit messages should work
+fine, but attempts to reorder commits tend to produce counterintuitive results.
+Use `--rebase-merges` in such scenarios instead.
 
 For example, an attempt to rearrange
 ------------
index 132f8e5..26e746c 100644 (file)
@@ -428,8 +428,8 @@ working index HEAD target         working index HEAD
 
 `reset --merge` is meant to be used when resetting out of a conflicted
 merge. Any mergy operation guarantees that the working tree file that is
-involved in the merge does not have local change wrt the index before
-it starts, and that it writes the result out to the working tree. So if
+involved in the merge does not have a local change with respect to the index
+before it starts, and that it writes the result out to the working tree. So if
 we see some difference between the index and the target and also
 between the index and the working tree, then it means that we are not
 resetting out from a state that a mergy operation left after failing
index 837707a..6afccb2 100644 (file)
@@ -101,6 +101,11 @@ effect to your index in a row.
        Pass the merge strategy-specific option through to the
        merge strategy.  See linkgit:git-merge[1] for details.
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 SEQUENCER SUBCOMMANDS
 ---------------------
 include::sequencer.txt[]
index ba3c4df..2794e29 100644 (file)
@@ -9,6 +9,7 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
+'git submodule' [--quiet] [--cached]
 'git submodule' [--quiet] add [<options>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
@@ -28,6 +29,9 @@ For more information about submodules, see linkgit:gitsubmodules[7].
 
 COMMANDS
 --------
+With no arguments, shows the status of existing submodules.  Several
+subcommands are available to perform operations on the submodules.
+
 add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]::
        Add the given repository as a submodule at the given path
        to the changeset to be committed next to the current
index b990295..223788f 100644 (file)
@@ -126,7 +126,7 @@ your Perl's Getopt::Long is < v2.37).
        command-line argument.
 +
 This automatically updates the rev_map if needed (see
-'$GIT_DIR/svn/\*\*/.rev_map.*' in the FILES section below for details).
+'$GIT_DIR/svn/\**/.rev_map.*' in the FILES section below for details).
 
 --localtime;;
        Store Git commit times in the local time zone instead of UTC.  This
@@ -239,7 +239,7 @@ Like 'git rebase'; this requires that the working tree be clean
 and have no uncommitted changes.
 +
 This automatically updates the rev_map if needed (see
-'$GIT_DIR/svn/\*\*/.rev_map.*' in the FILES section below for details).
+'$GIT_DIR/svn/\**/.rev_map.*' in the FILES section below for details).
 
 -l;;
 --local;;
@@ -524,7 +524,7 @@ This will set the property 'svn:keywords' to 'FreeBSD=%H' for the file
        way to repair the repo is to use 'reset'.
 +
 Only the rev_map and refs/remotes/git-svn are changed (see
-'$GIT_DIR/svn/\*\*/.rev_map.*' in the FILES section below for details).
+'$GIT_DIR/svn/\**/.rev_map.*' in the FILES section below for details).
 Follow 'reset' with a 'fetch' and then 'git reset' or 'git rebase' to
 move local branches onto the new tree.
 
@@ -760,7 +760,7 @@ svn-remote.<name>.noMetadata::
 +
 This option can only be used for one-shot imports as 'git svn'
 will not be able to fetch again without metadata. Additionally,
-if you lose your '$GIT_DIR/svn/\*\*/.rev_map.*' files, 'git svn' will not
+if you lose your '$GIT_DIR/svn/\**/.rev_map.*' files, 'git svn' will not
 be able to rebuild them.
 +
 The 'git svn log' command will not work on repositories using
@@ -1154,7 +1154,7 @@ fetching, then $GIT_DIR/svn/.metadata must be manually edited to remove
 
 FILES
 -----
-$GIT_DIR/svn/\*\*/.rev_map.*::
+$GIT_DIR/svn/\**/.rev_map.*::
        Mapping between Subversion revision numbers and Git commit
        names.  In a repository where the noMetadata option is not set,
        this can be rebuilt from the git-svn-id: lines that are at the
index cb86318..85d92c9 100644 (file)
@@ -213,7 +213,7 @@ refs of one working tree from another.
 
 In general, all pseudo refs are per working tree and all refs starting
 with "refs/" are shared. Pseudo refs are ones like HEAD which are
-directly under GIT_DIR instead of inside GIT_DIR/refs. There are one
+directly under GIT_DIR instead of inside GIT_DIR/refs. There is one
 exception to this: refs inside refs/bisect and refs/worktree is not
 shared.
 
index 00156d6..6d1f2fd 100644 (file)
@@ -536,7 +536,6 @@ other
        The command-line parameters passed to the configured command are
        determined by the ssh variant.  See `ssh.variant` option in
        linkgit:git-config[1] for details.
-
 +
 `$GIT_SSH_COMMAND` takes precedence over `$GIT_SSH`, and is interpreted
 by the shell, which allows additional arguments to be included.
index 9b41f81..4fb20cd 100644 (file)
@@ -18,7 +18,7 @@ A `gitattributes` file is a simple text file that gives
 
 Each line in `gitattributes` file is of form:
 
-       pattern attr1 attr2 ...
+       pattern attr1 attr2 ...
 
 That is, a pattern followed by an attributes list,
 separated by whitespaces. Leading and trailing whitespaces are
@@ -314,8 +314,8 @@ stored as UTF-8 internally. A client without `working-tree-encoding`
 support will checkout `foo.ps1` as UTF-8 encoded file. This will
 typically cause trouble for the users of this file.
 +
-If a Git client, that does not support the `working-tree-encoding`
-attribute, adds a new file `bar.ps1`, then `bar.ps1` will be
+If a Git client that does not support the `working-tree-encoding`
+attribute adds a new file `bar.ps1`, then `bar.ps1` will be
 stored "as-is" internally (in this example probably as UTF-16).
 A client with `working-tree-encoding` support will interpret the
 internal contents as UTF-8 and try to convert it to UTF-16 on checkout.
@@ -346,7 +346,7 @@ automatic line ending conversion based on your platform.
 
 Use the following attributes if your '*.ps1' files are UTF-16 little
 endian encoded without BOM and you want Git to use Windows line endings
-in the working directory (use `UTF-16-LE-BOM` instead of `UTF-16LE` if
+in the working directory (use `UTF-16LE-BOM` instead of `UTF-16LE` if
 you want UTF-16 little endian with BOM).
 Please note, it is highly recommended to
 explicitly define the line endings with `eol` if the `working-tree-encoding`
index 9590443..5bf653c 100644 (file)
@@ -99,6 +99,10 @@ All the `git commit` hooks are invoked with the environment
 variable `GIT_EDITOR=:` if the command will not bring up an editor
 to modify the commit message.
 
+The default 'pre-commit' hook, when enabled--and with the
+`hooks.allownonascii` config option unset or set to false--prevents
+the use of non-ASCII filenames.
+
 prepare-commit-msg
 ~~~~~~~~~~~~~~~~~~
 
index 1c94f08..b5bc9db 100644 (file)
@@ -132,6 +132,14 @@ full pathname may have special meaning:
  - Other consecutive asterisks are considered regular asterisks and
    will match according to the previous rules.
 
+CONFIGURATION
+-------------
+
+The optional configuration variable `core.excludesFile` indicates a path to a
+file containing patterns of file names to exclude, similar to
+`$GIT_DIR/info/exclude`.  Patterns in the exclude file are used in addition to
+those in `$GIT_DIR/info/exclude`.
+
 NOTES
 -----
 
index 9d1459a..4f2905d 100644 (file)
@@ -468,7 +468,7 @@ set by Git if the remote helper has the 'option' capability.
 
 'option dry-run' {'true'|'false'}:
        If true, pretend the operation completed successfully,
-       but don't actually change any repository data.  For most
+       but don't actually change any repository data.  For most
        helpers this only applies to the 'push', if supported.
 
 'option servpath <c-style-quoted-path>'::
index 92535db..b284953 100644 (file)
@@ -536,7 +536,7 @@ $omit_owner::
 
 $per_request_config::
        If this is set to code reference, it will be run once for each request.
-       You can set parts of configuration that change per session this way.
+       You can set parts of configuration that change per session this way.
        For example, one might use the following code in a gitweb configuration
        file
 +
index 023ca95..8d38ae6 100644 (file)
@@ -287,6 +287,15 @@ This commit is referred to as a "merge commit", or sometimes just a
        origin/name-of-upstream-branch, which you can see using
        `git branch -r`.
 
+[[def_overlay]]overlay::
+       Only update and add files to the working directory, but don't
+       delete them, similar to how 'cp -R' would update the contents
+       in the destination directory.  This is the default mode in a
+       <<def_checkout,checkout>> when checking out files from the
+       <<def_index,index>> or a <<def_tree-ish,tree-ish>>.  In
+       contrast, no-overlay mode also deletes tracked files not
+       present in the source, similar to 'rsync --delete'.
+
 [[def_pack]]pack::
        A set of objects which have been compressed into one file (to save space
        or to transmit them efficiently).
index 63a3fc0..92a7d93 100644 (file)
@@ -3,9 +3,14 @@
        Perform the merge and commit the result. This option can
        be used to override --no-commit.
 +
-With --no-commit perform the merge but pretend the merge
-failed and do not autocommit, to give the user a chance to
-inspect and further tweak the merge result before committing.
+With --no-commit perform the merge and stop just before creating
+a merge commit, to give the user a chance to inspect and further
+tweak the merge result before committing.
++
+Note that fast-forward updates do not create a merge commit and
+therefore there is no way to stop those merges with --no-commit.
+Thus, if you want to ensure your branch is not changed or updated
+by the merge command, use --no-ff with --no-commit.
 
 --edit::
 -e::
index 7bfffae..0795983 100644 (file)
@@ -102,120 +102,160 @@ The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
 +
 The placeholders are:
 
-- '%H': commit hash
-- '%h': abbreviated commit hash
-- '%T': tree hash
-- '%t': abbreviated tree hash
-- '%P': parent hashes
-- '%p': abbreviated parent hashes
-- '%an': author name
-- '%aN': author name (respecting .mailmap, see linkgit:git-shortlog[1]
-  or linkgit:git-blame[1])
-- '%ae': author email
-- '%aE': author email (respecting .mailmap, see
-  linkgit:git-shortlog[1] or linkgit:git-blame[1])
-- '%ad': author date (format respects --date= option)
-- '%aD': author date, RFC2822 style
-- '%ar': author date, relative
-- '%at': author date, UNIX timestamp
-- '%ai': author date, ISO 8601-like format
-- '%aI': author date, strict ISO 8601 format
-- '%cn': committer name
-- '%cN': committer name (respecting .mailmap, see
-  linkgit:git-shortlog[1] or linkgit:git-blame[1])
-- '%ce': committer email
-- '%cE': committer email (respecting .mailmap, see
-  linkgit:git-shortlog[1] or linkgit:git-blame[1])
-- '%cd': committer date (format respects --date= option)
-- '%cD': committer date, RFC2822 style
-- '%cr': committer date, relative
-- '%ct': committer date, UNIX timestamp
-- '%ci': committer date, ISO 8601-like format
-- '%cI': committer date, strict ISO 8601 format
-- '%d': ref names, like the --decorate option of linkgit:git-log[1]
-- '%D': ref names without the " (", ")" wrapping.
-- '%S': ref name given on the command line by which the commit was reached
-  (like `git log --source`), only works with `git log`
-- '%e': encoding
-- '%s': subject
-- '%f': sanitized subject line, suitable for a filename
-- '%b': body
-- '%B': raw body (unwrapped subject and body)
+- Placeholders that expand to a single literal character:
+'%n':: newline
+'%%':: a raw '%'
+'%x00':: print a byte from a hex code
+
+- Placeholders that affect formatting of later placeholders:
+'%Cred':: switch color to red
+'%Cgreen':: switch color to green
+'%Cblue':: switch color to blue
+'%Creset':: reset color
+'%C(...)':: color specification, as described under Values in the
+           "CONFIGURATION FILE" section of linkgit:git-config[1].  By
+           default, colors are shown only when enabled for log output
+           (by `color.diff`, `color.ui`, or `--color`, and respecting
+           the `auto` settings of the former if we are going to a
+           terminal). `%C(auto,...)` is accepted as a historical
+           synonym for the default (e.g., `%C(auto,red)`). Specifying
+           `%C(always,...)` will show the colors even when color is
+           not otherwise enabled (though consider just using
+           `--color=always` to enable color for the whole output,
+           including this format and anything else git might color).
+           `auto` alone (i.e. `%C(auto)`) will turn on auto coloring
+           on the next placeholders until the color is switched
+           again.
+'%m':: left (`<`), right (`>`) or boundary (`-`) mark
+'%w([<w>[,<i1>[,<i2>]]])':: switch line wrapping, like the -w option of
+                           linkgit:git-shortlog[1].
+'%<(<N>[,trunc|ltrunc|mtrunc])':: make the next placeholder take at
+                                 least N columns, padding spaces on
+                                 the right if necessary.  Optionally
+                                 truncate at the beginning (ltrunc),
+                                 the middle (mtrunc) or the end
+                                 (trunc) if the output is longer than
+                                 N columns.  Note that truncating
+                                 only works correctly with N >= 2.
+'%<|(<N>)':: make the next placeholder take at least until Nth
+            columns, padding spaces on the right if necessary
+'%>(<N>)', '%>|(<N>)':: similar to '%<(<N>)', '%<|(<N>)' respectively,
+                       but padding spaces on the left
+'%>>(<N>)', '%>>|(<N>)':: similar to '%>(<N>)', '%>|(<N>)'
+                         respectively, except that if the next
+                         placeholder takes more spaces than given and
+                         there are spaces on its left, use those
+                         spaces
+'%><(<N>)', '%><|(<N>)':: similar to '%<(<N>)', '%<|(<N>)'
+                         respectively, but padding both sides
+                         (i.e. the text is centered)
+
+- Placeholders that expand to information extracted from the commit:
+'%H':: commit hash
+'%h':: abbreviated commit hash
+'%T':: tree hash
+'%t':: abbreviated tree hash
+'%P':: parent hashes
+'%p':: abbreviated parent hashes
+'%an':: author name
+'%aN':: author name (respecting .mailmap, see linkgit:git-shortlog[1]
+       or linkgit:git-blame[1])
+'%ae':: author email
+'%aE':: author email (respecting .mailmap, see linkgit:git-shortlog[1]
+       or linkgit:git-blame[1])
+'%ad':: author date (format respects --date= option)
+'%aD':: author date, RFC2822 style
+'%ar':: author date, relative
+'%at':: author date, UNIX timestamp
+'%ai':: author date, ISO 8601-like format
+'%aI':: author date, strict ISO 8601 format
+'%cn':: committer name
+'%cN':: committer name (respecting .mailmap, see
+       linkgit:git-shortlog[1] or linkgit:git-blame[1])
+'%ce':: committer email
+'%cE':: committer email (respecting .mailmap, see
+       linkgit:git-shortlog[1] or linkgit:git-blame[1])
+'%cd':: committer date (format respects --date= option)
+'%cD':: committer date, RFC2822 style
+'%cr':: committer date, relative
+'%ct':: committer date, UNIX timestamp
+'%ci':: committer date, ISO 8601-like format
+'%cI':: committer date, strict ISO 8601 format
+'%d':: ref names, like the --decorate option of linkgit:git-log[1]
+'%D':: ref names without the " (", ")" wrapping.
+'%S':: ref name given on the command line by which the commit was reached
+       (like `git log --source`), only works with `git log`
+'%e':: encoding
+'%s':: subject
+'%f':: sanitized subject line, suitable for a filename
+'%b':: body
+'%B':: raw body (unwrapped subject and body)
 ifndef::git-rev-list[]
-- '%N': commit notes
+'%N':: commit notes
 endif::git-rev-list[]
-- '%GG': raw verification message from GPG for a signed commit
-- '%G?': show "G" for a good (valid) signature,
-  "B" for a bad signature,
-  "U" for a good signature with unknown validity,
-  "X" for a good signature that has expired,
-  "Y" for a good signature made by an expired key,
-  "R" for a good signature made by a revoked key,
-  "E" if the signature cannot be checked (e.g. missing key)
-  and "N" for no signature
-- '%GS': show the name of the signer for a signed commit
-- '%GK': show the key used to sign a signed commit
-- '%GF': show the fingerprint of the key used to sign a signed commit
-- '%GP': show the fingerprint of the primary key whose subkey was used
-  to sign a signed commit
-- '%gD': reflog selector, e.g., `refs/stash@{1}` or
-  `refs/stash@{2 minutes ago`}; the format follows the rules described
-  for the `-g` option. The portion before the `@` is the refname as
-  given on the command line (so `git log -g refs/heads/master` would
-  yield `refs/heads/master@{0}`).
-- '%gd': shortened reflog selector; same as `%gD`, but the refname
-  portion is shortened for human readability (so `refs/heads/master`
-  becomes just `master`).
-- '%gn': reflog identity name
-- '%gN': reflog identity name (respecting .mailmap, see
-  linkgit:git-shortlog[1] or linkgit:git-blame[1])
-- '%ge': reflog identity email
-- '%gE': reflog identity email (respecting .mailmap, see
-  linkgit:git-shortlog[1] or linkgit:git-blame[1])
-- '%gs': reflog subject
-- '%Cred': switch color to red
-- '%Cgreen': switch color to green
-- '%Cblue': switch color to blue
-- '%Creset': reset color
-- '%C(...)': color specification, as described under Values in the
-  "CONFIGURATION FILE" section of linkgit:git-config[1].
-  By default, colors are shown only when enabled for log output (by
-  `color.diff`, `color.ui`, or `--color`, and respecting the `auto`
-  settings of the former if we are going to a terminal). `%C(auto,...)`
-  is accepted as a historical synonym for the default (e.g.,
-  `%C(auto,red)`). Specifying `%C(always,...)` will show the colors
-  even when color is not otherwise enabled (though consider
-  just using `--color=always` to enable color for the whole output,
-  including this format and anything else git might color).  `auto`
-  alone (i.e. `%C(auto)`) will turn on auto coloring on the next
-  placeholders until the color is switched again.
-- '%m': left (`<`), right (`>`) or boundary (`-`) mark
-- '%n': newline
-- '%%': a raw '%'
-- '%x00': print a byte from a hex code
-- '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
-  linkgit:git-shortlog[1].
-- '%<(<N>[,trunc|ltrunc|mtrunc])': make the next placeholder take at
-  least N columns, padding spaces on the right if necessary.
-  Optionally truncate at the beginning (ltrunc), the middle (mtrunc)
-  or the end (trunc) if the output is longer than N columns.
-  Note that truncating only works correctly with N >= 2.
-- '%<|(<N>)': make the next placeholder take at least until Nth
-  columns, padding spaces on the right if necessary
-- '%>(<N>)', '%>|(<N>)': similar to '%<(<N>)', '%<|(<N>)'
-  respectively, but padding spaces on the left
-- '%>>(<N>)', '%>>|(<N>)': similar to '%>(<N>)', '%>|(<N>)'
-  respectively, except that if the next placeholder takes more spaces
-  than given and there are spaces on its left, use those spaces
-- '%><(<N>)', '%><|(<N>)': similar to '%<(<N>)', '%<|(<N>)'
-  respectively, but padding both sides (i.e. the text is centered)
-- %(trailers[:options]): display the trailers of the body as interpreted
-  by linkgit:git-interpret-trailers[1]. The `trailers` string may be
-  followed by a colon and zero or more comma-separated options. If the
-  `only` option is given, omit non-trailer lines from the trailer block.
-  If the `unfold` option is given, behave as if interpret-trailer's
-  `--unfold` option was given.  E.g., `%(trailers:only,unfold)` to do
-  both.
+'%GG':: raw verification message from GPG for a signed commit
+'%G?':: show "G" for a good (valid) signature,
+       "B" for a bad signature,
+       "U" for a good signature with unknown validity,
+       "X" for a good signature that has expired,
+       "Y" for a good signature made by an expired key,
+       "R" for a good signature made by a revoked key,
+       "E" if the signature cannot be checked (e.g. missing key)
+       and "N" for no signature
+'%GS':: show the name of the signer for a signed commit
+'%GK':: show the key used to sign a signed commit
+'%GF':: show the fingerprint of the key used to sign a signed commit
+'%GP':: show the fingerprint of the primary key whose subkey was used
+       to sign a signed commit
+'%gD':: reflog selector, e.g., `refs/stash@{1}` or `refs/stash@{2
+       minutes ago`}; the format follows the rules described for the
+       `-g` option. The portion before the `@` is the refname as
+       given on the command line (so `git log -g refs/heads/master`
+       would yield `refs/heads/master@{0}`).
+'%gd':: shortened reflog selector; same as `%gD`, but the refname
+       portion is shortened for human readability (so
+       `refs/heads/master` becomes just `master`).
+'%gn':: reflog identity name
+'%gN':: reflog identity name (respecting .mailmap, see
+       linkgit:git-shortlog[1] or linkgit:git-blame[1])
+'%ge':: reflog identity email
+'%gE':: reflog identity email (respecting .mailmap, see
+       linkgit:git-shortlog[1] or linkgit:git-blame[1])
+'%gs':: reflog subject
+'%(trailers[:options])':: display the trailers of the body as
+                         interpreted by
+                         linkgit:git-interpret-trailers[1]. The
+                         `trailers` string may be followed by a colon
+                         and zero or more comma-separated options:
+** 'key=<K>': only show trailers with specified key. Matching is done
+   case-insensitively and trailing colon is optional. If option is
+   given multiple times trailer lines matching any of the keys are
+   shown. This option automatically enables the `only` option so that
+   non-trailer lines in the trailer block are hidden. If that is not
+   desired it can be disabled with `only=false`.  E.g.,
+   `%(trailers:key=Reviewed-by)` shows trailer lines with key
+   `Reviewed-by`.
+** 'only[=val]': select whether non-trailer lines from the trailer
+   block should be included. The `only` keyword may optionally be
+   followed by an equal sign and one of `true`, `on`, `yes` to omit or
+   `false`, `off`, `no` to show the non-trailer lines. If option is
+   given without value it is enabled. If given multiple times the last
+   value is used.
+** 'separator=<SEP>': specify a separator inserted between trailer
+   lines. When this option is not given each trailer line is
+   terminated with a line feed character. The string SEP may contain
+   the literal formatting codes described above. To use comma as
+   separator one must use `%x2C` as it would otherwise be parsed as
+   next option. If separator option is given multiple times only the
+   last one is used. E.g., `%(trailers:key=Ticket,separator=%x2C )`
+   shows all trailer lines whose key is "Ticket" separated by a comma
+   and a space.
+** 'unfold[=val]': make it behave as if interpret-trailer's `--unfold`
+   option was given. In same way as to for `only` it can be followed
+   by an equal sign and explicit value. E.g.,
+   `%(trailers:only,unfold=true)` unfolds and shows all trailer lines.
+** 'valueonly[=val]': skip over the key part of the trailer line and only
+   show the value part. Also this optionally allows explicit value.
 
 NOTE: Some placeholders may depend on other options given to the
 revision traversal engine. For example, the `%g*` reflog options will
index cad711c..9cf983d 100644 (file)
@@ -743,7 +743,7 @@ explicitly-given commit or tree.
 
 --filter-print-omitted::
        Only useful with `--filter=`; prints a list of the objects omitted
-       by the filter.  Object IDs are prefixed with a ``~'' character.
+       by the filter.  Object IDs are prefixed with a ``~'' character.
 
 --missing=<missing-action>::
        A debug option to help with future "partial clone" development.
@@ -960,6 +960,13 @@ options may be given. See linkgit:git-diff-files[1] for more options.
        the parents have only two variants and the merge result picks
        one of them without modification.
 
+--combined-all-paths::
+       This flag causes combined diffs (used for merge commits) to
+       list the name of the file from all parents.  It thus only has
+       effect when -c or --cc are specified, and is likely only
+       useful if filename changes are detected (i.e. when either
+       rename or copy detection have been requested).
+
 -m::
        This flag makes the merge commits show the full diff like
        regular commits; for each merge parent, a separate log entry
diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt
new file mode 100644 (file)
index 0000000..2de565f
--- /dev/null
@@ -0,0 +1,1349 @@
+= Trace2 API
+
+The Trace2 API can be used to print debug, performance, and telemetry
+information to stderr or a file.  The Trace2 feature is inactive unless
+explicitly enabled by enabling one or more Trace2 Targets.
+
+The Trace2 API is intended to replace the existing (Trace1)
+printf-style tracing provided by the existing `GIT_TRACE` and
+`GIT_TRACE_PERFORMANCE` facilities.  During initial implementation,
+Trace2 and Trace1 may operate in parallel.
+
+The Trace2 API defines a set of high-level messages with known fields,
+such as (`start`: `argv`) and (`exit`: {`exit-code`, `elapsed-time`}).
+
+Trace2 instrumentation throughout the Git code base sends Trace2
+messages to the enabled Trace2 Targets.  Targets transform these
+messages content into purpose-specific formats and write events to
+their data streams.  In this manner, the Trace2 API can drive
+many different types of analysis.
+
+Targets are defined using a VTable allowing easy extension to other
+formats in the future.  This might be used to define a binary format,
+for example.
+
+== Trace2 Targets
+
+Trace2 defines the following set of Trace2 Targets.
+Format details are given in a later section.
+
+`GIT_TR2` (NORMAL)::
+
+       a simple printf format like GIT_TRACE.
++
+------------
+$ export GIT_TR2=~/log.normal
+$ git version
+git version 2.20.1.155.g426c96fcdb
+------------
++
+------------
+$ cat ~/log.normal
+12:28:42.620009 common-main.c:38                  version 2.20.1.155.g426c96fcdb
+12:28:42.620989 common-main.c:39                  start git version
+12:28:42.621101 git.c:432                         cmd_name version (version)
+12:28:42.621215 git.c:662                         exit elapsed:0.001227 code:0
+12:28:42.621250 trace2/tr2_tgt_normal.c:124       atexit elapsed:0.001265 code:0
+------------
+
+`GIT_TR2_PERF` (PERF)::
+
+       a column-based format to replace GIT_TRACE_PERFORMANCE suitable for
+       development and testing, possibly to complement tools like gprof.
++
+------------
+$ export GIT_TR2_PERF=~/log.perf
+$ git version
+git version 2.20.1.155.g426c96fcdb
+------------
++
+------------
+$ cat ~/log.perf
+12:28:42.620675 common-main.c:38                  | d0 | main                     | version      |     |           |           |            | 2.20.1.155.g426c96fcdb
+12:28:42.621001 common-main.c:39                  | d0 | main                     | start        |     |           |           |            | git version
+12:28:42.621111 git.c:432                         | d0 | main                     | cmd_name     |     |           |           |            | version (version)
+12:28:42.621225 git.c:662                         | d0 | main                     | exit         |     |  0.001227 |           |            | code:0
+12:28:42.621259 trace2/tr2_tgt_perf.c:211         | d0 | main                     | atexit       |     |  0.001265 |           |            | code:0
+------------
+
+`GIT_TR2_EVENT` (EVENT)::
+
+       a JSON-based format of event data suitable for telemetry analysis.
++
+------------
+$ export GIT_TR2_EVENT=~/log.event
+$ git version
+git version 2.20.1.155.g426c96fcdb
+------------
++
+------------
+$ cat ~/log.event
+{"event":"version","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.620713","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"}
+{"event":"start","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621027","file":"common-main.c","line":39,"argv":["git","version"]}
+{"event":"cmd_name","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621122","file":"git.c","line":432,"name":"version","hierarchy":"version"}
+{"event":"exit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621236","file":"git.c","line":662,"t_abs":0.001227,"code":0}
+{"event":"atexit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621268","file":"trace2/tr2_tgt_event.c","line":163,"t_abs":0.001265,"code":0}
+------------
+
+== Enabling a Target
+
+A Trace2 Target is enabled when the corresponding environment variable
+(`GIT_TR2`, `GIT_TR2_PERF`, or `GIT_TR2_EVENT`) is set.  The following
+values are recognized.
+
+`0`::
+`false`::
+
+       Disables the target.
+
+`1`::
+`true`::
+
+       Enables the target and writes stream to `STDERR`.
+
+`[2-9]`::
+
+       Enables the target and writes to the already opened file descriptor.
+
+`<absolute-pathname>`::
+
+       Enables the target, opens and writes to the file in append mode.
+
+`af_unix:[<socket_type>:]<absolute-pathname>`::
+
+       Enables the target, opens and writes to a Unix Domain Socket
+       (on platforms that support them).
++
+Socket type can be either `stream` or `dgram`.  If the socket type is
+omitted, Git will try both.
+
+== Trace2 API
+
+All public Trace2 functions and macros are defined in `trace2.h` and
+`trace2.c`.  All public symbols are prefixed with `trace2_`.
+
+There are no public Trace2 data structures.
+
+The Trace2 code also defines a set of private functions and data types
+in the `trace2/` directory.  These symbols are prefixed with `tr2_`
+and should only be used by functions in `trace2.c`.
+
+== Conventions for Public Functions and Macros
+
+The functions defined by the Trace2 API are declared and documented
+in `trace2.h`.  It defines the API functions and wrapper macros for
+Trace2.
+
+Some functions have a `_fl()` suffix to indicate that they take `file`
+and `line-number` arguments.
+
+Some functions have a `_va_fl()` suffix to indicate that they also
+take a `va_list` argument.
+
+Some functions have a `_printf_fl()` suffix to indicate that they also
+take a varargs argument.
+
+There are CPP wrapper macros and ifdefs to hide most of these details.
+See `trace2.h` for more details.  The following discussion will only
+describe the simplified forms.
+
+== Public API
+
+All Trace2 API functions send a messsage to all of the active
+Trace2 Targets.  This section describes the set of available
+messages.
+
+It helps to divide these functions into groups for discussion
+purposes.
+
+=== Basic Command Messages
+
+These are concerned with the lifetime of the overall git process.
+
+`void trace2_initialize()`::
+
+       Determines if any Trace2 Targets should be enabled and
+       initializes the Trace2 facility.  This includes starting the
+       elapsed time clocks and thread local storage (TLS).
++
+This function emits a "version" message containing the version of git
+and the Trace2 protocol.
++
+This function should be called from `main()` as early as possible in
+the life of the process.
+
+`int trace2_is_enabled()`::
+
+       Returns 1 if Trace2 is enabled (at least one target is
+       active).
+
+`void trace2_cmd_start(int argc, const char **argv)`::
+
+       Emits a "start" message containing the process command line
+       arguments.
+
+`int trace2_cmd_exit(int exit_code)`::
+
+       Emits an "exit" message containing the process exit-code and
+       elapsed time.
++
+Returns the exit-code.
+
+`void trace2_cmd_error(const char *fmt, va_list ap)`::
+
+       Emits an "error" message containing a formatted error message.
+
+`void trace2_cmd_path(const char *pathname)`::
+
+       Emits a "cmd_path" message with the full pathname of the
+       current process.
+
+=== Command Detail Messages
+
+These are concerned with describing the specific Git command
+after the command line, config, and environment are inspected.
+
+`void trace2_cmd_name(const char *name)`::
+
+       Emits a "cmd_name" message with the canonical name of the
+       command, for example "status" or "checkout".
+
+`void trace2_cmd_mode(const char *mode)`::
+
+       Emits a "cmd_mode" message with a qualifier name to further
+       describe the current git command.
++
+This message is intended to be used with git commands having multiple
+major modes.  For example, a "checkout" command can checkout a new
+branch or it can checkout a single file, so the checkout code could
+emit a cmd_mode message of "branch" or "file".
+
+`void trace2_cmd_alias(const char *alias, const char **argv_expansion)`::
+
+       Emits an "alias" message containing the alias used and the
+       argument expansion.
+
+`void trace2_def_param(const char *parameter, const char *value)`::
+
+       Emits a "def_param" message containing a key/value pair.
++
+This message is intended to report some global aspect of the current
+command, such as a configuration setting or command line switch that
+significantly affects program performance or behavior, such as
+`core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`.
+
+`void trace2_cmd_list_config()`::
+
+       Emits a "def_param" messages for "important" configuration
+       settings.
++
+The environment variable `GIT_TR2_CONFIG_PARAMS` can be set to a
+list of patterns of important configuration settings, for example:
+`core.*,remote.*.url`.  This function will iterate over all config
+settings and emit a "def_param" message for each match.
+
+`void trace2_cmd_set_config(const char *key, const char *value)`::
+
+       Emits a "def_param" message for a specific configuration
+       setting IFF it matches the `GIT_TR2_CONFIG_PARAMS` pattern.
++
+This is used to hook into `git_config_set()` and catch any
+configuration changes and update a value previously reported by
+`trace2_cmd_list_config()`.
+
+`void trace2_def_repo(struct repository *repo)`::
+
+       Registers a repository with the Trace2 layer.  Assigns a
+       unique "repo-id" to `repo->trace2_repo_id`.
++
+Emits a "worktree" messages containing the repo-id and the worktree
+pathname.
++
+Region and data messages (described later) may refer to this repo-id.
++
+The main/top-level repository will have repo-id value 1 (aka "r1").
++
+The repo-id field is in anticipation of future in-proc submodule
+repositories.
+
+=== Child Process Messages
+
+These are concerned with the various spawned child processes,
+including shell scripts, git commands, editors, pagers, and hooks.
+
+`void trace2_child_start(struct child_process *cmd)`::
+
+       Emits a "child_start" message containing the "child-id",
+       "child-argv", and "child-classification".
++
+Before calling this, set `cmd->trace2_child_class` to a name
+describing the type of child process, for example "editor".
++
+This function assigns a unique "child-id" to `cmd->trace2_child_id`.
+This field is used later during the "child_exit" message to associate
+it with the "child_start" message.
++
+This function should be called before spawning the child process.
+
+`void trace2_child_exit(struct child_proess *cmd, int child_exit_code)`::
+
+       Emits a "child_exit" message containing the "child-id",
+       the child's elapsed time and exit-code.
++
+The reported elapsed time includes the process creation overhead and
+time spend waiting for it to exit, so it may be slightly longer than
+the time reported by the child itself.
++
+This function should be called after reaping the child process.
+
+`int trace2_exec(const char *exe, const char **argv)`::
+
+       Emits a "exec" message containing the "exec-id" and the
+       argv of the new process.
++
+This function should be called before calling one of the `exec()`
+variants, such as `execvp()`.
++
+This function returns a unique "exec-id".  This value is used later
+if the exec() fails and a "exec-result" message is necessary.
+
+`void trace2_exec_result(int exec_id, int error_code)`::
+
+       Emits a "exec_result" message containing the "exec-id"
+       and the error code.
++
+On Unix-based systems, `exec()` does not return if successful.
+This message is used to indicate that the `exec()` failed and
+that the current program is continuing.
+
+=== Git Thread Messages
+
+These messages are concerned with Git thread usage.
+
+`void trace2_thread_start(const char *thread_name)`::
+
+       Emits a "thread_start" message.
++
+The `thread_name` field should be a descriptive name, such as the
+unique name of the thread-proc.  A unique "thread-id" will be added
+to the name to uniquely identify thread instances.
++
+Region and data messages (described later) may refer to this thread
+name.
++
+This function must be called by the thread-proc of the new thread
+(so that TLS data is properly initialized) and not by the caller
+of `pthread_create()`.
+
+`void trace2_thread_exit()`::
+
+       Emits a "thread_exit" message containing the thread name
+       and the thread elapsed time.
++
+This function must be called by the thread-proc before it returns
+(so that the coorect TLS data is used and cleaned up.  It should
+not be called by the caller of `pthread_join()`.
+
+=== Region and Data Messages
+
+These are concerned with recording performance data
+over regions or spans of code.
+
+`void trace2_region_enter(const char *category, const char *label, const struct repository *repo)`::
+
+`void trace2_region_enter_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`::
+
+`void trace2_region_enter_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`::
+
+       Emits a thread-relative "region_enter" message with optional
+       printf string.
++
+This function pushes a new region nesting stack level on the current
+thread and starts a clock for the new stack frame.
++
+The `category` field is an arbitrary category name used to classify
+regions by feature area, such as "status" or "index".  At this time
+it is only just printed along with the rest of the message.  It may
+be used in the future to filter messages.
++
+The `label` field is an arbitrary label used to describe the activity
+being started, such as "read_recursive" or "do_read_index".
++
+The `repo` field, if set, will be used to get the "repo-id", so that
+recursive oerations can be attributed to the correct repository.
+
+`void trace2_region_leave(const char *category, const char *label, const struct repository *repo)`::
+
+`void trace2_region_leave_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`::
+
+`void trace2_region_leave_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`::
+
+       Emits a thread-relative "region_leave" message with optional
+       printf string.
++
+This function pops the region nesting stack on the current thread
+and reports the elapsed time of the stack frame.
++
+The `category`, `label`, and `repo` fields are the same as above.
+The `category` and `label` do not need to match the correpsonding
+"region_enter" message, but it makes the data stream easier to
+understand.
+
+`void trace2_data_string(const char *category, const struct repository *repo, const char *key, const char * value)`::
+
+`void trace2_data_intmax(const char *category, const struct repository *repo, const char *key, intmax value)`::
+
+`void trace2_data_json(const char *category, const struct repository *repo, const char *key, const struct json_writer *jw)`::
+
+       Emits a region- and thread-relative "data" or "data_json" message.
++
+This is a key/value pair message containing information about the
+current thread, region stack, and repository.  This could be used
+to print the number of files in a directory during a multi-threaded
+recursive tree walk.
+
+`void trace2_printf(const char *fmt, ...)`::
+
+`void trace2_printf_va(const char *fmt, va_list ap)`::
+
+       Emits a region- and thread-relative "printf" message.
+
+== Trace2 Target Formats
+
+=== NORMAL Format
+
+NORMAL format is enabled when the `GIT_TR2` environment variable is
+set.
+
+Events are written as lines of the form:
+
+------------
+[<time> SP <filename>:<line> SP+] <event-name> [[SP] <event-message>] LF
+------------
+
+`<event-name>`::
+
+       is the event name.
+
+`<event-message>`::
+       is a free-form printf message intended for human consumption.
++
+Note that this may contain embedded LF or CRLF characters that are
+not escaped, so the event may spill across multiple lines.
+
+If `GIT_TR2_BRIEF` is true, the `time`, `filename`, and `line` fields
+are omitted.
+
+This target is intended to be more of a summary (like GIT_TRACE) and
+less detailed than the other targets.  It ignores thread, region, and
+data messages, for example.
+
+=== PERF Format
+
+PERF format is enabled when the `GIT_TR2_PERF` environment variable
+is set.
+
+Events are written as lines of the form:
+
+------------
+[<time> SP <filename>:<line> SP+
+    BAR SP] d<depth> SP
+    BAR SP <thread-name> SP+
+    BAR SP <event-name> SP+
+    BAR SP [r<repo-id>] SP+
+    BAR SP [<t_abs>] SP+
+    BAR SP [<t_rel>] SP+
+    BAR SP [<category>] SP+
+    BAR SP DOTS* <perf-event-message>
+    LF
+------------
+
+`<depth>`::
+       is the git process depth.  This is the number of parent
+       git processes.  A top-level git command has depth value "d0".
+       A child of it has depth value "d1".  A second level child
+       has depth value "d2" and so on.
+
+`<thread-name>`::
+       is a unique name for the thread.  The primary thread
+       is called "main".  Other thread names are of the form "th%d:%s"
+       and include a unique number and the name of the thread-proc.
+
+`<event-name>`::
+       is the event name.
+
+`<repo-id>`::
+       when present, is a number indicating the repository
+       in use.  A `def_repo` event is emitted when a repository is
+       opened.  This defines the repo-id and associated worktree.
+       Subsequent repo-specific events will reference this repo-id.
++
+Currently, this is always "r1" for the main repository.
+This field is in anticipation of in-proc submodules in the future.
+
+`<t_abs>`::
+       when present, is the absolute time in seconds since the
+       program started.
+
+`<t_rel>`::
+       when present, is time in seconds relative to the start of
+       the current region.  For a thread-exit event, it is the elapsed
+       time of the thread.
+
+`<category>`::
+       is present on region and data events and is used to
+       indicate a broad category, such as "index" or "status".
+
+`<perf-event-message>`::
+       is a free-form printf message intended for human consumption.
+
+------------
+15:33:33.532712 wt-status.c:2310                  | d0 | main                     | region_enter | r1  |  0.126064 |           | status     | label:print
+15:33:33.532712 wt-status.c:2331                  | d0 | main                     | region_leave | r1  |  0.127568 |  0.001504 | status     | label:print
+------------
+
+If `GIT_TR2_PERF_BRIEF` is true, the `time`, `file`, and `line`
+fields are omitted.
+
+------------
+d0 | main                     | region_leave | r1  |  0.011717 |  0.009122 | index      | label:preload
+------------
+
+The PERF target is intended for interactive performance analysis
+during development and is quite noisy.
+
+=== EVENT Format
+
+EVENT format is enabled when the `GIT_TR2_EVENT` environment
+variable is set.
+
+Each event is a JSON-object containing multiple key/value pairs
+written as a single line and followed by a LF.
+
+------------
+'{' <key> ':' <value> [',' <key> ':' <value>]* '}' LF
+------------
+
+Some key/value pairs are common to all events and some are
+event-specific.
+
+==== Common Key/Value Pairs
+
+The following key/value pairs are common to all events:
+
+------------
+{
+       "event":"version",
+       "sid":"1547659722619736-11614",
+       "thread":"main",
+       "time":"2019-01-16 17:28:42.620713",
+       "file":"common-main.c",
+       "line":38,
+       ...
+}
+------------
+
+`"event":<event>`::
+       is the event name.
+
+`"sid":<sid>`::
+       is the session-id.  This is a unique string to identify the
+       process instance to allow all events emitted by a process to
+       be identified.  A session-id is used instead of a PID because
+       PIDs are recycled by the OS.  For child git processes, the
+       session-id is prepended with the session-id of the parent git
+       process to allow parent-child relationships to be identified
+       during post-processing.
+
+`"thread":<thread>`::
+       is the thread name.
+
+`"time":<time>`::
+       is the UTC time of the event.
+
+`"file":<filename>`::
+       is source file generating the event.
+
+`"line":<line-number>`::
+       is the integer source line number generating the event.
+
+`"repo":<repo-id>`::
+       when present, is the integer repo-id as described previously.
+
+If `GIT_TR2_EVENT_BRIEF` is true, the `file` and `line` fields are omitted
+from all events and the `time` field is only present on the "start" and
+"atexit" events.
+
+==== Event-Specific Key/Value Pairs
+
+`"version"`::
+       This event gives the version of the executable and the EVENT format.
++
+------------
+{
+       "event":"version",
+       ...
+       "evt":"1",                     # EVENT format version
+       "exe":"2.20.1.155.g426c96fcdb" # git version
+}
+------------
+
+`"start"`::
+       This event contains the complete argv received by main().
++
+------------
+{
+       "event":"start",
+       ...
+       "argv":["git","version"]
+}
+------------
+
+`"exit"`::
+       This event is emitted when git calls `exit()`.
++
+------------
+{
+       "event":"exit",
+       ...
+       "t_abs":0.001227, # elapsed time in seconds
+       "code":0          # exit code
+}
+------------
+
+`"atexit"`::
+       This event is emitted by the Trace2 `atexit` routine during
+       final shutdown.  It should be the last event emitted by the
+       process.
++
+(The elapsed time reported here is greater than the time reported in
+the "exit" event because it runs after all other atexit tasks have
+completed.)
++
+------------
+{
+       "event":"atexit",
+       ...
+       "t_abs":0.001227, # elapsed time in seconds
+       "code":0          # exit code
+}
+------------
+
+`"signal"`::
+       This event is emitted when the program is terminated by a user
+       signal.  Depending on the platform, the signal event may
+       prevent the "atexit" event from being generated.
++
+------------
+{
+       "event":"signal",
+       ...
+       "t_abs":0.001227,  # elapsed time in seconds
+       "signal":13        # SIGTERM, SIGINT, etc.
+}
+------------
+
+`"error"`::
+       This event is emitted when one of the `error()`, `die()`,
+       or `usage()` functions are called.
++
+------------
+{
+       "event":"error",
+       ...
+       "msg":"invalid option: --cahced", # formatted error message
+       "fmt":"invalid option: %s"        # error format string
+}
+------------
++
+The error event may be emitted more than once.  The format string
+allows post-processors to group errors by type without worrying
+about specific error arguments.
+
+`"cmd_path"`::
+       This event contains the discovered full path of the git
+       executable (on platforms that are configured to resolve it).
++
+------------
+{
+       "event":"cmd_path",
+       ...
+       "path":"C:/work/gfw/git.exe"
+}
+------------
+
+`"cmd_name"`::
+       This event contains the command name for this git process
+       and the hierarchy of commands from parent git processes.
++
+------------
+{
+       "event":"cmd_name",
+       ...
+       "name":"pack-objects",
+       "hierarchy":"push/pack-objects"
+}
+------------
++
+Normally, the "name" field contains the canonical name of the
+command.  When a canonical name is not available, one of
+these special values are used:
++
+------------
+"_query_"            # "git --html-path"
+"_run_dashed_"       # when "git foo" tries to run "git-foo"
+"_run_shell_alias_"  # alias expansion to a shell command
+"_run_git_alias_"    # alias expansion to a git command
+"_usage_"            # usage error
+------------
+
+`"cmd_mode"`::
+       This event, when present, describes the command variant This
+       event may be emitted more than once.
++
+------------
+{
+       "event":"cmd_mode",
+       ...
+       "name":"branch"
+}
+------------
++
+The "name" field is an arbitrary string to describe the command mode.
+For example, checkout can checkout a branch or an individual file.
+And these variations typically have different performance
+characteristics that are not comparable.
+
+`"alias"`::
+       This event is present when an alias is expanded.
++
+------------
+{
+       "event":"alias",
+       ...
+       "alias":"l",             # registered alias
+       "argv":["log","--graph"] # alias expansion
+}
+------------
+
+`"child_start"`::
+       This event describes a child process that is about to be
+       spawned.
++
+------------
+{
+       "event":"child_start",
+       ...
+       "child_id":2,
+       "child_class":"?",
+       "use_shell":false,
+       "argv":["git","rev-list","--objects","--stdin","--not","--all","--quiet"]
+
+       "hook_name":"<hook_name>"  # present when child_class is "hook"
+       "cd":"<path>"              # present when cd is required
+}
+------------
++
+The "child_id" field can be used to match this child_start with the
+corresponding child_exit event.
++
+The "child_class" field is a rough classification, such as "editor",
+"pager", "transport/*", and "hook".  Unclassified children are classified
+with "?".
+
+`"child_exit"`::
+       This event is generated after the current process has returned
+       from the waitpid() and collected the exit information from the
+       child.
++
+------------
+{
+       "event":"child_exit",
+       ...
+       "child_id":2,
+       "pid":14708,     # child PID
+       "code":0,        # child exit-code
+       "t_rel":0.110605 # observed run-time of child process
+}
+------------
++
+Note that the session-id of the child process is not available to
+the current/spawning process, so the child's PID is reported here as
+a hint for post-processing.  (But it is only a hint because the child
+proces may be a shell script which doesn't have a session-id.)
++
+Note that the `t_rel` field contains the observed run time in seconds
+for the child process (starting before the fork/exec/spawn and
+stopping after the waitpid() and includes OS process creation overhead).
+So this time will be slightly larger than the atexit time reported by
+the child process itself.
+
+`"exec"`::
+       This event is generated before git attempts to `exec()`
+       another command rather than starting a child process.
++
+------------
+{
+       "event":"exec",
+       ...
+       "exec_id":0,
+       "exe":"git",
+       "argv":["foo", "bar"]
+}
+------------
++
+The "exec_id" field is a command-unique id and is only useful if the
+`exec()` fails and a corresponding exec_result event is generated.
+
+`"exec_result"`::
+       This event is generated if the `exec()` fails and control
+       returns to the current git command.
++
+------------
+{
+       "event":"exec_result",
+       ...
+       "exec_id":0,
+       "code":1      # error code (errno) from exec()
+}
+------------
+
+`"thread_start"`::
+       This event is generated when a thread is started.  It is
+       generated from *within* the new thread's thread-proc (for TLS
+       reasons).
++
+------------
+{
+       "event":"thread_start",
+       ...
+       "thread":"th02:preload_thread" # thread name
+}
+------------
+
+`"thread_exit"`::
+       This event is generated when a thread exits.  It is generated
+       from *within* the thread's thread-proc (for TLS reasons).
++
+------------
+{
+       "event":"thread_exit",
+       ...
+       "thread":"th02:preload_thread", # thread name
+       "t_rel":0.007328                # thread elapsed time
+}
+------------
+
+`"def_param"`::
+       This event is generated to log a global parameter.
++
+------------
+{
+       "event":"def_param",
+       ...
+       "param":"core.abbrev",
+       "value":"7"
+}
+------------
+
+`"def_repo"`::
+       This event defines a repo-id and associates it with the root
+       of the worktree.
++
+------------
+{
+       "event":"def_repo",
+       ...
+       "repo":1,
+       "worktree":"/Users/jeffhost/work/gfw"
+}
+------------
++
+As stated earlier, the repo-id is currently always 1, so there will
+only be one def_repo event.  Later, if in-proc submodules are
+supported, a def_repo event should be emitted for each submodule
+visited.
+
+`"region_enter"`::
+       This event is generated when entering a region.
++
+------------
+{
+       "event":"region_enter",
+       ...
+       "repo":1,                # optional
+       "nesting":1,             # current region stack depth
+       "category":"index",      # optional
+       "label":"do_read_index", # optional
+       "msg":".git/index"       # optional
+}
+------------
++
+The `category` field may be used in a future enhancement to
+do category-based filtering.
++
+The `GIT_TR2_EVENT_NESTING` environment variable can be used to
+filter deeply nested regions and data events.  It defaults to "2".
+
+`"region_leave"`::
+       This event is generated when leaving a region.
++
+------------
+{
+       "event":"region_leave",
+       ...
+       "repo":1,                # optional
+       "t_rel":0.002876,        # time spent in region in seconds
+       "nesting":1,             # region stack depth
+       "category":"index",      # optional
+       "label":"do_read_index", # optional
+       "msg":".git/index"       # optional
+}
+------------
+
+`"data"`::
+       This event is generated to log a thread- and region-local
+       key/value pair.
++
+------------
+{
+       "event":"data",
+       ...
+       "repo":1,              # optional
+       "t_abs":0.024107,      # absolute elapsed time
+       "t_rel":0.001031,      # elapsed time in region/thread
+       "nesting":2,           # region stack depth
+       "category":"index",
+       "key":"read/cache_nr",
+       "value":"3552"
+}
+------------
++
+The "value" field may be an integer or a string.
+
+`"data-json"`::
+       This event is generated to log a pre-formatted JSON string
+       containing structured data.
++
+------------
+{
+       "event":"data_json",
+       ...
+       "repo":1,              # optional
+       "t_abs":0.015905,
+       "t_rel":0.015905,
+       "nesting":1,
+       "category":"process",
+       "key":"windows/ancestry",
+       "value":["bash.exe","bash.exe"]
+}
+------------
+
+== Example Trace2 API Usage
+
+Here is a hypothetical usage of the Trace2 API showing the intended
+usage (without worrying about the actual Git details).
+
+Initialization::
+
+       Initialization happens in `main()`.  Behind the scenes, an
+       `atexit` and `signal` handler are registered.
++
+----------------
+int main(int argc, const char **argv)
+{
+       int exit_code;
+
+       trace2_initialize();
+       trace2_cmd_start(argv);
+
+       exit_code = cmd_main(argc, argv);
+
+       trace2_cmd_exit(exit_code);
+
+       return exit_code;
+}
+----------------
+
+Command Details::
+
+       After the basics are established, additional command
+       information can be sent to Trace2 as it is discovered.
++
+----------------
+int cmd_checkout(int argc, const char **argv)
+{
+       trace2_cmd_name("checkout");
+       trace2_cmd_mode("branch");
+       trace2_def_repo(the_repository);
+
+       // emit "def_param" messages for "interesting" config settings.
+       trace2_cmd_list_config();
+
+       if (do_something())
+           trace2_cmd_error("Path '%s': cannot do something", path);
+
+       return 0;
+}
+----------------
+
+Child Processes::
+
+       Wrap code spawning child processes.
++
+----------------
+void run_child(...)
+{
+       int child_exit_code;
+       struct child_process cmd = CHILD_PROCESS_INIT;
+       ...
+       cmd.trace2_child_class = "editor";
+
+       trace2_child_start(&cmd);
+       child_exit_code = spawn_child_and_wait_for_it();
+       trace2_child_exit(&cmd, child_exit_code);
+}
+----------------
++
+For example, the following fetch command spawned ssh, index-pack,
+rev-list, and gc.  This example also shows that fetch took
+5.199 seconds and of that 4.932 was in ssh.
++
+----------------
+$ export GIT_TR2_BRIEF=1
+$ export GIT_TR2=~/log.normal
+$ git fetch origin
+...
+----------------
++
+----------------
+$ cat ~/log.normal
+version 2.20.1.vfs.1.1.47.g534dbe1ad1
+start git fetch origin
+worktree /Users/jeffhost/work/gfw
+cmd_name fetch (fetch)
+child_start[0] ssh git@github.com ...
+child_start[1] git index-pack ...
+... (Trace2 events from child processes omitted)
+child_exit[1] pid:14707 code:0 elapsed:0.076353
+child_exit[0] pid:14706 code:0 elapsed:4.931869
+child_start[2] git rev-list ...
+... (Trace2 events from child process omitted)
+child_exit[2] pid:14708 code:0 elapsed:0.110605
+child_start[3] git gc --auto
+... (Trace2 events from child process omitted)
+child_exit[3] pid:14709 code:0 elapsed:0.006240
+exit elapsed:5.198503 code:0
+atexit elapsed:5.198541 code:0
+----------------
++
+When a git process is a (direct or indirect) child of another
+git process, it inherits Trace2 context information.  This
+allows the child to print the command hierarchy.  This example
+shows gc as child[3] of fetch.  When the gc process reports
+its name as "gc", it also reports the hierarchy as "fetch/gc".
+(In this example, trace2 messages from the child process is
+indented for clarity.)
++
+----------------
+$ export GIT_TR2_BRIEF=1
+$ export GIT_TR2=~/log.normal
+$ git fetch origin
+...
+----------------
++
+----------------
+$ cat ~/log.normal
+version 2.20.1.160.g5676107ecd.dirty
+start git fetch official
+worktree /Users/jeffhost/work/gfw
+cmd_name fetch (fetch)
+...
+child_start[3] git gc --auto
+    version 2.20.1.160.g5676107ecd.dirty
+    start /Users/jeffhost/work/gfw/git gc --auto
+    worktree /Users/jeffhost/work/gfw
+    cmd_name gc (fetch/gc)
+    exit elapsed:0.001959 code:0
+    atexit elapsed:0.001997 code:0
+child_exit[3] pid:20303 code:0 elapsed:0.007564
+exit elapsed:3.868938 code:0
+atexit elapsed:3.868970 code:0
+----------------
+
+Regions::
+
+       Regions can be use to time an interesting section of code.
++
+----------------
+void wt_status_collect(struct wt_status *s)
+{
+       trace2_region_enter("status", "worktrees", s->repo);
+       wt_status_collect_changes_worktree(s);
+       trace2_region_leave("status", "worktrees", s->repo);
+
+       trace2_region_enter("status", "index", s->repo);
+       wt_status_collect_changes_index(s);
+       trace2_region_leave("status", "index", s->repo);
+
+       trace2_region_enter("status", "untracked", s->repo);
+       wt_status_collect_untracked(s);
+       trace2_region_leave("status", "untracked", s->repo);
+}
+
+void wt_status_print(struct wt_status *s)
+{
+       trace2_region_enter("status", "print", s->repo);
+       switch (s->status_format) {
+           ...
+       }
+       trace2_region_leave("status", "print", s->repo);
+}
+----------------
++
+In this example, scanning for untracked files ran from +0.012568 to
++0.027149 (since the process started) and took 0.014581 seconds.
++
+----------------
+$ export GIT_TR2_PERF_BRIEF=1
+$ export GIT_TR2_PERF=~/log.perf
+$ git status
+...
+
+$ cat ~/log.perf
+d0 | main                     | version      |     |           |           |            | 2.20.1.160.g5676107ecd.dirty
+d0 | main                     | start        |     |           |           |            | git status
+d0 | main                     | def_repo     | r1  |           |           |            | worktree:/Users/jeffhost/work/gfw
+d0 | main                     | cmd_name     |     |           |           |            | status (status)
+...
+d0 | main                     | region_enter | r1  |  0.010988 |           | status     | label:worktrees
+d0 | main                     | region_leave | r1  |  0.011236 |  0.000248 | status     | label:worktrees
+d0 | main                     | region_enter | r1  |  0.011260 |           | status     | label:index
+d0 | main                     | region_leave | r1  |  0.012542 |  0.001282 | status     | label:index
+d0 | main                     | region_enter | r1  |  0.012568 |           | status     | label:untracked
+d0 | main                     | region_leave | r1  |  0.027149 |  0.014581 | status     | label:untracked
+d0 | main                     | region_enter | r1  |  0.027411 |           | status     | label:print
+d0 | main                     | region_leave | r1  |  0.028741 |  0.001330 | status     | label:print
+d0 | main                     | exit         |     |  0.028778 |           |            | code:0
+d0 | main                     | atexit       |     |  0.028809 |           |            | code:0
+----------------
++
+Regions may be nested.  This causes messages to be indented in the
+PERF target, for example.
+Elapsed times are relative to the start of the correpsonding nesting
+level as expected.  For example, if we add region message to:
++
+----------------
+static enum path_treatment read_directory_recursive(struct dir_struct *dir,
+       struct index_state *istate, const char *base, int baselen,
+       struct untracked_cache_dir *untracked, int check_only,
+       int stop_at_first_file, const struct pathspec *pathspec)
+{
+       enum path_treatment state, subdir_state, dir_state = path_none;
+
+       trace2_region_enter_printf("dir", "read_recursive", NULL, "%.*s", baselen, base);
+       ...
+       trace2_region_leave_printf("dir", "read_recursive", NULL, "%.*s", baselen, base);
+       return dir_state;
+}
+----------------
++
+We can further investigate the time spent scanning for untracked files.
++
+----------------
+$ export GIT_TR2_PERF_BRIEF=1
+$ export GIT_TR2_PERF=~/log.perf
+$ git status
+...
+$ cat ~/log.perf
+d0 | main                     | version      |     |           |           |            | 2.20.1.162.gb4ccea44db.dirty
+d0 | main                     | start        |     |           |           |            | git status
+d0 | main                     | def_repo     | r1  |           |           |            | worktree:/Users/jeffhost/work/gfw
+d0 | main                     | cmd_name     |     |           |           |            | status (status)
+...
+d0 | main                     | region_enter | r1  |  0.015047 |           | status     | label:untracked
+d0 | main                     | region_enter |     |  0.015132 |           | dir        | ..label:read_recursive
+d0 | main                     | region_enter |     |  0.016341 |           | dir        | ....label:read_recursive vcs-svn/
+d0 | main                     | region_leave |     |  0.016422 |  0.000081 | dir        | ....label:read_recursive vcs-svn/
+d0 | main                     | region_enter |     |  0.016446 |           | dir        | ....label:read_recursive xdiff/
+d0 | main                     | region_leave |     |  0.016522 |  0.000076 | dir        | ....label:read_recursive xdiff/
+d0 | main                     | region_enter |     |  0.016612 |           | dir        | ....label:read_recursive git-gui/
+d0 | main                     | region_enter |     |  0.016698 |           | dir        | ......label:read_recursive git-gui/po/
+d0 | main                     | region_enter |     |  0.016810 |           | dir        | ........label:read_recursive git-gui/po/glossary/
+d0 | main                     | region_leave |     |  0.016863 |  0.000053 | dir        | ........label:read_recursive git-gui/po/glossary/
+...
+d0 | main                     | region_enter |     |  0.031876 |           | dir        | ....label:read_recursive builtin/
+d0 | main                     | region_leave |     |  0.032270 |  0.000394 | dir        | ....label:read_recursive builtin/
+d0 | main                     | region_leave |     |  0.032414 |  0.017282 | dir        | ..label:read_recursive
+d0 | main                     | region_leave | r1  |  0.032454 |  0.017407 | status     | label:untracked
+...
+d0 | main                     | exit         |     |  0.034279 |           |            | code:0
+d0 | main                     | atexit       |     |  0.034322 |           |            | code:0
+----------------
++
+Trace2 regions are similar to the existing trace_performance_enter()
+and trace_performance_leave() routines, but are thread safe and
+maintain per-thread stacks of timers.
+
+Data Messages::
+
+       Data messages added to a region.
++
+----------------
+int read_index_from(struct index_state *istate, const char *path,
+       const char *gitdir)
+{
+       trace2_region_enter_printf("index", "do_read_index", the_repository, "%s", path);
+
+       ...
+
+       trace2_data_intmax("index", the_repository, "read/version", istate->version);
+       trace2_data_intmax("index", the_repository, "read/cache_nr", istate->cache_nr);
+
+       trace2_region_leave_printf("index", "do_read_index", the_repository, "%s", path);
+}
+----------------
++
+This example shows that the index contained 3552 entries.
++
+----------------
+$ export GIT_TR2_PERF_BRIEF=1
+$ export GIT_TR2_PERF=~/log.perf
+$ git status
+...
+$ cat ~/log.perf
+d0 | main                     | version      |     |           |           |            | 2.20.1.156.gf9916ae094.dirty
+d0 | main                     | start        |     |           |           |            | git status
+d0 | main                     | def_repo     | r1  |           |           |            | worktree:/Users/jeffhost/work/gfw
+d0 | main                     | cmd_name     |     |           |           |            | status (status)
+d0 | main                     | region_enter | r1  |  0.001791 |           | index      | label:do_read_index .git/index
+d0 | main                     | data         | r1  |  0.002494 |  0.000703 | index      | ..read/version:2
+d0 | main                     | data         | r1  |  0.002520 |  0.000729 | index      | ..read/cache_nr:3552
+d0 | main                     | region_leave | r1  |  0.002539 |  0.000748 | index      | label:do_read_index .git/index
+...
+----------------
+
+Thread Events::
+
+       Thread messages added to a thread-proc.
++
+For example, the multithreaded preload-index code can be
+instrumented with a region around the thread pool and then
+per-thread start and exit events within the threadproc.
++
+----------------
+static void *preload_thread(void *_data)
+{
+       // start the per-thread clock and emit a message.
+       trace2_thread_start("preload_thread");
+
+       // report which chunk of the array this thread was assigned.
+       trace2_data_intmax("index", the_repository, "offset", p->offset);
+       trace2_data_intmax("index", the_repository, "count", nr);
+
+       do {
+           ...
+       } while (--nr > 0);
+       ...
+
+       // report elapsed time taken by this thread.
+       trace2_thread_exit();
+       return NULL;
+}
+
+void preload_index(struct index_state *index,
+       const struct pathspec *pathspec,
+       unsigned int refresh_flags)
+{
+       trace2_region_enter("index", "preload", the_repository);
+
+       for (i = 0; i < threads; i++) {
+           ... /* create thread */
+       }
+
+       for (i = 0; i < threads; i++) {
+           ... /* join thread */
+       }
+
+       trace2_region_leave("index", "preload", the_repository);
+}
+----------------
++
+In this example preload_index() was executed by the `main` thread
+and started the `preload` region.  Seven threads, named
+`th01:preload_thread` through `th07:preload_thread`, were started.
+Events from each thread are atomically appended to the shared target
+stream as they occur so they may appear in random order with respect
+other threads. Finally, the main thread waits for the threads to
+finish and leaves the region.
++
+Data events are tagged with the active thread name.  They are used
+to report the per-thread parameters.
++
+----------------
+$ export GIT_TR2_PERF_BRIEF=1
+$ export GIT_TR2_PERF=~/log.perf
+$ git status
+...
+$ cat ~/log.perf
+...
+d0 | main                     | region_enter | r1  |  0.002595 |           | index      | label:preload
+d0 | th01:preload_thread      | thread_start |     |  0.002699 |           |            |
+d0 | th02:preload_thread      | thread_start |     |  0.002721 |           |            |
+d0 | th01:preload_thread      | data         | r1  |  0.002736 |  0.000037 | index      | offset:0
+d0 | th02:preload_thread      | data         | r1  |  0.002751 |  0.000030 | index      | offset:2032
+d0 | th03:preload_thread      | thread_start |     |  0.002711 |           |            |
+d0 | th06:preload_thread      | thread_start |     |  0.002739 |           |            |
+d0 | th01:preload_thread      | data         | r1  |  0.002766 |  0.000067 | index      | count:508
+d0 | th06:preload_thread      | data         | r1  |  0.002856 |  0.000117 | index      | offset:2540
+d0 | th03:preload_thread      | data         | r1  |  0.002824 |  0.000113 | index      | offset:1016
+d0 | th04:preload_thread      | thread_start |     |  0.002710 |           |            |
+d0 | th02:preload_thread      | data         | r1  |  0.002779 |  0.000058 | index      | count:508
+d0 | th06:preload_thread      | data         | r1  |  0.002966 |  0.000227 | index      | count:508
+d0 | th07:preload_thread      | thread_start |     |  0.002741 |           |            |
+d0 | th07:preload_thread      | data         | r1  |  0.003017 |  0.000276 | index      | offset:3048
+d0 | th05:preload_thread      | thread_start |     |  0.002712 |           |            |
+d0 | th05:preload_thread      | data         | r1  |  0.003067 |  0.000355 | index      | offset:1524
+d0 | th05:preload_thread      | data         | r1  |  0.003090 |  0.000378 | index      | count:508
+d0 | th07:preload_thread      | data         | r1  |  0.003037 |  0.000296 | index      | count:504
+d0 | th03:preload_thread      | data         | r1  |  0.002971 |  0.000260 | index      | count:508
+d0 | th04:preload_thread      | data         | r1  |  0.002983 |  0.000273 | index      | offset:508
+d0 | th04:preload_thread      | data         | r1  |  0.007311 |  0.004601 | index      | count:508
+d0 | th05:preload_thread      | thread_exit  |     |  0.008781 |  0.006069 |            |
+d0 | th01:preload_thread      | thread_exit  |     |  0.009561 |  0.006862 |            |
+d0 | th03:preload_thread      | thread_exit  |     |  0.009742 |  0.007031 |            |
+d0 | th06:preload_thread      | thread_exit  |     |  0.009820 |  0.007081 |            |
+d0 | th02:preload_thread      | thread_exit  |     |  0.010274 |  0.007553 |            |
+d0 | th07:preload_thread      | thread_exit  |     |  0.010477 |  0.007736 |            |
+d0 | th04:preload_thread      | thread_exit  |     |  0.011657 |  0.008947 |            |
+d0 | main                     | region_leave | r1  |  0.011717 |  0.009122 | index      | label:preload
+...
+d0 | main                     | exit         |     |  0.029996 |           |            | code:0
+d0 | main                     | atexit       |     |  0.030027 |           |            | code:0
+----------------
++
+In this example, the preload region took 0.009122 seconds.  The 7 threads
+took between 0.006069 and 0.008947 seconds to work on their portion of
+the index.  Thread "th01" worked on 508 items at offset 0.  Thread "th02"
+worked on 508 items at offset 2032.  Thread "th04" worked on 508 itemts
+at offset 508.
++
+This example also shows that thread names are assigned in a racy manner
+as each thread starts and allocates TLS storage.
+
+== Future Work
+
+=== Relationship to the Existing Trace Api (api-trace.txt)
+
+There are a few issues to resolve before we can completely
+switch to Trace2.
+
+* Updating existing tests that assume GIT_TRACE format messages.
+
+* How to best handle custom GIT_TRACE_<key> messages?
+
+** The GIT_TRACE_<key> mechanism allows each <key> to write to a
+different file (in addition to just stderr).
+
+** Do we want to maintain that ability or simply write to the existing
+Trace2 targets (and convert <key> to a "category").
index 1c0086e..844629c 100644 (file)
@@ -20,8 +20,8 @@ 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.
+  * 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.
index 7a2375a..c73e72d 100644 (file)
@@ -657,14 +657,14 @@ can be rejected.
 An example client/server communication might look like this:
 
 ----
-   S: 007c74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n
+   S: 006274730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n
    S: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe refs/heads/debug\n
    S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/master\n
-   S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n
+   S: 003d74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n
    S: 0000
 
-   C: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n
-   C: 003e74730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n
+   C: 00677d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n
+   C: 006874730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n
    C: 0000
    C: [PACKDATA]
 
index 332d209..2b267c0 100644 (file)
@@ -1,6 +1,10 @@
 Git Protocol Capabilities
 =========================
 
+NOTE: this document describes capabilities for versions 0 and 1 of the pack
+protocol. For version 2, please refer to the link:protocol-v2.html[protocol-v2]
+doc.
+
 Servers SHOULD support all capabilities defined in this document.
 
 On the very first line of the initial server response of either
@@ -172,6 +176,20 @@ agent strings are purely informative for statistics and debugging
 purposes, and MUST NOT be used to programmatically assume the presence
 or absence of particular features.
 
+symref
+------
+
+This parameterized capability is used to inform the receiver which symbolic ref
+points to which ref; for example, "symref=HEAD:refs/heads/master" tells the
+receiver that HEAD points to master. This capability can be repeated to
+represent multiple symrefs.
+
+Servers SHOULD include this capability for the HEAD symref if it is one of the
+refs being sent.
+
+Clients MAY use the parameters from this capability to select the proper initial
+branch when cloning a repository.
+
 shallow
 -------
 
index 13f835f..3fc4065 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.21.0
+DEF_VER=v2.21.GIT
 
 LF='
 '
index c524094..5e5489a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -479,7 +479,11 @@ all::
 #
 # Define DEVELOPER to enable more compiler warnings. Compiler version
 # and family are auto detected, but could be overridden by defining
-# COMPILER_FEATURES (see config.mak.dev)
+# COMPILER_FEATURES (see config.mak.dev). You can still set
+# CFLAGS="..." in combination with DEVELOPER enables, whether that's
+# for tweaking something unrelated (e.g. optimization level), or for
+# selectively overriding something DEVELOPER or one of the DEVOPTS
+# (see just below) brings in.
 #
 # When DEVELOPER is set, DEVOPTS can be used to control compiler
 # options.  This variable contains keywords separated by
@@ -506,17 +510,8 @@ GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
 -include GIT-VERSION-FILE
 
-# CFLAGS and LDFLAGS are for the users to override from the command line.
-
-CFLAGS = -g -O2 -Wall
-LDFLAGS =
-ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
-ALL_LDFLAGS = $(LDFLAGS)
-STRIP ?= strip
-
-# Create as necessary, replace existing, make ranlib unneeded.
-ARFLAGS = rcs
-
+# Set our default configuration.
+#
 # Among the variables below, these:
 #   gitexecdir
 #   template_dir
@@ -561,6 +556,7 @@ perllibdir_relative = $(patsubst $(prefix)/%,%,$(perllibdir))
 
 export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
 
+# Set our default programs
 CC = cc
 AR = ar
 RM = rm -f
@@ -573,29 +569,14 @@ TCLTK_PATH = wish
 XGETTEXT = xgettext
 MSGFMT = msgfmt
 CURL_CONFIG = curl-config
-PTHREAD_LIBS = -lpthread
-PTHREAD_CFLAGS =
 GCOV = gcov
+STRIP = strip
 SPATCH = spatch
 
 export TCL_PATH TCLTK_PATH
 
-# user customisation variable for 'sparse' target
-SPARSE_FLAGS ?=
-# internal/platform customisation variable for 'sparse'
-SP_EXTRA_FLAGS =
-
-SPATCH_FLAGS = --all-includes --patch .
-
-
-
-### --- END CONFIGURATION SECTION ---
-
-# Those must not be GNU-specific; they are shared with perl/ which may
-# be built by a different compiler. (Note that this is an artifact now
-# but it still might be nice to keep that distinction.)
-BASIC_CFLAGS = -I.
-BASIC_LDFLAGS =
+# Set our default LIBS variables
+PTHREAD_LIBS = -lpthread
 
 # Guard against environment variables
 BUILTIN_OBJS =
@@ -632,7 +613,6 @@ SCRIPT_SH += git-merge-one-file.sh
 SCRIPT_SH += git-merge-resolve.sh
 SCRIPT_SH += git-mergetool.sh
 SCRIPT_SH += git-quiltimport.sh
-SCRIPT_SH += git-legacy-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
@@ -773,6 +753,7 @@ TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
 TEST_BUILTINS_OBJS += test-subprocess.o
+TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
 TEST_BUILTINS_OBJS += test-xml-encode.o
 TEST_BUILTINS_OBJS += test-wildmatch.o
@@ -841,7 +822,8 @@ VCSSVN_LIB = vcs-svn/lib.a
 
 GENERATED_H += command-list.h
 
-LIB_H = $(shell $(FIND) . \
+LIB_H := $(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
+       $(FIND) . \
        -name .git -prune -o \
        -name t -prune -o \
        -name Documentation -prune -o \
@@ -1017,6 +999,16 @@ LIB_OBJS += tempfile.o
 LIB_OBJS += thread-utils.o
 LIB_OBJS += tmp-objdir.o
 LIB_OBJS += trace.o
+LIB_OBJS += trace2.o
+LIB_OBJS += trace2/tr2_cfg.o
+LIB_OBJS += trace2/tr2_cmd_name.o
+LIB_OBJS += trace2/tr2_dst.o
+LIB_OBJS += trace2/tr2_sid.o
+LIB_OBJS += trace2/tr2_tbuf.o
+LIB_OBJS += trace2/tr2_tgt_event.o
+LIB_OBJS += trace2/tr2_tgt_normal.o
+LIB_OBJS += trace2/tr2_tgt_perf.o
+LIB_OBJS += trace2/tr2_tls.o
 LIB_OBJS += trailer.o
 LIB_OBJS += transport.o
 LIB_OBJS += transport-helper.o
@@ -1165,6 +1157,25 @@ ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/s
 DC_SHA1_SUBMODULE = auto
 endif
 
+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be
+# tweaked by config.* below as well as the command-line, both of
+# which'll override these defaults.
+CFLAGS = -g -O2 -Wall
+LDFLAGS =
+BASIC_CFLAGS = -I.
+BASIC_LDFLAGS =
+
+# library flags
+ARFLAGS = rcs
+PTHREAD_CFLAGS =
+
+# For the 'sparse' target
+SPARSE_FLAGS ?=
+SP_EXTRA_FLAGS =
+
+# For the 'coccicheck' target
+SPATCH_FLAGS = --all-includes --patch .
+
 include config.mak.uname
 -include config.mak.autogen
 -include config.mak
@@ -1173,6 +1184,9 @@ ifdef DEVELOPER
 include config.mak.dev
 endif
 
+ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS)
+ALL_LDFLAGS = $(LDFLAGS)
+
 comma := ,
 empty :=
 space := $(empty) $(empty)
@@ -1183,6 +1197,7 @@ BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)
 BASIC_CFLAGS += -fno-omit-frame-pointer
 ifneq ($(filter undefined,$(SANITIZERS)),)
 BASIC_CFLAGS += -DNO_UNALIGNED_LOADS
+BASIC_CFLAGS += -DSHA1DC_FORCE_ALIGNED_ACCESS
 endif
 ifneq ($(filter leak,$(SANITIZERS)),)
 BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
@@ -1596,7 +1611,9 @@ ifdef NO_INET_PTON
        LIB_OBJS += compat/inet_pton.o
        BASIC_CFLAGS += -DNO_INET_PTON
 endif
-ifndef NO_UNIX_SOCKETS
+ifdef NO_UNIX_SOCKETS
+       BASIC_CFLAGS += -DNO_UNIX_SOCKETS
+else
        LIB_OBJS += unix-socket.o
        PROGRAM_OBJS += credential-cache.o
        PROGRAM_OBJS += credential-cache--daemon.o
@@ -2363,7 +2380,7 @@ else
 # should _not_ be included here, since they are necessary even when
 # building an object for the first time.
 
-$(OBJECTS): $(LIB_H)
+$(OBJECTS): $(LIB_H) $(GENERATED_H)
 endif
 
 exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
@@ -2736,7 +2753,10 @@ $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
 sparse: $(SP_OBJ)
 
 GEN_HDRS := command-list.h unicode-width.h
-EXCEPT_HDRS := $(GEN_HDRS) compat% xdiff%
+EXCEPT_HDRS := $(GEN_HDRS) compat/% xdiff/%
+ifndef GCRYPT_SHA256
+       EXCEPT_HDRS += sha256/gcrypt.h
+endif
 CHK_HDRS = $(filter-out $(EXCEPT_HDRS),$(patsubst ./%,%,$(LIB_H)))
 HCO = $(patsubst %.h,%.hco,$(CHK_HDRS))
 
index 31e2135..0b6d9fd 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.21.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.22.0.txt
\ No newline at end of file
diff --git a/apply.c b/apply.c
index 892ede5..f15afa9 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -56,6 +56,10 @@ static int parse_whitespace_option(struct apply_state *state, const char *option
                state->ws_error_action = correct_ws_error;
                return 0;
        }
+       /*
+        * Please update $__git_whitespacelist in git-completion.bash
+        * when you add new options.
+        */
        return error(_("unrecognized whitespace option '%s'"), option);
 }
 
diff --git a/attr.c b/attr.c
index fdd110b..93dc16b 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -431,14 +431,14 @@ fail_return:
  * Like info/exclude and .gitignore, the attribute information can
  * come from many places.
  *
- * (1) .gitattribute file of the same directory;
- * (2) .gitattribute file of the parent directory if (1) does not have
+ * (1) .gitattributes file of the same directory;
+ * (2) .gitattributes file of the parent directory if (1) does not have
  *      any match; this goes recursively upwards, just like .gitignore.
  * (3) $GIT_DIR/info/attributes, which overrides both of the above.
  *
  * In the same file, later entries override the earlier match, so in the
  * global list, we would have entries from info/attributes the earliest
- * (reading the file from top to bottom), .gitattribute of the root
+ * (reading the file from top to bottom), .gitattributes of the root
  * directory (again, reading the file from top to bottom) down to the
  * current directory, and then scan the list backwards to find the first match.
  * This is exactly the same as what is_excluded() does in dir.c to deal with
@@ -899,7 +899,7 @@ static void prepare_attr_stack(const struct index_state *istate,
         * set of attribute definitions, followed by the contents
         * of $(prefix)/etc/gitattributes and a file specified by
         * core.attributesfile.  Then, contents from
-        * .gitattribute files from directories closer to the
+        * .gitattributes files from directories closer to the
         * root to the ones in deeper directories are pushed
         * to the stack.  Finally, at the very top of the stack
         * we always keep the contents of $GIT_DIR/info/attributes.
index 3af955c..e87ac29 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -896,24 +896,15 @@ static void show_diff_tree(struct repository *r,
                           const char *prefix,
                           struct commit *commit)
 {
+       const char *argv[] = {
+               "diff-tree", "--pretty", "--stat", "--summary", "--cc", NULL
+       };
        struct rev_info opt;
 
-       /* diff-tree init */
+       git_config(git_diff_ui_config, NULL);
        repo_init_revisions(r, &opt, prefix);
-       git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
-       opt.abbrev = 0;
-       opt.diff = 1;
 
-       /* This is what "--pretty" does */
-       opt.verbose_header = 1;
-       opt.use_terminator = 0;
-       opt.commit_format = CMIT_FMT_DEFAULT;
-
-       /* diff-tree init */
-       if (!opt.diffopt.output_format)
-               opt.diffopt.output_format = DIFF_FORMAT_RAW;
-
-       setup_revisions(0, NULL, &opt, NULL);
+       setup_revisions(ARRAY_SIZE(argv) - 1, argv, &opt, NULL);
        log_tree_commit(&opt, commit);
 }
 
diff --git a/blame.c b/blame.c
index da57233..5c07dec 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -204,7 +204,8 @@ static struct commit *fake_working_tree_commit(struct repository *r,
 
        origin = make_origin(commit, path);
 
-       ident = fmt_ident("Not Committed Yet", "not.committed.yet", NULL, 0);
+       ident = fmt_ident("Not Committed Yet", "not.committed.yet",
+                       WANT_BLANK_IDENT, NULL, 0);
        strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
        for (parent = commit->parents; parent; parent = parent->next)
                strbuf_addf(&msg, "parent %s\n",
index 58a2aef..4fb107a 100644 (file)
@@ -453,6 +453,7 @@ static int run_post_rewrite_hook(const struct am_state *state)
 
        cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
        cp.stdout_to_stderr = 1;
+       cp.trace2_hook_name = "post-rewrite";
 
        ret = run_command(&cp);
 
@@ -1579,6 +1580,7 @@ static void do_commit(const struct am_state *state)
        }
 
        author = fmt_ident(state->author_name, state->author_email,
+               WANT_AUTHOR_IDENT,
                        state->ignore_date ? NULL : state->author_date,
                        IDENT_STRICT);
 
@@ -2119,6 +2121,10 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
                *opt_value = PATCH_FORMAT_HG;
        else if (!strcmp(arg, "mboxrd"))
                *opt_value = PATCH_FORMAT_MBOXRD;
+       /*
+        * Please update $__git_patchformat in git-completion.bash
+        * when you add new options
+        */
        else
                return error(_("Invalid value for --patch-format: %s"), arg);
        return 0;
index 581de0d..177c102 100644 (file)
@@ -814,7 +814,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                 * and are only included here to get included in the "-h"
                 * output:
                 */
-               { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb },
+               { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, NULL, 0, parse_opt_unknown_cb },
 
                OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL),
                OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")),
index 1be7272..4c83055 100644 (file)
@@ -443,6 +443,21 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
        free(to_free);
 }
 
+static void print_current_branch_name(void)
+{
+       int flags;
+       const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
+       const char *shortname;
+       if (!refname)
+               die(_("could not resolve HEAD"));
+       else if (!(flags & REF_ISSYMREF))
+               return;
+       else if (skip_prefix(refname, "refs/heads/", &shortname))
+               puts(shortname);
+       else
+               die(_("HEAD (%s) points outside of refs/heads/"), refname);
+}
+
 static void reject_rebase_or_bisect_branch(const char *target)
 {
        struct worktree **worktrees = get_worktrees(0);
@@ -581,6 +596,7 @@ static int edit_branch_description(const char *branch_name)
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
        int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
+       int show_current = 0;
        int reflog = 0, edit_description = 0;
        int quiet = 0, unset_upstream = 0;
        const char *new_upstream = NULL;
@@ -620,6 +636,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
                OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
                OPT_BOOL('l', "list", &list, N_("list branch names")),
+               OPT_BOOL(0, "show-current", &show_current, N_("show current branch name")),
                OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")),
                OPT_BOOL(0, "edit-description", &edit_description,
                         N_("edit the description for the branch")),
@@ -662,14 +679,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
                             0);
 
-       if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0)
+       if (!delete && !rename && !copy && !edit_description && !new_upstream &&
+           !show_current && !unset_upstream && argc == 0)
                list = 1;
 
        if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr ||
            filter.no_commit)
                list = 1;
 
-       if (!!delete + !!rename + !!copy + !!new_upstream +
+       if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current +
            list + unset_upstream > 1)
                usage_with_options(builtin_branch_usage, options);
 
@@ -697,6 +715,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                if (!argc)
                        die(_("branch name required"));
                return delete_branches(argc, argv, delete > 1, filter.kind, quiet);
+       } else if (show_current) {
+               print_current_branch_name();
+               return 0;
        } else if (list) {
                /*  git branch --local also shows HEAD when it is detached */
                if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached)
index a56fa53..f95e797 100644 (file)
@@ -46,6 +46,7 @@ struct checkout_opts {
        int ignore_other_worktrees;
        int show_progress;
        int count_checkout_paths;
+       int overlay_mode;
        /*
         * If new checkout options are added, skip_merge_working_tree
         * should be updated accordingly.
@@ -135,7 +136,8 @@ static int skip_same_name(const struct cache_entry *ce, int pos)
        return pos;
 }
 
-static int check_stage(int stage, const struct cache_entry *ce, int pos)
+static int check_stage(int stage, const struct cache_entry *ce, int pos,
+                      int overlay_mode)
 {
        while (pos < active_nr &&
               !strcmp(active_cache[pos]->name, ce->name)) {
@@ -143,6 +145,8 @@ static int check_stage(int stage, const struct cache_entry *ce, int pos)
                        return 0;
                pos++;
        }
+       if (!overlay_mode)
+               return 0;
        if (stage == 2)
                return error(_("path '%s' does not have our version"), ce->name);
        else
@@ -168,7 +172,8 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
 }
 
 static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
-                         const struct checkout *state, int *nr_checkouts)
+                         const struct checkout *state, int *nr_checkouts,
+                         int overlay_mode)
 {
        while (pos < active_nr &&
               !strcmp(active_cache[pos]->name, ce->name)) {
@@ -177,6 +182,10 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
                                              NULL, nr_checkouts);
                pos++;
        }
+       if (!overlay_mode) {
+               unlink_entry(ce);
+               return 0;
+       }
        if (stage == 2)
                return error(_("path '%s' does not have our version"), ce->name);
        else
@@ -251,6 +260,59 @@ static int checkout_merged(int pos, const struct checkout *state, int *nr_checko
        return status;
 }
 
+static void mark_ce_for_checkout_overlay(struct cache_entry *ce,
+                                        char *ps_matched,
+                                        const struct checkout_opts *opts)
+{
+       ce->ce_flags &= ~CE_MATCHED;
+       if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
+               return;
+       if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
+               /*
+                * "git checkout tree-ish -- path", but this entry
+                * is in the original index but is not in tree-ish
+                * or does not match the pathspec; it will not be
+                * checked out to the working tree.  We will not do
+                * anything to this entry at all.
+                */
+               return;
+       /*
+        * Either this entry came from the tree-ish we are
+        * checking the paths out of, or we are checking out
+        * of the index.
+        *
+        * If it comes from the tree-ish, we already know it
+        * matches the pathspec and could just stamp
+        * CE_MATCHED to it from update_some(). But we still
+        * need ps_matched and read_tree_recursive (and
+        * eventually tree_entry_interesting) cannot fill
+        * ps_matched yet. Once it can, we can avoid calling
+        * match_pathspec() for _all_ entries when
+        * opts->source_tree != NULL.
+        */
+       if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
+               ce->ce_flags |= CE_MATCHED;
+}
+
+static void mark_ce_for_checkout_no_overlay(struct cache_entry *ce,
+                                           char *ps_matched,
+                                           const struct checkout_opts *opts)
+{
+       ce->ce_flags &= ~CE_MATCHED;
+       if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
+               return;
+       if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched)) {
+               ce->ce_flags |= CE_MATCHED;
+               if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
+                       /*
+                        * In overlay mode, but the path is not in
+                        * tree-ish, which means we should remove it
+                        * from the index and the working tree.
+                        */
+                       ce->ce_flags |= CE_REMOVE | CE_WT_REMOVE;
+       }
+}
+
 static int checkout_paths(const struct checkout_opts *opts,
                          const char *revision)
 {
@@ -263,6 +325,8 @@ static int checkout_paths(const struct checkout_opts *opts,
        struct lock_file lock_file = LOCK_INIT;
        int nr_checkouts = 0, nr_unmerged = 0;
 
+       trace2_cmd_mode(opts->patch_mode ? "patch" : "path");
+
        if (opts->track != BRANCH_TRACK_UNSPECIFIED)
                die(_("'%s' cannot be used with updating paths"), "--track");
 
@@ -302,37 +366,15 @@ static int checkout_paths(const struct checkout_opts *opts,
         * Make sure all pathspecs participated in locating the paths
         * to be checked out.
         */
-       for (pos = 0; pos < active_nr; pos++) {
-               struct cache_entry *ce = active_cache[pos];
-               ce->ce_flags &= ~CE_MATCHED;
-               if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
-                       continue;
-               if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
-                       /*
-                        * "git checkout tree-ish -- path", but this entry
-                        * is in the original index; it will not be checked
-                        * out to the working tree and it does not matter
-                        * if pathspec matched this entry.  We will not do
-                        * anything to this entry at all.
-                        */
-                       continue;
-               /*
-                * Either this entry came from the tree-ish we are
-                * checking the paths out of, or we are checking out
-                * of the index.
-                *
-                * If it comes from the tree-ish, we already know it
-                * matches the pathspec and could just stamp
-                * CE_MATCHED to it from update_some(). But we still
-                * need ps_matched and read_tree_recursive (and
-                * eventually tree_entry_interesting) cannot fill
-                * ps_matched yet. Once it can, we can avoid calling
-                * match_pathspec() for _all_ entries when
-                * opts->source_tree != NULL.
-                */
-               if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
-                       ce->ce_flags |= CE_MATCHED;
-       }
+       for (pos = 0; pos < active_nr; pos++)
+               if (opts->overlay_mode)
+                       mark_ce_for_checkout_overlay(active_cache[pos],
+                                                    ps_matched,
+                                                    opts);
+               else
+                       mark_ce_for_checkout_no_overlay(active_cache[pos],
+                                                       ps_matched,
+                                                       opts);
 
        if (report_path_error(ps_matched, &opts->pathspec, opts->prefix)) {
                free(ps_matched);
@@ -353,7 +395,7 @@ static int checkout_paths(const struct checkout_opts *opts,
                        if (opts->force) {
                                warning(_("path '%s' is unmerged"), ce->name);
                        } else if (opts->writeout_stage) {
-                               errs |= check_stage(opts->writeout_stage, ce, pos);
+                               errs |= check_stage(opts->writeout_stage, ce, pos, opts->overlay_mode);
                        } else if (opts->merge) {
                                errs |= check_stages((1<<2) | (1<<3), ce, pos);
                        } else {
@@ -383,13 +425,16 @@ static int checkout_paths(const struct checkout_opts *opts,
                        if (opts->writeout_stage)
                                errs |= checkout_stage(opts->writeout_stage,
                                                       ce, pos,
-                                                      &state, &nr_checkouts);
+                                                      &state,
+                                                      &nr_checkouts, opts->overlay_mode);
                        else if (opts->merge)
                                errs |= checkout_merged(pos, &state,
                                                        &nr_unmerged);
                        pos = skip_same_name(ce, pos) - 1;
                }
        }
+       remove_marked_cache_entries(&the_index, 1);
+       remove_scheduled_dirs();
        errs |= finish_delayed_checkout(&state, &nr_checkouts);
 
        if (opts->count_checkout_paths) {
@@ -571,6 +616,11 @@ static int skip_merge_working_tree(const struct checkout_opts *opts,
         * opts->show_progress only impacts output so doesn't require a merge
         */
 
+       /*
+        * opts->overlay_mode cannot be used with switching branches so is
+        * not tested here
+        */
+
        /*
         * If we aren't creating a new branch any changes or updates will
         * happen in the existing branch.  Since that could only be updating
@@ -975,6 +1025,9 @@ static int switch_branches(const struct checkout_opts *opts,
        void *path_to_free;
        struct object_id rev;
        int flag, writeout_error = 0;
+
+       trace2_cmd_mode("branch");
+
        memset(&old_branch_info, 0, sizeof(old_branch_info));
        old_branch_info.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag);
        if (old_branch_info.path)
@@ -1212,6 +1265,8 @@ static int switch_unborn_to_new_branch(const struct checkout_opts *opts)
        int status;
        struct strbuf branch_ref = STRBUF_INIT;
 
+       trace2_cmd_mode("unborn");
+
        if (!opts->new_branch)
                die(_("You are on a branch yet to be born"));
        strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch);
@@ -1233,6 +1288,10 @@ static int checkout_branch(struct checkout_opts *opts,
                die(_("'%s' cannot be used with switching branches"),
                    "--patch");
 
+       if (!opts->overlay_mode)
+               die(_("'%s' cannot be used with switching branches"),
+                   "--no-overlay");
+
        if (opts->writeout_stage)
                die(_("'%s' cannot be used with switching branches"),
                    "--ours/--theirs");
@@ -1321,6 +1380,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                            "checkout", "control recursive updating of submodules",
                            PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
                OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
+               OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode (default)")),
                OPT_END(),
        };
 
@@ -1329,6 +1389,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        opts.overwrite_ignore = 1;
        opts.prefix = prefix;
        opts.show_progress = -1;
+       opts.overlay_mode = -1;
 
        git_config(git_checkout_config, &opts);
 
@@ -1353,6 +1414,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
                die(_("-b, -B and --orphan are mutually exclusive"));
 
+       if (opts.overlay_mode == 1 && opts.patch_mode)
+               die(_("-p and --overlay are mutually exclusive"));
+
        /*
         * From here on, new_branch will contain the branch to be checked out,
         * and new_branch_force and new_orphan_branch will tell us which one of
index 12cc403..b866d83 100644 (file)
 #include "builtin.h"
 #include "utf8.h"
 #include "gpg-interface.h"
+#include "parse-options.h"
 
-static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1>";
+static const char * const commit_tree_usage[] = {
+       N_("git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...] "
+               "[(-F <file>)...] <tree>"),
+       NULL
+};
 
 static const char *sign_commit;
 
@@ -23,7 +28,7 @@ static void new_parent(struct commit *parent, struct commit_list **parents_p)
        struct commit_list *parents;
        for (parents = *parents_p; parents; parents = parents->next) {
                if (parents->item == parent) {
-                       error("duplicate parent %s ignored", oid_to_hex(oid));
+                       error(_("duplicate parent %s ignored"), oid_to_hex(oid));
                        return;
                }
                parents_p = &parents->next;
@@ -39,91 +44,100 @@ static int commit_tree_config(const char *var, const char *value, void *cb)
        return git_default_config(var, value, cb);
 }
 
+static int parse_parent_arg_callback(const struct option *opt,
+               const char *arg, int unset)
+{
+       struct object_id oid;
+       struct commit_list **parents = opt->value;
+
+       BUG_ON_OPT_NEG_NOARG(unset, arg);
+
+       if (get_oid_commit(arg, &oid))
+               die(_("not a valid object name %s"), arg);
+
+       assert_oid_type(&oid, OBJ_COMMIT);
+       new_parent(lookup_commit(the_repository, &oid), parents);
+       return 0;
+}
+
+static int parse_message_arg_callback(const struct option *opt,
+               const char *arg, int unset)
+{
+       struct strbuf *buf = opt->value;
+
+       BUG_ON_OPT_NEG_NOARG(unset, arg);
+
+       if (buf->len)
+               strbuf_addch(buf, '\n');
+       strbuf_addstr(buf, arg);
+       strbuf_complete_line(buf);
+
+       return 0;
+}
+
+static int parse_file_arg_callback(const struct option *opt,
+               const char *arg, int unset)
+{
+       int fd;
+       struct strbuf *buf = opt->value;
+
+       BUG_ON_OPT_NEG_NOARG(unset, arg);
+
+       if (buf->len)
+               strbuf_addch(buf, '\n');
+       if (!strcmp(arg, "-"))
+               fd = 0;
+       else {
+               fd = open(arg, O_RDONLY);
+               if (fd < 0)
+                       die_errno(_("git commit-tree: failed to open '%s'"), arg);
+       }
+       if (strbuf_read(buf, fd, 0) < 0)
+               die_errno(_("git commit-tree: failed to read '%s'"), arg);
+       if (fd && close(fd))
+               die_errno(_("git commit-tree: failed to close '%s'"), arg);
+
+       return 0;
+}
+
 int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 {
-       int i, got_tree = 0;
+       static struct strbuf buffer = STRBUF_INIT;
        struct commit_list *parents = NULL;
        struct object_id tree_oid;
        struct object_id commit_oid;
-       struct strbuf buffer = STRBUF_INIT;
+
+       struct option options[] = {
+               { OPTION_CALLBACK, 'p', NULL, &parents, N_("parent"),
+                       N_("id of a parent commit object"), PARSE_OPT_NONEG,
+                       parse_parent_arg_callback },
+               { OPTION_CALLBACK, 'm', NULL, &buffer, N_("message"),
+                       N_("commit message"), PARSE_OPT_NONEG,
+                       parse_message_arg_callback },
+               { OPTION_CALLBACK, 'F', NULL, &buffer, N_("file"),
+                       N_("read commit log message from file"), PARSE_OPT_NONEG,
+                       parse_file_arg_callback },
+               { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
+                       N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+               OPT_END()
+       };
 
        git_config(commit_tree_config, NULL);
 
        if (argc < 2 || !strcmp(argv[1], "-h"))
-               usage(commit_tree_usage);
-
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-               if (!strcmp(arg, "-p")) {
-                       struct object_id oid;
-                       if (argc <= ++i)
-                               usage(commit_tree_usage);
-                       if (get_oid_commit(argv[i], &oid))
-                               die("Not a valid object name %s", argv[i]);
-                       assert_oid_type(&oid, OBJ_COMMIT);
-                       new_parent(lookup_commit(the_repository, &oid),
-                                                &parents);
-                       continue;
-               }
+               usage_with_options(commit_tree_usage, options);
 
-               if (!strcmp(arg, "--gpg-sign")) {
-                   sign_commit = "";
-                   continue;
-               }
+       argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0);
 
-               if (skip_prefix(arg, "-S", &sign_commit) ||
-                       skip_prefix(arg, "--gpg-sign=", &sign_commit))
-                       continue;
+       if (argc != 1)
+               die(_("must give exactly one tree"));
 
-               if (!strcmp(arg, "--no-gpg-sign")) {
-                       sign_commit = NULL;
-                       continue;
-               }
-
-               if (!strcmp(arg, "-m")) {
-                       if (argc <= ++i)
-                               usage(commit_tree_usage);
-                       if (buffer.len)
-                               strbuf_addch(&buffer, '\n');
-                       strbuf_addstr(&buffer, argv[i]);
-                       strbuf_complete_line(&buffer);
-                       continue;
-               }
-
-               if (!strcmp(arg, "-F")) {
-                       int fd;
-
-                       if (argc <= ++i)
-                               usage(commit_tree_usage);
-                       if (buffer.len)
-                               strbuf_addch(&buffer, '\n');
-                       if (!strcmp(argv[i], "-"))
-                               fd = 0;
-                       else {
-                               fd = open(argv[i], O_RDONLY);
-                               if (fd < 0)
-                                       die_errno("git commit-tree: failed to open '%s'",
-                                                 argv[i]);
-                       }
-                       if (strbuf_read(&buffer, fd, 0) < 0)
-                               die_errno("git commit-tree: failed to read '%s'",
-                                         argv[i]);
-                       if (fd && close(fd))
-                               die_errno("git commit-tree: failed to close '%s'",
-                                         argv[i]);
-                       continue;
-               }
-
-               if (get_oid_tree(arg, &tree_oid))
-                       die("Not a valid object name %s", arg);
-               if (got_tree)
-                       die("Cannot give more than one trees");
-               got_tree = 1;
-       }
+       if (get_oid_tree(argv[0], &tree_oid))
+               die(_("not a valid object name %s"), argv[0]);
 
        if (!buffer.len) {
                if (strbuf_read(&buffer, 0, 0) < 0)
-                       die_errno("git commit-tree: failed to read");
+                       die_errno(_("git commit-tree: failed to read"));
        }
 
        if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
index 2986553..f175374 100644 (file)
@@ -609,7 +609,8 @@ static void determine_author_info(struct strbuf *author_ident)
                set_ident_var(&date, strbuf_detach(&date_buf, NULL));
        }
 
-       strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
+       strbuf_addstr(author_ident, fmt_ident(name, email, WANT_AUTHOR_IDENT, date,
+                               IDENT_STRICT));
        assert_split_ident(&author, author_ident);
        export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
        export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
@@ -1038,6 +1039,10 @@ static void handle_untracked_files_arg(struct wt_status *s)
                s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
        else if (!strcmp(untracked_files_arg, "all"))
                s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+       /*
+        * Please update $__git_untracked_file_modes in
+        * git-completion.bash when you add new options
+        */
        else
                die(_("Invalid untracked files mode '%s'"), untracked_files_arg);
 }
@@ -1179,6 +1184,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
        else if (!strcmp(cleanup_arg, "scissors"))
                cleanup_mode = use_editor ? COMMIT_MSG_CLEANUP_SCISSORS :
                                            COMMIT_MSG_CLEANUP_SPACE;
+       /*
+        * Please update _git_commit() in git-completion.bash when you
+        * add new options.
+        */
        else
                die(_("Invalid cleanup mode %s"), cleanup_arg);
 
index a90681b..cb9ea79 100644 (file)
@@ -83,9 +83,13 @@ static int diff_tree_stdin(char *line)
 }
 
 static const char diff_tree_usage[] =
-"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
+"git diff-tree [--stdin] [-m] [-c | --cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
 "[<common-diff-options>] <tree-ish> [<tree-ish>] [<path>...]\n"
 "  -r            diff recursively\n"
+"  -c            show combined diff for merge commits\n"
+"  --cc          show combined diff for merge commits removing uninteresting hunks\n"
+"  --combined-all-paths\n"
+"                show name of file in all parents for combined diffs\n"
 "  --root        include the initial commit as diff against /dev/null\n"
 COMMON_DIFF_OPTIONS_HELP;
 
index 9f61092..53d4234 100644 (file)
@@ -338,21 +338,23 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                       "--no-index" : "[--no-index]");
 
        }
-       if (no_index)
-               /* If this is a no-index diff, just run it and exit there. */
-               diff_no_index(the_repository, &rev, argc, argv);
-
-       /* Otherwise, we are doing the usual "git" diff */
-       rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
 
-       /* Scale to real terminal size and respect statGraphWidth config */
+       /* Set up defaults that will apply to both no-index and regular diffs. */
        rev.diffopt.stat_width = -1;
        rev.diffopt.stat_graph_width = -1;
-
-       /* Default to let external and textconv be used */
        rev.diffopt.flags.allow_external = 1;
        rev.diffopt.flags.allow_textconv = 1;
 
+       /* If this is a no-index diff, just run it and exit there. */
+       if (no_index)
+               diff_no_index(&rev, argc, argv);
+
+       /*
+        * Otherwise, we are doing the usual "git" diff; set up any
+        * further defaults that apply to regular diffs.
+        */
+       rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
+
        /*
         * Default to intent-to-add entries invisible in the
         * index. This makes them show up as new files in diff-files
index b620fd5..4ba63d5 100644 (file)
@@ -1556,7 +1556,9 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int pru
 
        sigchain_push_common(unlock_pack_on_signal);
        atexit(unlock_pack);
+       sigchain_push(SIGPIPE, SIG_IGN);
        exit_code = do_fetch(gtransport, &rs);
+       sigchain_pop(SIGPIPE);
        refspec_clear(&rs);
        transport_disconnect(gtransport);
        gtransport = NULL;
index bb4227b..d26fb0a 100644 (file)
@@ -235,6 +235,48 @@ static int mark_used(struct object *obj, int type, void *data, struct fsck_optio
        return 0;
 }
 
+static void mark_unreachable_referents(const struct object_id *oid)
+{
+       struct fsck_options options = FSCK_OPTIONS_DEFAULT;
+       struct object *obj = lookup_object(the_repository, oid->hash);
+
+       if (!obj || !(obj->flags & HAS_OBJ))
+               return; /* not part of our original set */
+       if (obj->flags & REACHABLE)
+               return; /* reachable objects already traversed */
+
+       /*
+        * Avoid passing OBJ_NONE to fsck_walk, which will parse the object
+        * (and we want to avoid parsing blobs).
+        */
+       if (obj->type == OBJ_NONE) {
+               enum object_type type = oid_object_info(the_repository,
+                                                       &obj->oid, NULL);
+               if (type > 0)
+                       object_as_type(the_repository, obj, type, 0);
+       }
+
+       options.walk = mark_used;
+       fsck_walk(obj, NULL, &options);
+}
+
+static int mark_loose_unreachable_referents(const struct object_id *oid,
+                                           const char *path,
+                                           void *data)
+{
+       mark_unreachable_referents(oid);
+       return 0;
+}
+
+static int mark_packed_unreachable_referents(const struct object_id *oid,
+                                            struct packed_git *pack,
+                                            uint32_t pos,
+                                            void *data)
+{
+       mark_unreachable_referents(oid);
+       return 0;
+}
+
 /*
  * Check a single reachable object
  */
@@ -347,6 +389,26 @@ static void check_connectivity(void)
        /* Traverse the pending reachable objects */
        traverse_reachable();
 
+       /*
+        * With --connectivity-only, we won't have actually opened and marked
+        * unreachable objects with USED. Do that now to make --dangling, etc
+        * accurate.
+        */
+       if (connectivity_only && (show_dangling || write_lost_and_found)) {
+               /*
+                * Even though we already have a "struct object" for each of
+                * these in memory, we must not iterate over the internal
+                * object hash as we do below. Our loop would potentially
+                * resize the hash, making our iteration invalid.
+                *
+                * Instead, we'll just go back to the source list of objects,
+                * and ignore any that weren't present in our earlier
+                * traversal.
+                */
+               for_each_loose_object(mark_loose_unreachable_referents, NULL, 0);
+               for_each_packed_object(mark_packed_unreachable_referents, NULL, 0);
+       }
+
        /* Look up all the requirements, warn about missing objects.. */
        max = get_max_object_index();
        if (verbose)
index 7739a5c..e5590d7 100644 (file)
@@ -70,6 +70,10 @@ static enum help_format parse_help_format(const char *format)
                return HELP_FORMAT_INFO;
        if (!strcmp(format, "web") || !strcmp(format, "html"))
                return HELP_FORMAT_WEB;
+       /*
+        * Please update _git_config() in git-completion.bash when you
+        * add new help formats.
+        */
        die(_("unrecognized help format '%s'"), format);
 }
 
index 93eff76..6ca0028 100644 (file)
@@ -96,7 +96,7 @@ static void copy_templates(const char *template_dir)
        struct strbuf path = STRBUF_INIT;
        struct strbuf template_path = STRBUF_INIT;
        size_t template_len;
-       struct repository_format template_format;
+       struct repository_format template_format = REPOSITORY_FORMAT_INIT;
        struct strbuf err = STRBUF_INIT;
        DIR *dir;
        char *to_free = NULL;
@@ -148,6 +148,7 @@ free_return:
        free(to_free);
        strbuf_release(&path);
        strbuf_release(&template_path);
+       clear_repository_format(&template_format);
 }
 
 static int git_init_db_config(const char *k, const char *v, void *cb)
@@ -155,6 +156,9 @@ static int git_init_db_config(const char *k, const char *v, void *cb)
        if (!strcmp(k, "init.templatedir"))
                return git_config_pathname(&init_db_template_dir, k, v);
 
+       if (starts_with(k, "core."))
+               return platform_core_config(k, v, cb);
+
        return 0;
 }
 
@@ -185,6 +189,7 @@ static int create_default_files(const char *template_path,
        struct strbuf err = STRBUF_INIT;
 
        /* Just look for `init.templatedir` */
+       init_db_template_dir = NULL; /* re-set in case it was set before */
        git_config(git_init_db_config, NULL);
 
        /*
@@ -361,6 +366,9 @@ int init_db(const char *git_dir, const char *real_git_dir,
        }
        startup_info->have_repository = 1;
 
+       /* Just look for `core.hidedotfiles` */
+       git_config(git_init_db_config, NULL);
+
        safe_create_dir(git_dir, 0);
 
        init_is_bare_repository = is_bare_repository();
index 5786926..e63c8c2 100644 (file)
@@ -84,6 +84,10 @@ static int parse_decoration_style(const char *value)
                return DECORATE_SHORT_REFS;
        else if (!strcmp(value, "auto"))
                return auto_decoration_style();
+       /*
+        * Please update _git_log() in git-completion.bash when you
+        * add new decoration styles.
+        */
        return -1;
 }
 
@@ -513,7 +517,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
        if (get_oid_with_context(the_repository, obj_name,
                                 GET_OID_RECORD_PATH,
                                 &oidc, &obj_context))
-               die(_("Not a valid object name %s"), obj_name);
+               die(_("not a valid object name %s"), obj_name);
        if (!obj_context.path ||
            !textconv_object(the_repository, obj_context.path,
                             obj_context.mode, &oidc, 1, &buf, &size)) {
@@ -537,7 +541,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
        int offset = 0;
 
        if (!buf)
-               return error(_("Could not read object %s"), oid_to_hex(oid));
+               return error(_("could not read object %s"), oid_to_hex(oid));
 
        assert(type == OBJ_TAG);
        while (offset < size && buf[offset] != '\n') {
@@ -631,7 +635,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                                break;
                        o = parse_object(the_repository, &t->tagged->oid);
                        if (!o)
-                               ret = error(_("Could not read object %s"),
+                               ret = error(_("could not read object %s"),
                                            oid_to_hex(&t->tagged->oid));
                        objects[i].item = o;
                        i--;
@@ -656,7 +660,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                        ret = cmd_log_walk(&rev);
                        break;
                default:
-                       ret = error(_("Unknown type: %d"), o->type);
+                       ret = error(_("unknown type: %d"), o->type);
                }
        }
        free(objects);
@@ -894,7 +898,7 @@ static int open_next_file(struct commit *commit, const char *subject,
                printf("%s\n", filename.buf + outdir_offset);
 
        if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
-               error_errno(_("Cannot open patch file %s"), filename.buf);
+               error_errno(_("cannot open patch file %s"), filename.buf);
                strbuf_release(&filename);
                return -1;
        }
@@ -911,7 +915,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
        unsigned flags1, flags2;
 
        if (rev->pending.nr != 2)
-               die(_("Need exactly one range."));
+               die(_("need exactly one range"));
 
        o1 = rev->pending.objects[0].item;
        o2 = rev->pending.objects[1].item;
@@ -921,7 +925,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
        c2 = lookup_commit_reference(the_repository, &o2->oid);
 
        if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
-               die(_("Not a range."));
+               die(_("not a range"));
 
        init_patch_ids(the_repository, ids);
 
@@ -1044,13 +1048,13 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
        struct commit *head = list[0];
 
        if (!cmit_fmt_is_mail(rev->commit_format))
-               die(_("Cover letter needs email format"));
+               die(_("cover letter needs email format"));
 
        committer = git_committer_info(0);
 
        if (!use_stdout &&
            open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
-               return;
+               die(_("failed to create cover-letter file"));
 
        log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
 
@@ -1214,7 +1218,7 @@ static int output_directory_callback(const struct option *opt, const char *arg,
        const char **dir = (const char **)opt->value;
        BUG_ON_OPT_NEG(unset);
        if (*dir)
-               die(_("Two output directories?"));
+               die(_("two output directories?"));
        *dir = arg;
        return 0;
 }
@@ -1228,6 +1232,10 @@ static int thread_callback(const struct option *opt, const char *arg, int unset)
                *thread = THREAD_SHALLOW;
        else if (!strcmp(arg, "deep"))
                *thread = THREAD_DEEP;
+       /*
+        * Please update _git_formatpatch() in git-completion.bash
+        * when you add new options.
+        */
        else
                return 1;
        return 0;
@@ -1321,7 +1329,7 @@ static struct commit *get_base_commit(const char *base_commit,
        if (base_commit && strcmp(base_commit, "auto")) {
                base = lookup_commit_reference_by_name(base_commit);
                if (!base)
-                       die(_("Unknown commit %s"), base_commit);
+                       die(_("unknown commit %s"), base_commit);
        } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) {
                struct branch *curr_branch = branch_get(NULL);
                const char *upstream = branch_get_upstream(curr_branch, NULL);
@@ -1331,18 +1339,18 @@ static struct commit *get_base_commit(const char *base_commit,
                        struct object_id oid;
 
                        if (get_oid(upstream, &oid))
-                               die(_("Failed to resolve '%s' as a valid ref."), upstream);
+                               die(_("failed to resolve '%s' as a valid ref"), upstream);
                        commit = lookup_commit_or_die(&oid, "upstream base");
                        base_list = get_merge_bases_many(commit, total, list);
                        /* There should be one and only one merge base. */
                        if (!base_list || base_list->next)
-                               die(_("Could not find exact merge base."));
+                               die(_("could not find exact merge base"));
                        base = base_list->item;
                        free_commit_list(base_list);
                } else {
-                       die(_("Failed to get upstream, if you want to record base commit automatically,\n"
+                       die(_("failed to get upstream, if you want to record base commit automatically,\n"
                              "please use git branch --set-upstream-to to track a remote branch.\n"
-                             "Or you could specify base commit by --base=<base-commit-id> manually."));
+                             "Or you could specify base commit by --base=<base-commit-id> manually"));
                }
        }
 
@@ -1360,7 +1368,7 @@ static struct commit *get_base_commit(const char *base_commit,
                        struct commit_list *merge_base;
                        merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
                        if (!merge_base || merge_base->next)
-                               die(_("Failed to find exact merge base"));
+                               die(_("failed to find exact merge base"));
 
                        rev[i] = merge_base->item;
                }
@@ -1739,7 +1747,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                if (use_stdout)
                        die(_("standard output, or directory, which one?"));
                if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
-                       die_errno(_("Could not create directory '%s'"),
+                       die_errno(_("could not create directory '%s'"),
                                  output_directory);
        }
 
@@ -1941,7 +1949,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 
                if (!use_stdout &&
                    open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
-                       die(_("Failed to create output files"));
+                       die(_("failed to create output files"));
                shown = log_tree_commit(&rev, commit);
                free_commit_buffer(the_repository->parsed_objects,
                                   commit);
@@ -2065,9 +2073,9 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        revs.max_parents = 1;
 
        if (add_pending_commit(head, &revs, 0))
-               die(_("Unknown commit %s"), head);
+               die(_("unknown commit %s"), head);
        if (add_pending_commit(upstream, &revs, UNINTERESTING))
-               die(_("Unknown commit %s"), upstream);
+               die(_("unknown commit %s"), upstream);
 
        /* Don't say anything if head and upstream are the same. */
        if (revs.pending.nr == 2) {
@@ -2079,7 +2087,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        get_patch_ids(&revs, &ids);
 
        if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
-               die(_("Unknown commit %s"), limit);
+               die(_("unknown commit %s"), limit);
 
        /* reverse the list of commits */
        if (prepare_revision_walk(&revs))
index e47d77b..5ce8946 100644 (file)
@@ -113,12 +113,15 @@ static int option_parse_message(const struct option *opt,
        return 0;
 }
 
-static int option_read_message(struct parse_opt_ctx_t *ctx,
-                              const struct option *opt, int unset)
+static enum parse_opt_result option_read_message(struct parse_opt_ctx_t *ctx,
+                                                const struct option *opt,
+                                                const char *arg_not_used,
+                                                int unset)
 {
        struct strbuf *buf = opt->value;
        const char *arg;
 
+       BUG_ON_OPT_ARG(arg_not_used);
        if (unset)
                BUG("-F cannot be negated");
 
@@ -262,7 +265,7 @@ static struct option builtin_merge_options[] = {
                option_parse_message),
        { OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"),
                N_("read message from file"), PARSE_OPT_NONEG,
-               (parse_opt_cb *) option_read_message },
+               NULL, 0, option_read_message },
        OPT__VERBOSITY(&verbosity),
        OPT_BOOL(0, "abort", &abort_current_merge,
                N_("abort the current in-progress merge")),
index a9fac7c..a154fc2 100644 (file)
@@ -33,6 +33,7 @@
 #include "object-store.h"
 #include "dir.h"
 #include "midx.h"
+#include "trace2.h"
 
 #define IN_PACK(obj) oe_in_pack(&to_pack, obj)
 #define SIZE(obj) oe_size(&to_pack, obj)
@@ -3473,6 +3474,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                }
        }
 
+       trace2_region_enter("pack-objects", "enumerate-objects",
+                           the_repository);
        prepare_packing_data(the_repository, &to_pack);
 
        if (progress)
@@ -3487,12 +3490,23 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        if (include_tag && nr_result)
                for_each_ref(add_ref_tag, NULL);
        stop_progress(&progress_state);
+       trace2_region_leave("pack-objects", "enumerate-objects",
+                           the_repository);
 
        if (non_empty && !nr_result)
                return 0;
-       if (nr_result)
+       if (nr_result) {
+               trace2_region_enter("pack-objects", "prepare-pack",
+                                   the_repository);
                prepare_pack(window, depth);
+               trace2_region_leave("pack-objects", "prepare-pack",
+                                   the_repository);
+       }
+
+       trace2_region_enter("pack-objects", "write-pack-file", the_repository);
        write_pack_file();
+       trace2_region_leave("pack-objects", "write-pack-file", the_repository);
+
        if (progress)
                fprintf_ln(stderr,
                           _("Total %"PRIu32" (delta %"PRIu32"),"
index 11bc514..68c1e54 100644 (file)
@@ -32,14 +32,10 @@ static struct pack_list {
        struct pack_list *next;
        struct packed_git *pack;
        struct llist *unique_objects;
-       struct llist *all_objects;
+       struct llist *remaining_objects;
+       size_t all_objects_size;
 } *local_packs = NULL, *altodb_packs = NULL;
 
-struct pll {
-       struct pll *next;
-       struct pack_list *pl;
-};
-
 static struct llist_item *free_nodes;
 
 static inline void llist_item_put(struct llist_item *item)
@@ -63,15 +59,6 @@ static inline struct llist_item *llist_item_get(void)
        return new_item;
 }
 
-static void llist_free(struct llist *list)
-{
-       while ((list->back = list->front)) {
-               list->front = list->front->next;
-               llist_item_put(list->back);
-       }
-       free(list);
-}
-
 static inline void llist_init(struct llist **list)
 {
        *list = xmalloc(sizeof(struct llist));
@@ -254,6 +241,11 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
        struct llist_item *p1_hint = NULL, *p2_hint = NULL;
        const unsigned int hashsz = the_hash_algo->rawsz;
 
+       if (!p1->unique_objects)
+               p1->unique_objects = llist_copy(p1->remaining_objects);
+       if (!p2->unique_objects)
+               p2->unique_objects = llist_copy(p2->remaining_objects);
+
        p1_base = p1->pack->index_data;
        p2_base = p2->pack->index_data;
        p1_base += 256 * 4 + ((p1->pack->index_version < 2) ? 4 : 8);
@@ -285,78 +277,6 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
        }
 }
 
-static void pll_free(struct pll *l)
-{
-       struct pll *old;
-       struct pack_list *opl;
-
-       while (l) {
-               old = l;
-               while (l->pl) {
-                       opl = l->pl;
-                       l->pl = opl->next;
-                       free(opl);
-               }
-               l = l->next;
-               free(old);
-       }
-}
-
-/* all the permutations have to be free()d at the same time,
- * since they refer to each other
- */
-static struct pll * get_permutations(struct pack_list *list, int n)
-{
-       struct pll *subset, *ret = NULL, *new_pll = NULL;
-
-       if (list == NULL || pack_list_size(list) < n || n == 0)
-               return NULL;
-
-       if (n == 1) {
-               while (list) {
-                       new_pll = xmalloc(sizeof(*new_pll));
-                       new_pll->pl = NULL;
-                       pack_list_insert(&new_pll->pl, list);
-                       new_pll->next = ret;
-                       ret = new_pll;
-                       list = list->next;
-               }
-               return ret;
-       }
-
-       while (list->next) {
-               subset = get_permutations(list->next, n - 1);
-               while (subset) {
-                       new_pll = xmalloc(sizeof(*new_pll));
-                       new_pll->pl = subset->pl;
-                       pack_list_insert(&new_pll->pl, list);
-                       new_pll->next = ret;
-                       ret = new_pll;
-                       subset = subset->next;
-               }
-               list = list->next;
-       }
-       return ret;
-}
-
-static int is_superset(struct pack_list *pl, struct llist *list)
-{
-       struct llist *diff;
-
-       diff = llist_copy(list);
-
-       while (pl) {
-               llist_sorted_difference_inplace(diff, pl->all_objects);
-               if (diff->size == 0) { /* we're done */
-                       llist_free(diff);
-                       return 1;
-               }
-               pl = pl->next;
-       }
-       llist_free(diff);
-       return 0;
-}
-
 static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)
 {
        size_t ret = 0;
@@ -421,14 +341,58 @@ static inline off_t pack_set_bytecount(struct pack_list *pl)
        return ret;
 }
 
+static int cmp_remaining_objects(const void *a, const void *b)
+{
+       struct pack_list *pl_a = *((struct pack_list **)a);
+       struct pack_list *pl_b = *((struct pack_list **)b);
+
+       if (pl_a->remaining_objects->size == pl_b->remaining_objects->size) {
+               /* have the same remaining_objects, big pack first */
+               if (pl_a->all_objects_size == pl_b->all_objects_size)
+                       return 0;
+               else if (pl_a->all_objects_size < pl_b->all_objects_size)
+                       return 1;
+               else
+                       return -1;
+       } else if (pl_a->remaining_objects->size < pl_b->remaining_objects->size) {
+               /* sort by remaining objects, more objects first */
+               return 1;
+       } else {
+               return -1;
+       }
+}
+
+/* Sort pack_list, greater size of remaining_objects first */
+static void sort_pack_list(struct pack_list **pl)
+{
+       struct pack_list **ary, *p;
+       int i;
+       size_t n = pack_list_size(*pl);
+
+       if (n < 2)
+               return;
+
+       /* prepare an array of packed_list for easier sorting */
+       ary = xcalloc(n, sizeof(struct pack_list *));
+       for (n = 0, p = *pl; p; p = p->next)
+               ary[n++] = p;
+
+       QSORT(ary, n, cmp_remaining_objects);
+
+       /* link them back again */
+       for (i = 0; i < n - 1; i++)
+               ary[i]->next = ary[i + 1];
+       ary[n - 1]->next = NULL;
+       *pl = ary[0];
+
+       free(ary);
+}
+
+
 static void minimize(struct pack_list **min)
 {
-       struct pack_list *pl, *unique = NULL,
-               *non_unique = NULL, *min_perm = NULL;
-       struct pll *perm, *perm_all, *perm_ok = NULL, *new_perm;
-       struct llist *missing;
-       off_t min_perm_size = 0, perm_size;
-       int n;
+       struct pack_list *pl, *unique = NULL, *non_unique = NULL;
+       struct llist *missing, *unique_pack_objects;
 
        pl = local_packs;
        while (pl) {
@@ -442,53 +406,41 @@ static void minimize(struct pack_list **min)
        missing = llist_copy(all_objects);
        pl = unique;
        while (pl) {
-               llist_sorted_difference_inplace(missing, pl->all_objects);
+               llist_sorted_difference_inplace(missing, pl->remaining_objects);
                pl = pl->next;
        }
 
+       *min = unique;
+
        /* return if there are no objects missing from the unique set */
        if (missing->size == 0) {
-               *min = unique;
                free(missing);
                return;
        }
 
-       /* find the permutations which contain all missing objects */
-       for (n = 1; n <= pack_list_size(non_unique) && !perm_ok; n++) {
-               perm_all = perm = get_permutations(non_unique, n);
-               while (perm) {
-                       if (is_superset(perm->pl, missing)) {
-                               new_perm = xmalloc(sizeof(struct pll));
-                               memcpy(new_perm, perm, sizeof(struct pll));
-                               new_perm->next = perm_ok;
-                               perm_ok = new_perm;
-                       }
-                       perm = perm->next;
-               }
-               if (perm_ok)
-                       break;
-               pll_free(perm_all);
-       }
-       if (perm_ok == NULL)
-               die("Internal error: No complete sets found!");
-
-       /* find the permutation with the smallest size */
-       perm = perm_ok;
-       while (perm) {
-               perm_size = pack_set_bytecount(perm->pl);
-               if (!min_perm_size || min_perm_size > perm_size) {
-                       min_perm_size = perm_size;
-                       min_perm = perm->pl;
-               }
-               perm = perm->next;
-       }
-       *min = min_perm;
-       /* add the unique packs to the list */
-       pl = unique;
+       unique_pack_objects = llist_copy(all_objects);
+       llist_sorted_difference_inplace(unique_pack_objects, missing);
+
+       /* remove unique pack objects from the non_unique packs */
+       pl = non_unique;
        while (pl) {
-               pack_list_insert(min, pl);
+               llist_sorted_difference_inplace(pl->remaining_objects, unique_pack_objects);
                pl = pl->next;
        }
+
+       while (non_unique) {
+               /* sort the non_unique packs, greater size of remaining_objects first */
+               sort_pack_list(&non_unique);
+               if (non_unique->remaining_objects->size == 0)
+                       break;
+
+               pack_list_insert(min, non_unique);
+
+               for (pl = non_unique->next; pl && pl->remaining_objects->size > 0;  pl = pl->next)
+                       llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects);
+
+               non_unique = non_unique->next;
+       }
 }
 
 static void load_all_objects(void)
@@ -500,7 +452,7 @@ static void load_all_objects(void)
 
        while (pl) {
                hint = NULL;
-               l = pl->all_objects->front;
+               l = pl->remaining_objects->front;
                while (l) {
                        hint = llist_insert_sorted_unique(all_objects,
                                                          l->oid, hint);
@@ -511,7 +463,7 @@ static void load_all_objects(void)
        /* remove objects present in remote packs */
        pl = altodb_packs;
        while (pl) {
-               llist_sorted_difference_inplace(all_objects, pl->all_objects);
+               llist_sorted_difference_inplace(all_objects, pl->remaining_objects);
                pl = pl->next;
        }
 }
@@ -536,11 +488,10 @@ static void scan_alt_odb_packs(void)
        while (alt) {
                local = local_packs;
                while (local) {
-                       llist_sorted_difference_inplace(local->unique_objects,
-                                                       alt->all_objects);
+                       llist_sorted_difference_inplace(local->remaining_objects,
+                                                       alt->remaining_objects);
                        local = local->next;
                }
-               llist_sorted_difference_inplace(all_objects, alt->all_objects);
                alt = alt->next;
        }
 }
@@ -555,7 +506,7 @@ static struct pack_list * add_pack(struct packed_git *p)
                return NULL;
 
        l.pack = p;
-       llist_init(&l.all_objects);
+       llist_init(&l.remaining_objects);
 
        if (open_pack_index(p))
                return NULL;
@@ -564,11 +515,11 @@ static struct pack_list * add_pack(struct packed_git *p)
        base += 256 * 4 + ((p->index_version < 2) ? 4 : 8);
        step = the_hash_algo->rawsz + ((p->index_version < 2) ? 4 : 0);
        while (off < p->num_objects * step) {
-               llist_insert_back(l.all_objects, (const struct object_id *)(base + off));
+               llist_insert_back(l.remaining_objects, (const struct object_id *)(base + off));
                off += step;
        }
-       /* this list will be pruned in cmp_two_packs later */
-       l.unique_objects = llist_copy(l.all_objects);
+       l.all_objects_size = l.remaining_objects->size;
+       l.unique_objects = NULL;
        if (p->pack_local)
                return pack_list_insert(&local_packs, &l);
        else
@@ -603,7 +554,7 @@ static void load_all(void)
 int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
 {
        int i;
-       struct pack_list *min, *red, *pl;
+       struct pack_list *min = NULL, *red, *pl;
        struct llist *ignore;
        struct object_id *oid;
        char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
@@ -646,7 +597,6 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
 
        load_all_objects();
 
-       cmp_local_packs();
        if (alt_odb)
                scan_alt_odb_packs();
 
@@ -663,10 +613,12 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
        llist_sorted_difference_inplace(all_objects, ignore);
        pl = local_packs;
        while (pl) {
-               llist_sorted_difference_inplace(pl->unique_objects, ignore);
+               llist_sorted_difference_inplace(pl->remaining_objects, ignore);
                pl = pl->next;
        }
 
+       cmp_local_packs();
+
        minimize(&min);
 
        if (verbose) {
index a9e7b55..48c5e78 100644 (file)
@@ -63,6 +63,11 @@ int cmd_prune_packed(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, prune_packed_options,
                             prune_packed_usage, 0);
 
+       if (argc > 0)
+               usage_msg_opt(_("too many arguments"),
+                             prune_packed_usage,
+                             prune_packed_options);
+
        prune_packed_objects(opts);
        return 0;
 }
index 1ec9ddd..97613ec 100644 (file)
@@ -31,16 +31,39 @@ static int prune_tmp_file(const char *fullpath)
        return 0;
 }
 
+static void perform_reachability_traversal(struct rev_info *revs)
+{
+       static int initialized;
+       struct progress *progress = NULL;
+
+       if (initialized)
+               return;
+
+       if (show_progress)
+               progress = start_delayed_progress(_("Checking connectivity"), 0);
+       mark_reachable_objects(revs, 1, expire, progress);
+       stop_progress(&progress);
+       initialized = 1;
+}
+
+static int is_object_reachable(const struct object_id *oid,
+                              struct rev_info *revs)
+{
+       struct object *obj;
+
+       perform_reachability_traversal(revs);
+
+       obj = lookup_object(the_repository, oid->hash);
+       return obj && (obj->flags & SEEN);
+}
+
 static int prune_object(const struct object_id *oid, const char *fullpath,
                        void *data)
 {
+       struct rev_info *revs = data;
        struct stat st;
 
-       /*
-        * Do we know about this object?
-        * It must have been reachable
-        */
-       if (lookup_object(the_repository, oid->hash))
+       if (is_object_reachable(oid, revs))
                return 0;
 
        if (lstat(fullpath, &st)) {
@@ -102,7 +125,6 @@ static void remove_temporary_files(const char *path)
 int cmd_prune(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
-       struct progress *progress = NULL;
        int exclude_promisor_objects = 0;
        const struct option options[] = {
                OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
@@ -142,17 +164,13 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 
        if (show_progress == -1)
                show_progress = isatty(2);
-       if (show_progress)
-               progress = start_delayed_progress(_("Checking connectivity"), 0);
        if (exclude_promisor_objects) {
                fetch_if_missing = 0;
                revs.exclude_promisor_objects = 1;
        }
 
-       mark_reachable_objects(&revs, 1, expire, progress);
-       stop_progress(&progress);
        for_each_loose_file_in_objdir(get_object_directory(), prune_object,
-                                     prune_cruft, prune_subdir, NULL);
+                                     prune_cruft, prune_subdir, &revs);
 
        prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
        remove_temporary_files(get_object_directory());
@@ -160,8 +178,10 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
        remove_temporary_files(s);
        free(s);
 
-       if (is_repository_shallow(the_repository))
+       if (is_repository_shallow(the_repository)) {
+               perform_reachability_traversal(&revs);
                prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0);
+       }
 
        return 0;
 }
index 701d147..33db889 100644 (file)
@@ -56,6 +56,10 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
                return REBASE_MERGES;
        else if (!strcmp(value, "interactive") || !strcmp(value, "i"))
                return REBASE_INTERACTIVE;
+       /*
+        * Please update _git_config() in git-completion.bash when you
+        * add new rebase modes.
+        */
 
        if (fatal)
                die(_("Invalid value for %s: %s"), key, value);
index 7c7bc13..2e41ad5 100644 (file)
@@ -46,29 +46,6 @@ enum rebase_type {
        REBASE_PRESERVE_MERGES
 };
 
-static int use_builtin_rebase(void)
-{
-       struct child_process cp = CHILD_PROCESS_INIT;
-       struct strbuf out = STRBUF_INIT;
-       int ret, env = git_env_bool("GIT_TEST_REBASE_USE_BUILTIN", -1);
-
-       if (env != -1)
-               return env;
-
-       argv_array_pushl(&cp.args,
-                        "config", "--bool", "rebase.usebuiltin", NULL);
-       cp.git_cmd = 1;
-       if (capture_command(&cp, &out, 6)) {
-               strbuf_release(&out);
-               return 1;
-       }
-
-       strbuf_trim(&out);
-       ret = !strcmp("true", out.buf);
-       strbuf_release(&out);
-       return ret;
-}
-
 struct rebase_options {
        enum rebase_type type;
        const char *state_dir;
@@ -106,6 +83,7 @@ struct rebase_options {
        char *strategy, *strategy_opts;
        struct strbuf git_format_patch_opt;
        int reschedule_failed_exec;
+       int use_legacy_rebase;
 };
 
 static int is_interactive(struct rebase_options *opts)
@@ -369,6 +347,7 @@ static void add_var(struct strbuf *buf, const char *name, const char *value)
 #define RESET_HEAD_HARD (1<<1)
 #define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
 #define RESET_HEAD_REFS_ONLY (1<<3)
+#define RESET_ORIG_HEAD (1<<4)
 
 static int reset_head(struct object_id *oid, const char *action,
                      const char *switch_to_branch, unsigned flags,
@@ -378,6 +357,7 @@ static int reset_head(struct object_id *oid, const char *action,
        unsigned reset_hard = flags & RESET_HEAD_HARD;
        unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
        unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
+       unsigned update_orig_head = flags & RESET_ORIG_HEAD;
        struct object_id head_oid;
        struct tree_desc desc[2] = { { NULL }, { NULL } };
        struct lock_file lock = LOCK_INIT;
@@ -454,18 +434,21 @@ reset_head_refs:
        strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
        prefix_len = msg.len;
 
-       if (!get_oid("ORIG_HEAD", &oid_old_orig))
-               old_orig = &oid_old_orig;
-       if (!get_oid("HEAD", &oid_orig)) {
-               orig = &oid_orig;
-               if (!reflog_orig_head) {
-                       strbuf_addstr(&msg, "updating ORIG_HEAD");
-                       reflog_orig_head = msg.buf;
-               }
-               update_ref(reflog_orig_head, "ORIG_HEAD", orig, old_orig, 0,
-                          UPDATE_REFS_MSG_ON_ERR);
-       } else if (old_orig)
-               delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
+       if (update_orig_head) {
+               if (!get_oid("ORIG_HEAD", &oid_old_orig))
+                       old_orig = &oid_old_orig;
+               if (!get_oid("HEAD", &oid_orig)) {
+                       orig = &oid_orig;
+                       if (!reflog_orig_head) {
+                               strbuf_addstr(&msg, "updating ORIG_HEAD");
+                               reflog_orig_head = msg.buf;
+                       }
+                       update_ref(reflog_orig_head, "ORIG_HEAD", orig,
+                                  old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
+               } else if (old_orig)
+                       delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
+       }
+
        if (!reflog_head) {
                strbuf_setlen(&msg, prefix_len);
                strbuf_addstr(&msg, "updating HEAD");
@@ -476,7 +459,7 @@ reset_head_refs:
                                 detach_head ? REF_NO_DEREF : 0,
                                 UPDATE_REFS_MSG_ON_ERR);
        else {
-               ret = update_ref(reflog_orig_head, switch_to_branch, oid,
+               ret = update_ref(reflog_head, switch_to_branch, oid,
                                 NULL, 0, UPDATE_REFS_MSG_ON_ERR);
                if (!ret)
                        ret = create_symref("HEAD", switch_to_branch,
@@ -869,6 +852,11 @@ static int rebase_config(const char *var, const char *value, void *data)
                return 0;
        }
 
+       if (!strcmp(var, "rebase.usebuiltin")) {
+               opts->use_legacy_rebase = !git_config_bool(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, data);
 }
 
@@ -1027,6 +1015,14 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                ACTION_EDIT_TODO,
                ACTION_SHOW_CURRENT_PATCH,
        } action = NO_ACTION;
+       static const char *action_names[] = { N_("undefined"),
+                                             N_("continue"),
+                                             N_("skip"),
+                                             N_("abort"),
+                                             N_("quit"),
+                                             N_("edit_todo"),
+                                             N_("show_current_patch"),
+                                             NULL };
        const char *gpg_sign = NULL;
        struct string_list exec = STRING_LIST_INIT_NODUP;
        const char *rebase_merges = NULL;
@@ -1092,8 +1088,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        PARSE_OPT_NOARG | PARSE_OPT_NONEG,
                        parse_opt_interactive },
                OPT_SET_INT('p', "preserve-merges", &options.type,
-                           N_("try to recreate merges instead of ignoring "
-                              "them"), REBASE_PRESERVE_MERGES),
+                           N_("(DEPRECATED) try to recreate merges instead of "
+                              "ignoring them"), REBASE_PRESERVE_MERGES),
                OPT_BOOL(0, "rerere-autoupdate",
                         &options.allow_rerere_autoupdate,
                         N_("allow rerere to update index with resolved "
@@ -1135,22 +1131,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        };
        int i;
 
-       /*
-        * NEEDSWORK: Once the builtin rebase has been tested enough
-        * and git-legacy-rebase.sh is retired to contrib/, this preamble
-        * can be removed.
-        */
-
-       if (!use_builtin_rebase()) {
-               const char *path = mkpath("%s/git-legacy-rebase",
-                                         git_exec_path());
-
-               if (sane_execvp(path, (char **)argv) < 0)
-                       die_errno(_("could not exec %s"), path);
-               else
-                       BUG("sane_execvp() returned???");
-       }
-
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
@@ -1161,6 +1141,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
        git_config(rebase_config, &options);
 
+       if (options.use_legacy_rebase ||
+           !git_env_bool("GIT_TEST_REBASE_USE_BUILTIN", -1))
+               warning(_("the rebase.useBuiltin support has been removed!\n"
+                         "See its entry in 'git help config' for details."));
+
        strbuf_reset(&buf);
        strbuf_addf(&buf, "%s/applying", apply_dir());
        if(file_exists(buf.buf))
@@ -1204,6 +1189,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
 
+       if (options.type == REBASE_PRESERVE_MERGES)
+               warning(_("git rebase --preserve-merges is deprecated. "
+                         "Use --rebase-merges instead."));
+
        if (action != NO_ACTION && !in_progress)
                die(_("No rebase in progress?"));
        setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
@@ -1212,6 +1201,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                die(_("The --edit-todo action can only be used during "
                      "interactive rebase."));
 
+       if (trace2_is_enabled()) {
+               if (is_interactive(&options))
+                       trace2_cmd_mode("interactive");
+               else if (exec.nr)
+                       trace2_cmd_mode("interactive-exec");
+               else
+                       trace2_cmd_mode(action_names[action]);
+       }
+
        switch (action) {
        case ACTION_CONTINUE: {
                struct object_id head;
@@ -1760,7 +1758,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        strbuf_addf(&msg, "%s: checkout %s",
                    getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
        if (reset_head(&options.onto->object.oid, "checkout", NULL,
-                      RESET_HEAD_DETACH | RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
+                      RESET_HEAD_DETACH | RESET_ORIG_HEAD | 
+                      RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
                       NULL, msg.buf))
                die(_("Could not detach HEAD"));
        strbuf_release(&msg);
@@ -1776,8 +1775,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                strbuf_addf(&msg, "rebase finished: %s onto %s",
                        options.head_name ? options.head_name : "detached HEAD",
                        oid_to_hex(&options.onto->object.oid));
-               reset_head(NULL, "Fast-forwarded", options.head_name, 0,
-                          "HEAD", msg.buf);
+               reset_head(NULL, "Fast-forwarded", options.head_name,
+                          RESET_HEAD_REFS_ONLY, "HEAD", msg.buf);
                strbuf_release(&msg);
                ret = !!finish_rebase(&options);
                goto cleanup;
index d58b775..29f165d 100644 (file)
@@ -694,6 +694,8 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,
        proc.argv = argv;
        proc.in = -1;
        proc.stdout_to_stderr = 1;
+       proc.trace2_hook_name = hook_name;
+
        if (feed_state->push_options) {
                int i;
                for (i = 0; i < feed_state->push_options->nr; i++)
@@ -807,6 +809,7 @@ static int run_update_hook(struct command *cmd)
        proc.stdout_to_stderr = 1;
        proc.err = use_sideband ? -1 : 0;
        proc.argv = argv;
+       proc.trace2_hook_name = "update";
 
        code = start_command(&proc);
        if (code)
@@ -1190,6 +1193,7 @@ static void run_update_post_hook(struct command *commands)
        proc.no_stdin = 1;
        proc.stdout_to_stderr = 1;
        proc.err = use_sideband ? -1 : 0;
+       proc.trace2_hook_name = "post-update";
 
        if (!start_command(&proc)) {
                if (use_sideband)
@@ -1198,17 +1202,12 @@ static void run_update_post_hook(struct command *commands)
        }
 }
 
-static void check_aliased_update(struct command *cmd, struct string_list *list)
+static void check_aliased_update_internal(struct command *cmd,
+                                         struct string_list *list,
+                                         const char *dst_name, int flag)
 {
-       struct strbuf buf = STRBUF_INIT;
-       const char *dst_name;
        struct string_list_item *item;
        struct command *dst_cmd;
-       int flag;
-
-       strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
-       dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
-       strbuf_release(&buf);
 
        if (!(flag & REF_ISSYMREF))
                return;
@@ -1247,6 +1246,18 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
                "inconsistent aliased update";
 }
 
+static void check_aliased_update(struct command *cmd, struct string_list *list)
+{
+       struct strbuf buf = STRBUF_INIT;
+       const char *dst_name;
+       int flag;
+
+       strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
+       dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
+       check_aliased_update_internal(cmd, list, dst_name, flag);
+       strbuf_release(&buf);
+}
+
 static void check_aliased_updates(struct command *commands)
 {
        struct command *cmd;
index 5b80b7f..f570162 100644 (file)
@@ -82,6 +82,10 @@ static int list_replace_refs(const char *pattern, const char *format)
                data.format = REPLACE_FORMAT_MEDIUM;
        else if (!strcmp(format, "long"))
                data.format = REPLACE_FORMAT_LONG;
+       /*
+        * Please update _git_replace() in git-completion.bash when
+        * you add new format
+        */
        else
                return error(_("invalid replace format '%s'\n"
                               "valid formats are 'short', 'medium' and 'long'"),
index 4d18a46..7882829 100644 (file)
@@ -341,6 +341,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        if (patch_mode) {
                if (reset_type != NONE)
                        die(_("--patch is incompatible with --{hard,mixed,soft}"));
+               trace2_cmd_mode("patch-interactive");
                return run_add_interactive(rev, "--patch=reset", &pathspec);
        }
 
@@ -357,6 +358,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        if (reset_type == NONE)
                reset_type = MIXED; /* by default */
 
+       if (pathspec.nr)
+               trace2_cmd_mode("path");
+       else
+               trace2_cmd_mode(reset_type_names[reset_type]);
+
        if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))
                setup_work_tree();
 
index 5b5b6db..425a577 100644 (file)
@@ -238,7 +238,7 @@ static inline void finish_object__ma(struct object *obj)
 static int finish_object(struct object *obj, const char *name, void *cb_data)
 {
        struct rev_list_info *info = cb_data;
-       if (!has_object_file(&obj->oid)) {
+       if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
                finish_object__ma(obj);
                return 1;
        }
index b80fc4b..6bcc4f1 100644 (file)
@@ -1816,11 +1816,10 @@ static int update_submodules(struct submodule_update_clone *suc)
 {
        int i;
 
-       run_processes_parallel(suc->max_jobs,
-                              update_clone_get_next_task,
-                              update_clone_start_failure,
-                              update_clone_task_finished,
-                              suc);
+       run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task,
+                                  update_clone_start_failure,
+                                  update_clone_task_finished, suc, "submodule",
+                                  "parallel/update");
 
        /*
         * We saved the output and put it out all at once now.
index 02ace60..1b6c42f 100644 (file)
@@ -848,14 +848,16 @@ static int parse_new_style_cacheinfo(const char *arg,
        return 0;
 }
 
-static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result cacheinfo_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        struct object_id oid;
        unsigned int mode;
        const char *path;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) {
                if (add_cacheinfo(mode, &oid, path, 0))
@@ -874,12 +876,14 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
        return 0;
 }
 
-static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx,
-                             const struct option *opt, int unset)
+static enum parse_opt_result stdin_cacheinfo_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *nul_term_line = opt->value;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
@@ -888,12 +892,14 @@ static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx,
        return 0;
 }
 
-static int stdin_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result stdin_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *read_from_stdin = opt->value;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
@@ -901,13 +907,15 @@ static int stdin_callback(struct parse_opt_ctx_t *ctx,
        return 0;
 }
 
-static int unresolve_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result unresolve_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *has_errors = opt->value;
        const char *prefix = startup_info->prefix;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        /* consume remaining arguments. */
        *has_errors = do_unresolve(ctx->argc, ctx->argv,
@@ -920,13 +928,15 @@ static int unresolve_callback(struct parse_opt_ctx_t *ctx,
        return 0;
 }
 
-static int reupdate_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result reupdate_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *has_errors = opt->value;
        const char *prefix = startup_info->prefix;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        /* consume remaining arguments. */
        setup_work_tree();
@@ -986,7 +996,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                        N_("add the specified entry to the index"),
                        PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
                        PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
-                       (parse_opt_cb *) cacheinfo_callback},
+                       NULL, 0,
+                       cacheinfo_callback},
                {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, "(+|-)x",
                        N_("override the executable bit of the listed files"),
                        PARSE_OPT_NONEG,
@@ -1012,19 +1023,19 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
                        N_("read list of paths to be updated from standard input"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) stdin_callback},
+                       NULL, 0, stdin_callback},
                {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL,
                        N_("add entries from standard input to the index"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) stdin_cacheinfo_callback},
+                       NULL, 0, stdin_cacheinfo_callback},
                {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
                        N_("repopulate stages #2 and #3 for the listed paths"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) unresolve_callback},
+                       NULL, 0, unresolve_callback},
                {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
                        N_("only update entries that differ from HEAD"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) reupdate_callback},
+                       NULL, 0, reupdate_callback},
                OPT_BIT(0, "ignore-missing", &refresh_args.flags,
                        N_("ignore files missing from worktree"),
                        REFRESH_IGNORE_MISSING),
index 3f9907f..d2a7e2f 100644 (file)
@@ -268,10 +268,10 @@ static int add_worktree(const char *path, const char *refname,
        struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
        struct strbuf sb = STRBUF_INIT;
        const char *name;
-       struct stat st;
        struct child_process cp = CHILD_PROCESS_INIT;
        struct argv_array child_env = ARGV_ARRAY_INIT;
-       int counter = 0, len, ret;
+       unsigned int counter = 0;
+       int len, ret;
        struct strbuf symref = STRBUF_INIT;
        struct commit *commit = NULL;
        int is_branch = 0;
@@ -295,8 +295,12 @@ static int add_worktree(const char *path, const char *refname,
        if (safe_create_leading_directories_const(sb_repo.buf))
                die_errno(_("could not create leading directories of '%s'"),
                          sb_repo.buf);
-       while (!stat(sb_repo.buf, &st)) {
+
+       while (mkdir(sb_repo.buf, 0777)) {
                counter++;
+               if ((errno != EEXIST) || !counter /* overflow */)
+                       die_errno(_("could not create directory of '%s'"),
+                                 sb_repo.buf);
                strbuf_setlen(&sb_repo, len);
                strbuf_addf(&sb_repo, "%d", counter);
        }
@@ -306,8 +310,6 @@ static int add_worktree(const char *path, const char *refname,
        atexit(remove_junk);
        sigchain_push_common(remove_junk_on_signal);
 
-       if (mkdir(sb_repo.buf, 0777))
-               die_errno(_("could not create directory of '%s'"), sb_repo.buf);
        junk_git_dir = xstrdup(sb_repo.buf);
        is_junk = 1;
 
@@ -402,6 +404,7 @@ done:
                        cp.dir = path;
                        cp.env = env;
                        cp.argv = NULL;
+                       cp.trace2_hook_name = "post-checkout";
                        argv_array_pushl(&cp.args, absolute_path(hook),
                                         oid_to_hex(&null_oid),
                                         oid_to_hex(&commit->object.oid),
diff --git a/cache.h b/cache.h
index 27fe635..ac92421 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -9,6 +9,7 @@
 #include "gettext.h"
 #include "convert.h"
 #include "trace.h"
+#include "trace2.h"
 #include "string-list.h"
 #include "pack-revindex.h"
 #include "hash.h"
@@ -758,7 +759,7 @@ extern void rename_index_entry_at(struct index_state *, int pos, const char *new
 /* Remove entry, return true if there are more entries to go. */
 extern int remove_index_entry_at(struct index_state *, int pos);
 
-extern void remove_marked_cache_entries(struct index_state *istate);
+extern void remove_marked_cache_entries(struct index_state *istate, int invalidate);
 extern int remove_file_from_index(struct index_state *, const char *path);
 #define ADD_CACHE_VERBOSE 1
 #define ADD_CACHE_PRETEND 2
@@ -961,6 +962,10 @@ extern char *repository_format_partial_clone;
 extern const char *core_partial_clone_filter_default;
 extern int repository_format_worktree_config;
 
+/*
+ * You _have_ to initialize a `struct repository_format` using
+ * `= REPOSITORY_FORMAT_INIT` before calling `read_repository_format()`.
+ */
 struct repository_format {
        int version;
        int precious_objects;
@@ -972,14 +977,35 @@ struct repository_format {
        struct string_list unknown_extensions;
 };
 
+/*
+ * Always use this to initialize a `struct repository_format`
+ * to a well-defined, default state before calling
+ * `read_repository()`.
+ */
+#define REPOSITORY_FORMAT_INIT \
+{ \
+       .version = -1, \
+       .is_bare = -1, \
+       .hash_algo = GIT_HASH_SHA1, \
+       .unknown_extensions = STRING_LIST_INIT_DUP, \
+}
+
 /*
  * Read the repository format characteristics from the config file "path" into
- * "format" struct. Returns the numeric version. On error, -1 is returned,
- * format->version is set to -1, and all other fields in the struct are
- * undefined.
+ * "format" struct. Returns the numeric version. On error, or if no version is
+ * found in the configuration, -1 is returned, format->version is set to -1,
+ * and all other fields in the struct are set to the default configuration
+ * (REPOSITORY_FORMAT_INIT). Always initialize the struct using
+ * REPOSITORY_FORMAT_INIT before calling this function.
  */
 int read_repository_format(struct repository_format *format, const char *path);
 
+/*
+ * Free the memory held onto by `format`, but not the struct itself.
+ * (No need to use this after `read_repository_format()` fails.)
+ */
+void clear_repository_format(struct repository_format *format);
+
 /*
  * Verify that the repository described by repository_format is something we
  * can read. If it is, return 0. Otherwise, return -1, and "err" will describe
@@ -1506,10 +1532,19 @@ int date_overflows(timestamp_t date);
 #define IDENT_STRICT          1
 #define IDENT_NO_DATE         2
 #define IDENT_NO_NAME         4
+
+enum want_ident {
+       WANT_BLANK_IDENT,
+       WANT_AUTHOR_IDENT,
+       WANT_COMMITTER_IDENT
+};
+
 extern const char *git_author_info(int);
 extern const char *git_committer_info(int);
-extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
-extern const char *fmt_name(const char *name, const char *email);
+extern const char *fmt_ident(const char *name, const char *email,
+               enum want_ident whose_ident,
+               const char *date_str, int);
+extern const char *fmt_name(enum want_ident);
 extern const char *ident_default_name(void);
 extern const char *ident_default_email(void);
 extern const char *git_editor(void);
@@ -1569,6 +1604,11 @@ struct checkout {
 extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
 extern void enable_delayed_checkout(struct checkout *state);
 extern int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
+/*
+ * Unlink the last component and schedule the leading directories for
+ * removal, such that empty directories get removed.
+ */
+extern void unlink_entry(const struct cache_entry *ce);
 
 struct cache_def {
        struct strbuf path;
diff --git a/check-racy.c b/check-racy.c
deleted file mode 100644 (file)
index 24b6542..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "cache.h"
-
-int main(int ac, char **av)
-{
-       int i;
-       int dirty, clean, racy;
-
-       dirty = clean = racy = 0;
-       read_cache();
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
-               struct stat st;
-
-               if (lstat(ce->name, &st)) {
-                       error_errno("lstat(%s)", ce->name);
-                       continue;
-               }
-
-               if (ce_match_stat(ce, &st, 0))
-                       dirty++;
-               else if (ce_match_stat(ce, &st, CE_MATCH_RACY_IS_DIRTY))
-                       racy++;
-               else
-                       clean++;
-       }
-       printf("dirty %d, clean %d, racy %d\n", dirty, clean, racy);
-       return 0;
-}
diff --git a/ci/run-windows-build.sh b/ci/run-windows-build.sh
deleted file mode 100755 (executable)
index a73a4ec..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env bash
-#
-# Script to trigger the Git for Windows build and test run.
-# Set the $GFW_CI_TOKEN as environment variable.
-# Pass the branch (only branches on https://github.com/git/git are
-# supported) and a commit hash.
-#
-
-. ${0%/*}/lib.sh
-
-test $# -ne 2 && echo "Unexpected number of parameters" && exit 1
-test -z "$GFW_CI_TOKEN" && echo "GFW_CI_TOKEN not defined" && exit
-
-BRANCH=$1
-COMMIT=$2
-
-gfwci () {
-       local CURL_ERROR_CODE HTTP_CODE
-       CONTENT_FILE=$(mktemp -t "git-windows-ci-XXXXXX")
-       while test -z $HTTP_CODE
-       do
-       HTTP_CODE=$(curl \
-               -H "Authentication: Bearer $GFW_CI_TOKEN" \
-               --silent --retry 5 --write-out '%{HTTP_CODE}' \
-               --output >(sed "$(printf '1s/^\xef\xbb\xbf//')" >$CONTENT_FILE) \
-               "https://git-for-windows-ci.azurewebsites.net/api/TestNow?$1" \
-       )
-       CURL_ERROR_CODE=$?
-               # The GfW CI web app sometimes returns HTTP errors of
-               # "502 bad gateway" or "503 service unavailable".
-               # We also need to check the HTTP content because the GfW web
-               # app seems to pass through (error) results from other Azure
-               # calls with HTTP code 200.
-               # Wait a little and retry if we detect this error. More info:
-               # https://docs.microsoft.com/en-in/azure/app-service-web/app-service-web-troubleshoot-http-502-http-503
-               if test $HTTP_CODE -eq 502 ||
-                  test $HTTP_CODE -eq 503 ||
-                  grep "502 - Web server received an invalid response" $CONTENT_FILE >/dev/null
-               then
-                       sleep 10
-                       HTTP_CODE=
-               fi
-       done
-       cat $CONTENT_FILE
-       rm $CONTENT_FILE
-       if test $CURL_ERROR_CODE -ne 0
-       then
-               return $CURL_ERROR_CODE
-       fi
-       if test "$HTTP_CODE" -ge 400 && test "$HTTP_CODE" -lt 600
-       then
-               return 127
-       fi
-}
-
-# Trigger build job
-BUILD_ID=$(gfwci "action=trigger&branch=$BRANCH&commit=$COMMIT&skipTests=false")
-if test $? -ne 0
-then
-       echo "Unable to trigger Visual Studio Team Services Build"
-       echo "$BUILD_ID"
-       exit 1
-fi
-
-# Check if the $BUILD_ID contains a number
-case $BUILD_ID in
-''|*[!0-9]*) echo "Unexpected build number: $BUILD_ID" && exit 1
-esac
-
-echo "Visual Studio Team Services Build #${BUILD_ID}"
-
-# Tracing execued commands would produce too much noise in the waiting
-# loop below.
-set +x
-
-# Wait until build job finished
-STATUS=
-RESULT=
-while true
-do
-       LAST_STATUS=$STATUS
-       STATUS=$(gfwci "action=status&buildId=$BUILD_ID")
-       test "$STATUS" = "$LAST_STATUS" || printf "\nStatus: %s " "$STATUS"
-       printf "."
-
-       case "$STATUS" in
-       inProgress|postponed|notStarted) sleep 10               ;; # continue
-                "completed: succeeded") RESULT="success"; break;; # success
-                   "completed: failed")                   break;; # failure
-       *) echo "Unhandled status: $STATUS";               break;; # unknown
-       esac
-done
-
-# Print log
-echo ""
-echo ""
-set -x
-gfwci "action=log&buildId=$BUILD_ID" | cut -c 30-
-
-# Set exit code for TravisCI
-test "$RESULT" = "success"
-
-save_good_tree
index 23d8fab..3e49f3b 100644 (file)
@@ -23,11 +23,20 @@ static int compare_paths(const struct combine_diff_path *one,
                                 two->path, strlen(two->path), two->mode);
 }
 
-static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
+static int filename_changed(char status)
+{
+       return status == 'R' || status == 'C';
+}
+
+static struct combine_diff_path *intersect_paths(
+       struct combine_diff_path *curr,
+       int n,
+       int num_parent,
+       int combined_all_paths)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        struct combine_diff_path *p, **tail = &curr;
-       int i, cmp;
+       int i, j, cmp;
 
        if (!n) {
                for (i = 0; i < q->nr; i++) {
@@ -50,6 +59,13 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
                        oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);
                        p->parent[n].mode = q->queue[i]->one->mode;
                        p->parent[n].status = q->queue[i]->status;
+
+                       if (combined_all_paths &&
+                           filename_changed(p->parent[n].status)) {
+                               strbuf_init(&p->parent[n].path, 0);
+                               strbuf_addstr(&p->parent[n].path,
+                                             q->queue[i]->one->path);
+                       }
                        *tail = p;
                        tail = &p->next;
                }
@@ -68,6 +84,10 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
                if (cmp < 0) {
                        /* p->path not in q->queue[]; drop it */
                        *tail = p->next;
+                       for (j = 0; j < num_parent; j++)
+                               if (combined_all_paths &&
+                                   filename_changed(p->parent[j].status))
+                                       strbuf_release(&p->parent[j].path);
                        free(p);
                        continue;
                }
@@ -81,6 +101,10 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
                oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);
                p->parent[n].mode = q->queue[i]->one->mode;
                p->parent[n].status = q->queue[i]->status;
+               if (combined_all_paths &&
+                   filename_changed(p->parent[n].status))
+                       strbuf_addstr(&p->parent[n].path,
+                                     q->queue[i]->one->path);
 
                tail = &p->next;
                i++;
@@ -960,12 +984,25 @@ static void show_combined_header(struct combine_diff_path *elem,
        if (!show_file_header)
                return;
 
-       if (added)
-               dump_quoted_path("--- ", "", "/dev/null",
-                                line_prefix, c_meta, c_reset);
-       else
-               dump_quoted_path("--- ", a_prefix, elem->path,
-                                line_prefix, c_meta, c_reset);
+       if (rev->combined_all_paths) {
+               for (i = 0; i < num_parent; i++) {
+                       char *path = filename_changed(elem->parent[i].status)
+                               ? elem->parent[i].path.buf : elem->path;
+                       if (elem->parent[i].status == DIFF_STATUS_ADDED)
+                               dump_quoted_path("--- ", "", "/dev/null",
+                                                line_prefix, c_meta, c_reset);
+                       else
+                               dump_quoted_path("--- ", a_prefix, path,
+                                                line_prefix, c_meta, c_reset);
+               }
+       } else {
+               if (added)
+                       dump_quoted_path("--- ", "", "/dev/null",
+                                        line_prefix, c_meta, c_reset);
+               else
+                       dump_quoted_path("--- ", a_prefix, elem->path,
+                                        line_prefix, c_meta, c_reset);
+       }
        if (deleted)
                dump_quoted_path("+++ ", "", "/dev/null",
                                 line_prefix, c_meta, c_reset);
@@ -1227,6 +1264,15 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
                putchar(inter_name_termination);
        }
 
+       for (i = 0; i < num_parent; i++)
+               if (rev->combined_all_paths) {
+                       if (filename_changed(p->parent[i].status))
+                               write_name_quoted(p->parent[i].path.buf, stdout,
+                                                 inter_name_termination);
+                       else
+                               write_name_quoted(p->path, stdout,
+                                                 inter_name_termination);
+               }
        write_name_quoted(p->path, stdout, line_termination);
 }
 
@@ -1332,7 +1378,9 @@ static const char *path_path(void *obj)
 
 /* find set of paths that every parent touches */
 static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
-       const struct oid_array *parents, struct diff_options *opt)
+       const struct oid_array *parents,
+       struct diff_options *opt,
+       int combined_all_paths)
 {
        struct combine_diff_path *paths = NULL;
        int i, num_parent = parents->nr;
@@ -1357,7 +1405,8 @@ static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
                        opt->output_format = DIFF_FORMAT_NO_OUTPUT;
                diff_tree_oid(&parents->oid[i], oid, "", opt);
                diffcore_std(opt);
-               paths = intersect_paths(paths, i, num_parent);
+               paths = intersect_paths(paths, i, num_parent,
+                                       combined_all_paths);
 
                /* if showing diff, show it in requested order */
                if (opt->output_format != DIFF_FORMAT_NO_OUTPUT &&
@@ -1467,7 +1516,8 @@ void diff_tree_combined(const struct object_id *oid,
                 * diff(sha1,parent_i) for all i to do the job, specifically
                 * for parent0.
                 */
-               paths = find_paths_generic(oid, parents, &diffopts);
+               paths = find_paths_generic(oid, parents, &diffopts,
+                                          rev->combined_all_paths);
        }
        else {
                int stat_opt;
@@ -1540,6 +1590,10 @@ void diff_tree_combined(const struct object_id *oid,
        while (paths) {
                struct combine_diff_path *tmp = paths;
                paths = paths->next;
+               for (i = 0; i < num_parent; i++)
+                       if (rev->combined_all_paths &&
+                           filename_changed(tmp->parent[i].status))
+                               strbuf_release(&tmp->parent[i].path);
                free(tmp);
        }
 
index 3728f66..d484aec 100644 (file)
@@ -25,12 +25,19 @@ static void restore_sigpipe_to_default(void)
 
 int main(int argc, const char **argv)
 {
+       int result;
+
        /*
         * Always open file descriptors 0/1/2 to avoid clobbering files
         * in die().  It also avoids messing up when the pipes are dup'ed
         * onto stdin/stdout/stderr in the child processes we spawn.
         */
        sanitize_stdfds();
+       restore_sigpipe_to_default();
+
+       trace2_initialize();
+       trace2_cmd_start(argv);
+       trace2_collect_process_info();
 
        git_resolve_executable_dir(argv[0]);
 
@@ -40,7 +47,9 @@ int main(int argc, const char **argv)
 
        attr_start();
 
-       restore_sigpipe_to_default();
+       result = cmd_main(argc, argv);
+
+       trace2_cmd_exit(result);
 
-       return cmd_main(argc, argv);
+       return result;
 }
index 5078ce5..e4e2573 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef COMPAT_BSWAP_H
+#define COMPAT_BSWAP_H
+
 /*
  * Let's make sure we always have a sane definition for ntohl()/htonl().
  * Some libraries define those as a function call, just to perform byte
@@ -210,3 +213,5 @@ static inline void put_be64(void *ptr, uint64_t value)
 }
 
 #endif
+
+#endif /* COMPAT_BSWAP_H */
index 8141f77..6b04514 100644 (file)
@@ -1551,19 +1551,23 @@ static int try_shell_exec(const char *cmd, char *const *argv)
                return 0;
        prog = path_lookup(interpr, 1);
        if (prog) {
+               int exec_id;
                int argc = 0;
                const char **argv2;
                while (argv[argc]) argc++;
                ALLOC_ARRAY(argv2, argc + 1);
                argv2[0] = (char *)cmd; /* full path to the script file */
                memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
+               exec_id = trace2_exec(prog, argv2);
                pid = mingw_spawnv(prog, argv2, 1);
                if (pid >= 0) {
                        int status;
                        if (waitpid(pid, &status, 0) < 0)
                                status = 255;
+                       trace2_exec_result(exec_id, status);
                        exit(status);
                }
+               trace2_exec_result(exec_id, -1);
                pid = 1;        /* indicate that we tried but failed */
                free(prog);
                free(argv2);
@@ -1576,12 +1580,17 @@ int mingw_execv(const char *cmd, char *const *argv)
        /* check if git_command is a shell script */
        if (!try_shell_exec(cmd, argv)) {
                int pid, status;
+               int exec_id;
 
+               exec_id = trace2_exec(cmd, (const char **)argv);
                pid = mingw_spawnv(cmd, (const char **)argv, 0);
-               if (pid < 0)
+               if (pid < 0) {
+                       trace2_exec_result(exec_id, -1);
                        return -1;
+               }
                if (waitpid(pid, &status, 0) < 0)
                        status = 255;
+               trace2_exec_result(exec_id, status);
                exit(status);
        }
        return -1;
index 30d9fb3..4d73f8a 100644 (file)
+++ b/