Merge branch 'mh/ref-locking-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 26 Oct 2017 03:29:23 +0000 (12:29 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 26 Oct 2017 03:29:23 +0000 (12:29 +0900)
Transactions to update multiple references that involves a deletion
was quite broken in an error codepath and did not abort everything
correctly.

* mh/ref-locking-fix:
  files_transaction_prepare(): fix handling of ref lock failure
  t1404: add a bunch of tests of D/F conflicts

348 files changed:
.clang-format [new file with mode: 0644]
.mailmap
.travis.yml
.tsan-suppressions [new file with mode: 0644]
Documentation/Makefile
Documentation/RelNotes/2.10.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.11.4.txt [new file with mode: 0644]
Documentation/RelNotes/2.12.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.13.6.txt [new file with mode: 0644]
Documentation/RelNotes/2.14.2.txt
Documentation/RelNotes/2.14.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.15.0.txt
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-apply.txt
Documentation/git-branch.txt
Documentation/git-cat-file.txt
Documentation/git-checkout.txt
Documentation/git-cvsserver.txt
Documentation/git-describe.txt
Documentation/git-diff-index.txt
Documentation/git-filter-branch.txt
Documentation/git-for-each-ref.txt
Documentation/git-grep.txt
Documentation/git-merge.txt
Documentation/git-notes.txt
Documentation/git-read-tree.txt
Documentation/git-rebase.txt
Documentation/git-rerere.txt
Documentation/git-rev-parse.txt
Documentation/git-rm.txt
Documentation/git-shell.txt
Documentation/git-status.txt
Documentation/git-svn.txt
Documentation/git-tag.txt
Documentation/git-update-index.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitcore-tutorial.txt
Documentation/githooks.txt
Documentation/gitrepository-layout.txt
Documentation/gittutorial.txt
Documentation/glossary-content.txt
Documentation/merge-options.txt
Documentation/merge-strategies.txt
Documentation/pull-fetch-param.txt
Documentation/rev-list-options.txt
Documentation/technical/api-argv-array.txt
Documentation/technical/api-config.txt
Documentation/technical/api-ref-iteration.txt
Documentation/technical/api-string-list.txt [deleted file]
Documentation/technical/hash-function-transition.txt [new file with mode: 0644]
Documentation/technical/pack-protocol.txt
Documentation/technical/trivial-merge.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
abspath.c
apply.c
archive.c
attr.c
bisect.c
branch.c
builtin/add.c
builtin/am.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/check-ref-format.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit-tree.c
builtin/commit.c
builtin/config.c
builtin/describe.c
builtin/diff-index.c
builtin/diff.c
builtin/fast-export.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/gc.c
builtin/get-tar-commit-id.c
builtin/grep.c
builtin/help.c
builtin/index-pack.c
builtin/init-db.c
builtin/log.c
builtin/ls-files.c
builtin/merge.c
builtin/name-rev.c
builtin/notes.c
builtin/pack-objects.c
builtin/pull.c
builtin/rebase--helper.c
builtin/receive-pack.c
builtin/reflog.c
builtin/remote-ext.c
builtin/remote.c
builtin/rerere.c
builtin/reset.c
builtin/rev-parse.c
builtin/shortlog.c
builtin/show-branch.c
builtin/submodule--helper.c
builtin/symbolic-ref.c
builtin/tag.c
builtin/unpack-file.c
builtin/unpack-objects.c
builtin/update-index.c
builtin/worktree.c
bulk-checkin.c
bundle.c
cache-tree.c
cache.h
ci/install-dependencies.sh [new file with mode: 0755]
ci/lib-travisci.sh [new file with mode: 0755]
ci/print-test-failures.sh [new file with mode: 0755]
ci/run-build.sh [new file with mode: 0755]
ci/run-linux32-docker.sh [new file with mode: 0755]
ci/run-static-analysis.sh [new file with mode: 0755]
ci/run-tests.sh [new file with mode: 0755]
ci/run-windows-build.sh
ci/test-documentation.sh
color.c
commit-slab.h
commit.c
commit.h
compat/poll/poll.c
compat/regex/regex_internal.c
compat/regex/regexec.c
compat/win32/lazyload.h [new file with mode: 0644]
config.c
config.h
config.mak.uname
connect.c
contrib/coccinelle/array.cocci
contrib/completion/git-completion.bash
contrib/diff-highlight/Makefile
contrib/examples/git-merge.sh
contrib/examples/git-resolve.sh
contrib/subtree/t/t7900-subtree.sh
convert.c
credential-cache--daemon.c
csum-file.c
diff-delta.c
diff-lib.c
diff.c
dir.c
entry.c
environment.c
exec_cmd.c
fast-import.c
fetch-pack.c
fsck.c
git-archimport.perl
git-compat-util.h
git-cvsimport.perl
git-cvsserver.perl
git-filter-branch.sh
git-gui/po/README
git-merge-octopus.sh
git-p4.py
git-rebase--interactive.sh
git-rebase.sh
git-request-pull.sh
git-send-email.perl
git.c
gpg-interface.c
graph.c
hash.h
hashmap.c
hashmap.h
http-backend.c
http-push.c
http.c
imap-send.c
line-log.c
line-log.h
list.h
ll-merge.c
lockfile.c
lockfile.h
log-tree.c
mailinfo.c
merge-recursive.c
merge-recursive.h
name-hash.c
notes-merge.c
notes.c
object.c
object.h
oidmap.c [new file with mode: 0644]
oidmap.h [new file with mode: 0644]
oidset.c
oidset.h
outgoing/packfile.h [deleted file]
pack-bitmap-write.c
pack-bitmap.c
pack-write.c
packfile.c
parse-options.c
path.c
pathspec.c
pathspec.h
pkt-line.c
po/TEAMS
po/bg.po
po/ca.po
po/de.po
po/es.po [new file with mode: 0644]
po/fr.po
po/git.pot
po/ko.po
po/ru.po
po/sv.po
po/vi.po
po/zh_CN.po
pretty.c
quote.c
reachable.c
read-cache.c
ref-filter.c
reflog-walk.c
refs.c
refs.h
refs/files-backend.c
refs/iterator.c
refs/packed-backend.c
refs/ref-cache.c
refs/ref-cache.h
refs/refs-internal.h
remote.c
repository.c
rerere.c
revision.c
revision.h
run-command.c
send-pack.c
sequencer.c
sequencer.h
setup.c
sha1-lookup.c
sha1-lookup.h
sha1_file.c
sha1_name.c
sha1dc_git.c
sha1dc_git.h
shallow.c
shell.c
strbuf.h
streaming.c
string-list.c
string-list.h
sub-process.c
submodule.c
submodule.h
t/README
t/check-non-portable-shell.pl
t/helper/.gitignore
t/helper/test-delta.c
t/helper/test-hashmap.c
t/helper/test-line-buffer.c
t/helper/test-parse-options.c
t/helper/test-string-list.c
t/t0040-parse-options.sh
t/t1004-read-tree-m-u-wf.sh
t/t1400-update-ref.sh
t/t1401-symbolic-ref.sh
t/t1407-worktree-ref-store.sh
t/t1450-fsck.sh
t/t1500-rev-parse.sh
t/t1502-rev-parse-parseopt.sh
t/t3200-branch.sh
t/t3203-branch-output.sh
t/t3205-branch-color.sh
t/t3308-notes-merge.sh
t/t3404-rebase-interactive.sh
t/t3415-rebase-autosquash.sh
t/t3701-add-interactive.sh
t/t4013-diff-various.sh
t/t4013/diff.diff-tree_--stat_initial_mode [new file with mode: 0644]
t/t4013/diff.diff-tree_--summary_initial_mode [new file with mode: 0644]
t/t4013/diff.diff-tree_initial_mode [new file with mode: 0644]
t/t4013/diff.log_--decorate=full_--all
t/t4013/diff.log_--decorate_--all
t/t4015-diff-whitespace.sh
t/t4059-diff-submodule-not-initialized.sh
t/t4202-log.sh
t/t4205-log-pretty-formats.sh
t/t5001-archive-attr.sh
t/t5002-archive-attr-pattern.sh
t/t5004-archive-corner-cases.sh
t/t5150-request-pull.sh
t/t5304-prune.sh
t/t5531-deep-submodule-push.sh
t/t5572-pull-submodule.sh
t/t6002-rev-list-bisect.sh
t/t6006-rev-list-format.sh
t/t6007-rev-list-cherry-pick-file.sh
t/t6013-rev-list-reverse-parents.sh
t/t6040-tracking-info.sh
t/t6120-describe.sh
t/t6132-pathspec-exclude.sh
t/t6300-for-each-ref.sh
t/t7001-mv.sh
t/t7004-tag.sh
t/t7005-editor.sh
t/t7006-pager.sh
t/t7102-reset.sh
t/t7201-co.sh
t/t7301-clean-interactive.sh
t/t7400-submodule-basic.sh
t/t7405-submodule-merge.sh
t/t7406-submodule-update.sh
t/t7502-commit.sh
t/t7504-commit-msg-hook.sh
t/t7506-status-submodule.sh
t/t7508-status.sh
t/t7600-merge.sh
t/t7610-mergetool.sh
t/t8010-cat-file-filters.sh
t/t9001-send-email.sh
t/t9010-svn-fe.sh
t/t9300-fast-import.sh
t/t9350-fast-export.sh
t/t9400-git-cvsserver-server.sh
t/test-lib.sh
t/test-terminal.perl
tag.c
tempfile.c
tempfile.h
templates/hooks--pre-rebase.sample
trailer.c
transport-helper.c
transport.c
tree-walk.c
unpack-trees.c
upload-pack.c
usage.c
userdiff.c
utf8.c
vcs-svn/svndump.c
worktree.c
worktree.h
wrapper.c
wt-status.c
xdiff/xpatience.c

diff --git a/.clang-format b/.clang-format
new file mode 100644 (file)
index 0000000..611ab47
--- /dev/null
@@ -0,0 +1,169 @@
+# This file is an example configuration for clang-format 5.0.
+#
+# Note that this style definition should only be understood as a hint
+# for writing new code. The rules are still work-in-progress and does
+# not yet exactly match the style we have in the existing code.
+
+# Use tabs whenever we need to fill whitespace that spans at least from one tab
+# stop to the next one.
+UseTab: Always
+TabWidth: 8
+IndentWidth: 8
+ContinuationIndentWidth: 8
+ColumnLimit: 80
+
+# C Language specifics
+Language: Cpp
+
+# Align parameters on the open bracket
+# someLongFunction(argument1,
+#                  argument2);
+AlignAfterOpenBracket: Align
+
+# Don't align consecutive assignments
+# int aaaa = 12;
+# int b = 14;
+AlignConsecutiveAssignments: false
+
+# Don't align consecutive declarations
+# int aaaa = 12;
+# double b = 3.14;
+AlignConsecutiveDeclarations: false
+
+# Align escaped newlines as far left as possible
+# #define A   \
+#   int aaaa; \
+#   int b;    \
+#   int cccccccc;
+AlignEscapedNewlines: Left
+
+# Align operands of binary and ternary expressions
+# int aaa = bbbbbbbbbbb +
+#           cccccc;
+AlignOperands: true
+
+# Don't align trailing comments
+# int a; // Comment a
+# int b = 2; // Comment b
+AlignTrailingComments: false
+
+# By default don't allow putting parameters onto the next line
+# myFunction(foo, bar, baz);
+AllowAllParametersOfDeclarationOnNextLine: false
+
+# Don't allow short braced statements to be on a single line
+# if (a)           not       if (a) return;
+#   return;
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+
+# By default don't add a line break after the return type of top-level functions
+# int foo();
+AlwaysBreakAfterReturnType: None
+
+# Pack as many parameters or arguments onto the same line as possible
+# int myFunction(int aaaaaaaaaaaa, int bbbbbbbb,
+#                int cccc);
+BinPackArguments: true
+BinPackParameters: true
+
+# Attach braces to surrounding context except break before braces on function
+# definitions.
+# void foo()
+# {
+#    if (true) {
+#    } else {
+#    }
+# };
+BreakBeforeBraces: Linux
+
+# Break after operators
+# int valuve = aaaaaaaaaaaaa +
+#              bbbbbb -
+#              ccccccccccc;
+BreakBeforeBinaryOperators: None
+BreakBeforeTernaryOperators: false
+
+# Don't break string literals
+BreakStringLiterals: false
+
+# Use the same indentation level as for the switch statement.
+# Switch statement body is always indented one level more than case labels.
+IndentCaseLabels: false
+
+# Don't indent a function definition or declaration if it is wrapped after the
+# type
+IndentWrappedFunctionNames: false
+
+# Align pointer to the right
+# int *a;
+PointerAlignment: Right
+
+# Don't insert a space after a cast
+# x = (int32)y;    not    x = (int32) y;
+SpaceAfterCStyleCast: false
+
+# Insert spaces before and after assignment operators
+# int a = 5;    not    int a=5;
+# a += 42;             a+=42;
+SpaceBeforeAssignmentOperators: true
+
+# Put a space before opening parentheses only after control statement keywords.
+# void f() {
+#   if (true) {
+#     f();
+#   }
+# }
+SpaceBeforeParens: ControlStatements
+
+# Don't insert spaces inside empty '()'
+SpaceInEmptyParentheses: false
+
+# The number of spaces before trailing line comments (// - comments).
+# This does not affect trailing block comments (/* - comments).
+SpacesBeforeTrailingComments: 1
+
+# Don't insert spaces in casts
+# x = (int32) y;    not    x = ( int32 ) y;
+SpacesInCStyleCastParentheses: false
+
+# Don't insert spaces inside container literals
+# var arr = [1, 2, 3];    not    var arr = [ 1, 2, 3 ];
+SpacesInContainerLiterals: false
+
+# Don't insert spaces after '(' or before ')'
+# f(arg);    not    f( arg );
+SpacesInParentheses: false
+
+# Don't insert spaces after '[' or before ']'
+# int a[5];    not    int a[ 5 ];
+SpacesInSquareBrackets: false
+
+# Insert a space after '{' and before '}' in struct initializers
+Cpp11BracedListStyle: false
+
+# A list of macros that should be interpreted as foreach loops instead of as
+# function calls.
+ForEachMacros: ['for_each_string_list_item']
+
+# The maximum number of consecutive empty lines to keep.
+MaxEmptyLinesToKeep: 1
+
+# No empty line at the start of a block.
+KeepEmptyLinesAtTheStartOfBlocks: false
+
+# Penalties
+# This decides what order things should be done if a line is too long
+PenaltyBreakAssignment: 10
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 5
+
+# Don't sort #include's
+SortIncludes: false
index ab85e0d..224db83 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -194,6 +194,7 @@ Philippe Bruhat <book@cpan.org>
 Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
 Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk>
 RenĂ© Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx>
+RenĂ© Scharfe <l.s.r@web.de> Rene Scharfe
 Richard Hansen <rhansen@rhansen.org> <hansenr@google.com>
 Richard Hansen <rhansen@rhansen.org> <rhansen@bbn.com>
 Robert Fitzsimons <robfitz@273k.net>
index 278943d..fead995 100644 (file)
@@ -61,23 +61,8 @@ matrix:
       services:
         - docker
       before_install:
-        - docker pull daald/ubuntu32:xenial
       before_script:
-      script:
-        - >
-          docker run
-          --interactive
-          --env DEVELOPER
-          --env DEFAULT_TEST_TARGET
-          --env GIT_PROVE_OPTS
-          --env GIT_TEST_OPTS
-          --env GIT_TEST_CLONE_2GB
-          --volume "${PWD}:/usr/src/git"
-          daald/ubuntu32:xenial
-          /usr/src/git/ci/run-linux32-build.sh $(id -u $USER)
-        # Use the following command to debug the docker build locally:
-        # $ docker run -itv "${PWD}:/usr/src/git" --entrypoint /bin/bash daald/ubuntu32:xenial
-        # root@container:/# /usr/src/git/ci/run-linux32-build.sh
+      script: ci/run-linux32-docker.sh
     - env: Static Analysis
       os: linux
       compiler:
@@ -86,9 +71,8 @@ matrix:
           packages:
           - coccinelle
       before_install:
-      script:
-        # "before_script" that builds Git is inherited from base job
-        - make coccicheck
+      # "before_script" that builds Git is inherited from base job
+      script: ci/run-static-analysis.sh
       after_failure:
     - env: Documentation
       os: linux
@@ -99,70 +83,14 @@ matrix:
           - asciidoc
           - xmlto
       before_install:
-      before_script: gem install asciidoctor
+      before_script:
       script: ci/test-documentation.sh
       after_failure:
 
-before_install:
-  - >
-    case "${TRAVIS_OS_NAME:-linux}" in
-    linux)
-      export GIT_TEST_HTTPD=YesPlease
-
-      mkdir --parents custom/p4
-      pushd custom/p4
-        wget --quiet http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION/bin.linux26x86_64/p4d
-        wget --quiet http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION/bin.linux26x86_64/p4
-        chmod u+x p4d
-        chmod u+x p4
-        export PATH="$(pwd):$PATH"
-      popd
-      mkdir --parents custom/git-lfs
-      pushd custom/git-lfs
-        wget --quiet https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz
-        tar --extract --gunzip --file "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
-        cp git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs .
-        export PATH="$(pwd):$PATH"
-      popd
-      ;;
-    osx)
-      brew update --quiet
-      # Uncomment this if you want to run perf tests:
-      # brew install gnu-time
-      brew install git-lfs gettext
-      brew link --force gettext
-      brew install caskroom/cask/perforce
-      ;;
-    esac;
-    echo "$(tput setaf 6)Perforce Server Version$(tput sgr0)";
-    p4d -V | grep Rev.;
-    echo "$(tput setaf 6)Perforce Client Version$(tput sgr0)";
-    p4 -V | grep Rev.;
-    echo "$(tput setaf 6)Git-LFS Version$(tput sgr0)";
-    git-lfs version;
-
-before_script: make --jobs=2
-
-script:
-  - >
-    mkdir -p $HOME/travis-cache;
-    ln -s $HOME/travis-cache/.prove t/.prove;
-    make --quiet test;
-
-after_failure:
-  - >
-    : '<-- Click here to see detailed test output!                                                        ';
-    for TEST_EXIT in t/test-results/*.exit;
-    do
-      if [ "$(cat "$TEST_EXIT")" != "0" ];
-      then
-        TEST_OUT="${TEST_EXIT%exit}out";
-        echo "------------------------------------------------------------------------";
-        echo "$(tput setaf 1)${TEST_OUT}...$(tput sgr0)";
-        echo "------------------------------------------------------------------------";
-        cat "${TEST_OUT}";
-      fi;
-    done;
+before_install: ci/install-dependencies.sh
+before_script: ci/run-build.sh
+script: ci/run-tests.sh
+after_failure: ci/print-test-failures.sh
 
 notifications:
   email: false
diff --git a/.tsan-suppressions b/.tsan-suppressions
new file mode 100644 (file)
index 0000000..8c85014
--- /dev/null
@@ -0,0 +1,10 @@
+# Suppressions for ThreadSanitizer (tsan).
+#
+# This file is used by setting the environment variable TSAN_OPTIONS to, e.g.,
+# "suppressions=$(pwd)/.tsan-suppressions". Observe that relative paths such as
+# ".tsan-suppressions" might not work.
+
+# A static variable is written to racily, but we always write the same value, so
+# in practice it (hopefully!) doesn't matter.
+race:^want_color$
+race:^transfer_debug$
index 2415e0d..471bb29 100644 (file)
@@ -67,6 +67,7 @@ SP_ARTICLES += howto/maintain-git
 API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
 SP_ARTICLES += $(API_DOCS)
 
+TECH_DOCS += technical/hash-function-transition
 TECH_DOCS += technical/http-protocol
 TECH_DOCS += technical/index-format
 TECH_DOCS += technical/pack-format
diff --git a/Documentation/RelNotes/2.10.5.txt b/Documentation/RelNotes/2.10.5.txt
new file mode 100644 (file)
index 0000000..a498fd6
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.10.5 Release Notes
+=========================
+
+Fixes since v2.10.4
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
diff --git a/Documentation/RelNotes/2.11.4.txt b/Documentation/RelNotes/2.11.4.txt
new file mode 100644 (file)
index 0000000..ad4da8e
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.11.4 Release Notes
+=========================
+
+Fixes since v2.11.3
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
diff --git a/Documentation/RelNotes/2.12.5.txt b/Documentation/RelNotes/2.12.5.txt
new file mode 100644 (file)
index 0000000..8fa73cf
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.12.5 Release Notes
+=========================
+
+Fixes since v2.12.4
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
diff --git a/Documentation/RelNotes/2.13.6.txt b/Documentation/RelNotes/2.13.6.txt
new file mode 100644 (file)
index 0000000..afcae9c
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.13.6 Release Notes
+=========================
+
+Fixes since v2.13.5
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
index 5517afc..bec9186 100644 (file)
@@ -32,4 +32,74 @@ Fixes since v2.14.1
    daemon is torn down were flaky.  This was fixed by reacting to
    ECONNRESET and behaving as if we got an EOF.
 
+ * Some versions of GnuPG fail to kill gpg-agent it auto-spawned
+   and such a left-over agent can interfere with a test.  Work it
+   around by attempting to kill one before starting a new test.
+
+ * "git log --tag=no-such-tag" showed log starting from HEAD, which
+   has been fixed---it now shows nothing.
+
+ * The "tag.pager" configuration variable was useless for those who
+   actually create tag objects, as it interfered with the use of an
+   editor.  A new mechanism has been introduced for commands to enable
+   pager depending on what operation is being carried out to fix this,
+   and then "git tag -l" is made to run pager by default.
+
+ * "git push --recurse-submodules $there HEAD:$target" was not
+   propagated down to the submodules, but now it is.
+
+ * Commands like "git rebase" accepted the --rerere-autoupdate option
+   from the command line, but did not always use it.  This has been
+   fixed.
+
+ * "git clone --recurse-submodules --quiet" did not pass the quiet
+   option down to submodules.
+
+ * "git am -s" has been taught that some input may end with a trailer
+   block that is not Signed-off-by: and it should refrain from adding
+   an extra blank line before adding a new sign-off in such a case.
+
+ * "git svn" used with "--localtime" option did not compute the tz
+   offset for the timestamp in question and instead always used the
+   current time, which has been corrected.
+
+ * Memory leaks in a few error codepaths have been plugged.
+
+ * bash 4.4 or newer gave a warning on NUL byte in command
+   substitution done in "git stash"; this has been squelched.
+
+ * "git grep -L" and "git grep --quiet -L" reported different exit
+   codes; this has been corrected.
+
+ * When handshake with a subprocess filter notices that the process
+   asked for an unknown capability, Git did not report what program
+   the offending subprocess was running.  This has been corrected.
+
+ * "git apply" that is used as a better "patch -p1" failed to apply a
+   taken from a file with CRLF line endings to a file with CRLF line
+   endings.  The root cause was because it misused convert_to_git()
+   that tried to do "safe-crlf" processing by looking at the index
+   entry at the same path, which is a nonsense---in that mode, "apply"
+   is not working on the data in (or derived from) the index at all.
+   This has been fixed.
+
+ * Killing "git merge --edit" before the editor returns control left
+   the repository in a state with MERGE_MSG but without MERGE_HEAD,
+   which incorrectly tells the subsequent "git commit" that there was
+   a squash merge in progress.  This has been fixed.
+
+ * "git archive" did not work well with pathspecs and the
+   export-ignore attribute.
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
 Also contains various documentation updates and code clean-ups.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
diff --git a/Documentation/RelNotes/2.14.3.txt b/Documentation/RelNotes/2.14.3.txt
new file mode 100644 (file)
index 0000000..977c9e8
--- /dev/null
@@ -0,0 +1,99 @@
+Git v2.14.3 Release Notes
+=========================
+
+Fixes since v2.14.2
+-------------------
+
+ * A helper function to read a single whole line into strbuf
+   mistakenly triggered OOM error at EOF under certain conditions,
+   which has been fixed.
+
+ * In addition to "cc: <a@dd.re.ss> # cruft", "cc: a@dd.re.ss # cruft"
+   was taught to "git send-email" as a valid way to tell it that it
+   needs to also send a carbon copy to <a@dd.re.ss> in the trailer
+   section.
+
+ * Fix regression to "gitk --bisect" by a recent update.
+
+ * Unlike "git commit-tree < file", "git commit-tree -F file" did not
+   pass the contents of the file verbatim and instead completed an
+   incomplete line at the end, if exists.  The latter has been updated
+   to match the behaviour of the former.
+
+ * "git archive", especially when used with pathspec, stored an empty
+   directory in its output, even though Git itself never does so.
+   This has been fixed.
+
+ * API error-proofing which happens to also squelch warnings from GCC.
+
+ * "git gc" tries to avoid running two instances at the same time by
+   reading and writing pid/host from and to a lock file; it used to
+   use an incorrect fscanf() format when reading, which has been
+   corrected.
+
+ * The test linter has been taught that we do not like "echo -e".
+
+ * Code cmp.std.c nitpick.
+
+ * "git describe --match" learned to take multiple patterns in v2.13
+   series, but the feature ignored the patterns after the first one
+   and did not work at all.  This has been fixed.
+
+ * "git cat-file --textconv" started segfaulting recently, which
+   has been corrected.
+
+ * The built-in pattern to detect the "function header" for HTML did
+   not match <H1>..<H6> elements without any attributes, which has
+   been fixed.
+
+ * "git mailinfo" was loose in decoding quoted printable and produced
+   garbage when the two letters after the equal sign are not
+   hexadecimal.  This has been fixed.
+
+ * The documentation for '-X<option>' for merges was misleadingly
+   written to suggest that "-s theirs" exists, which is not the case.
+
+ * Spell the name of our system as "Git" in the output from
+   request-pull script.
+
+ * Fixes for a handful memory access issues identified by valgrind.
+
+ * Backports a moral equivalent of 2015 fix to the poll emulation from
+   the upstream gnulib to fix occasional breakages on HPE NonStop.
+
+ * In the "--format=..." option of the "git for-each-ref" command (and
+   its friends, i.e. the listing mode of "git branch/tag"), "%(atom:)"
+   (e.g. "%(refname:)", "%(body:)" used to error out.  Instead, treat
+   them as if the colon and an empty string that follows it were not
+   there.
+
+ * Users with "color.ui = always" in their configuration were broken
+   by a recent change that made plumbing commands to pay attention to
+   them as the patch created internally by "git add -p" were colored
+   (heh) and made unusable.  This has been fixed.
+
+ * "git branch -M a b" while on a branch that is completely unrelated
+   to either branch a or branch b misbehaved when multiple worktree
+   was in use.  This has been fixed.
+
+ * "git fast-export" with -M/-C option issued "copy" instruction on a
+   path that is simultaneously modified, which was incorrect.
+
+ * The checkpoint command "git fast-import" did not flush updates to
+   refs and marks unless at least one object was created since the
+   last checkpoint, which has been corrected, as these things can
+   happen without any new object getting created.
+
+ * The scripts to drive TravisCI has been reorganized and then an
+   optimization to avoid spending cycles on a branch whose tip is
+   tagged has been implemented.
+
+ * "git fetch <there> <src>:<dst>" allows an object name on the <src>
+   side when the other side accepts such a request since Git v2.5, but
+   the documentation was left stale.
+
+ * A regression in 2.11 that made the code to read the list of
+   alternate object stores overrun the end of the string has been
+   fixed.
+
+Also contains various documentation updates and code clean-ups.
index cb63072..541815e 100644 (file)
@@ -8,16 +8,19 @@ Backward compatibility notes and other notable changes.
    more explicit '.' for that instead.  The hope is that existing
    users will not mind this change, and eventually the warning can be
    turned into a hard error, upgrading the deprecation into removal of
-   this (mis)feature.  That is now scheduled to happen in the upcoming
-   release.
+   this (mis)feature.  That is now scheduled to happen in Git v2.16,
+   the next major release after this one.
 
  * Git now avoids blindly falling back to ".git" when the setup
    sequence said we are _not_ in Git repository.  A corner case that
-   happens to work right now may be broken by a call to die("BUG").
+   happens to work right now may be broken by a call to BUG().
    We've tried hard to locate such cases and fixed them, but there
    might still be cases that need to be addressed--bug reports are
    greatly appreciated.
 
+ * "branch --set-upstream" that has been deprecated in Git 1.8 has
+   finally been retired.
+
 
 Updates since v2.14
 -------------------
@@ -58,6 +61,10 @@ UI, Workflows & Features
    other options to make it easier for scripts to grab existing
    trailer lines from a commit log message.
 
+ * The "--format=%(trailers)" option "git log" and its friends take
+   learned to take the 'unfold' and 'only' modifiers to normalize its
+   output, e.g. "git log --format=%(trailers:only,unfold)".
+
  * "gitweb" shows a link to visit the 'raw' contents of blbos in the
    history overview page.
 
@@ -71,6 +78,31 @@ UI, Workflows & Features
    which can make it succeed if the lock holder was holding it during
    a read-only operation.
 
+ * "branch --set-upstream" that has been deprecated in Git 1.8 has
+   finally been retired.
+
+ * The codepath to call external process filter for smudge/clean
+   operation learned to show the progress meter.
+
+ * "git rev-parse" learned "--is-shallow-repository", that is to be
+   used in a way similar to existing "--is-bare-repository" and
+   friends.
+
+ * "git describe --match <pattern>" has been taught to play well with
+   the "--all" option.
+
+ * "git branch" learned "-c/-C" to create a new branch by copying an
+   existing one.
+
+ * Some commands (most notably "git status") makes an opportunistic
+   update when performing a read-only operation to help optimize later
+   operations in the same repository.  The new "--no-optional-locks"
+   option can be passed to Git to disable them.
+
+ * "git for-each-ref --format=..." learned a new format element,
+   %(trailers), to show only the commit log trailer part of the log
+   message.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -101,7 +133,6 @@ Performance, Internal Implementation, Development Support etc.
  * A helper function to read a single whole line into strbuf
    mistakenly triggered OOM error at EOF under certain conditions,
    which has been fixed.
-   (merge 642956cf45 rs/strbuf-getwholeline-fix later to maint).
 
  * The "ref-store" code reorganization continues.
 
@@ -127,6 +158,87 @@ Performance, Internal Implementation, Development Support etc.
    piece of memory while writing each index entry out.  This has been
    optimized.
 
+ * Platforms that ship with a separate sha1 with collision detection
+   library can link to it instead of using the copy we ship as part of
+   our source tree.
+
+ * Code around "notes" have been cleaned up.
+   (merge 3964281524 mh/notes-cleanup later to maint).
+
+ * The long-standing rule that an in-core lockfile instance, once it
+   is used, must not be freed, has been lifted and the lockfile and
+   tempfile APIs have been updated to reduce the chance of programming
+   errors.
+
+ * Our hashmap implementation in hashmap.[ch] is not thread-safe when
+   adding a new item needs to expand the hashtable by rehashing; add
+   an API to disable the automatic rehashing to work it around.
+
+ * Many of our programs consider that it is OK to release dynamic
+   storage that is used throughout the life of the program by simply
+   exiting, but this makes it harder to leak detection tools to avoid
+   reporting false positives.  Plug many existing leaks and introduce
+   a mechanism for developers to mark that the region of memory
+   pointed by a pointer is not lost/leaking to help these tools.
+
+ * As "git commit" to conclude a conflicted "git merge" honors the
+   commit-msg hook, "git merge" that records a merge commit that
+   cleanly auto-merges should, but it didn't.
+
+ * The codepath for "git merge-recursive" has been cleaned up.
+
+ * Many leaks of strbuf have been fixed.
+
+ * "git imap-send" has our own implementation of the protocol and also
+   can use more recent libCurl with the imap protocol support.  Update
+   the latter so that it can use the credential subsystem, and then
+   make it the default option to use, so that we can eventually
+   deprecate and remove the former.
+
+ * "make style" runs git-clang-format to help developers by pointing
+   out coding style issues.
+
+ * A test to demonstrate "git mv" failing to adjust nested submodules
+   has been added.
+   (merge c514167df2 hv/mv-nested-submodules-test later to maint).
+
+ * On Cygwin, "ulimit -s" does not report failure but it does not work
+   at all, which causes an unexpected success of some tests that
+   expect failures under a limited stack situation.  This has been
+   fixed.
+
+ * Many codepaths have been updated to squelch -Wimplicit-fallthrough
+   warnings from Gcc 7 (which is a good code hygiene).
+
+ * Add a helper for DLL loading in anticipation for its need in a
+   future topic RSN.
+
+ * "git status --ignored", when noticing that a directory without any
+   tracked path is ignored, still enumerated all the ignored paths in
+   the directory, which is unnecessary.  The codepath has been
+   optimized to avoid this overhead.
+
+ * The final batch to "git rebase -i" updates to move more code from
+   the shell script to C has been merged.
+
+ * Operations that do not touch (majority of) packed refs have been
+   optimized by making accesses to packed-refs file lazy; we no longer
+   pre-parse everything, and an access to a single ref in the
+   packed-refs does not touch majority of irrelevant refs, either.
+
+ * Add comment to clarify that the style file is meant to be used with
+   clang-5 and the rules are still work in progress.
+
+ * Many variables that points at a region of memory that will live
+   throughout the life of the program have been marked with UNLEAK
+   marker to help the leak checkers concentrate on real leaks..
+
+ * Plans for weaning us off of SHA-1 has been documented.
+
+ * A new "oidmap" API has been introduced and oidset API has been
+   rewritten to use it.
+
+
 Also contains various documentation updates and code clean-ups.
 
 
@@ -155,7 +267,6 @@ Fixes since v2.14
  * Some versions of GnuPG fails to kill gpg-agent it auto-spawned
    and such a left-over agent can interfere with a test.  Work it
    around by attempting to kill one before starting a new test.
-   (merge 29ff1f8f74 st/lib-gpg-kill-stray-agent later to maint).
 
  * A recently added test for the "credential-cache" helper revealed
    that EOF detection done around the time the connection to the cache
@@ -164,49 +275,36 @@ Fixes since v2.14
 
  * "git log --tag=no-such-tag" showed log starting from HEAD, which
    has been fixed---it now shows nothing.
-   (merge 5d34d1ac06 jk/rev-list-empty-input later to maint).
 
  * The "tag.pager" configuration variable was useless for those who
    actually create tag objects, as it interfered with the use of an
    editor.  A new mechanism has been introduced for commands to enable
    pager depending on what operation is being carried out to fix this,
    and then "git tag -l" is made to run pager by default.
-   (merge 595d59e2b5 ma/pager-per-subcommand-action later to maint).
 
  * "git push --recurse-submodules $there HEAD:$target" was not
    propagated down to the submodules, but now it is.
-   (merge c7be7201a7 bw/push-options-recursively-to-submodules later to maint).
 
  * Commands like "git rebase" accepted the --rerere-autoupdate option
    from the command line, but did not always use it.  This has been
    fixed.
-   (merge f826fb799e pw/sequence-rerere-autoupdate later to maint).
 
  * "git clone --recurse-submodules --quiet" did not pass the quiet
    option down to submodules.
-   (merge 03c004c581 bw/clone-recursive-quiet later to maint).
 
  * Test portability fix for OBSD.
-   (merge bed67874e2 rs/obsd-getcwd-workaround later to maint).
-   (merge 4c7fda8fc1 rs/t4062-obsd later to maint).
 
  * Portability fix for OBSD.
-   (merge 29c2eda80b rs/in-obsd-basename-dirname-take-const later to maint).
 
  * "git am -s" has been taught that some input may end with a trailer
    block that is not Signed-off-by: and it should refrain from adding
    an extra blank line before adding a new sign-off in such a case.
-   (merge 735285b403 pw/am-signoff later to maint).
 
  * "git svn" used with "--localtime" option did not compute the tz
    offset for the timestamp in question and instead always used the
    current time, which has been corrected.
-   (merge 1adc4b9a58 ur/svn-local-zone later to maint).
 
  * Memory leak in an error codepath has been plugged.
-   (merge 83cd6f9017 rs/fsck-obj-leakfix later to maint).
-   (merge 896dca3ab7 rs/unpack-entry-leakfix later to maint).
-   (merge 149d8cbb2e rs/win32-syslog-leakfix later to maint).
 
  * "git stash -u" used the contents of the committed version of the
    ".gitignore" file to decide which paths are ignored, even when the
@@ -215,16 +313,13 @@ Fixes since v2.14
 
  * bash 4.4 or newer gave a warning on NUL byte in command
    substitution done in "git stash"; this has been squelched.
-   (merge 5fc92f8828 kd/stash-with-bash-4.4 later to maint).
 
  * "git grep -L" and "git grep --quiet -L" reported different exit
    codes; this has been corrected.
-   (merge e1f68c66d5 as/grep-quiet-no-match-exit-code-fix later to maint).
 
  * When handshake with a subprocess filter notices that the process
    asked for an unknown capability, Git did not report what program
    the offending subprocess was running.  This has been corrected.
-   (merge d3ba566342 cc/subprocess-handshake-missing-capabilities later to maint).
 
  * "git apply" that is used as a better "patch -p1" failed to apply a
    taken from a file with CRLF line endings to a file with CRLF line
@@ -233,34 +328,174 @@ Fixes since v2.14
    entry at the same path, which is a nonsense---in that mode, "apply"
    is not working on the data in (or derived from) the index at all.
    This has been fixed.
-   (merge c24f3abace tb/apply-with-crlf later to maint).
 
  * Killing "git merge --edit" before the editor returns control left
    the repository in a state with MERGE_MSG but without MERGE_HEAD,
    which incorrectly tells the subsequent "git commit" that there was
    a squash merge in progress.  This has been fixed.
-   (merge 9d89b35526 mg/killed-merge later to maint).
+
+ * "git archive" did not work well with pathspecs and the
+   export-ignore attribute.
+
+ * In addition to "cc: <a@dd.re.ss> # cruft", "cc: a@dd.re.ss # cruft"
+   was taught to "git send-email" as a valid way to tell it that it
+   needs to also send a carbon copy to <a@dd.re.ss> in the trailer
+   section.
+
+ * "git branch -M a b" while on a branch that is completely unrelated
+   to either branch a or branch b misbehaved when multiple worktree
+   was in use.  This has been fixed.
+   (merge 31824d180d nd/worktree-kill-parse-ref later to maint).
+
+ * "git gc" and friends when multiple worktrees are used off of a
+   single repository did not consider the index and per-worktree refs
+   of other worktrees as the root for reachability traversal, making
+   objects that are in use only in other worktrees to be subject to
+   garbage collection.
+
+ * A regression to "gitk --bisect" by a recent update has been fixed.
+
+ * "git -c submodule.recurse=yes pull" did not work as if the
+   "--recurse-submodules" option was given from the command line.
+   This has been corrected.
+
+ * Unlike "git commit-tree < file", "git commit-tree -F file" did not
+   pass the contents of the file verbatim and instead completed an
+   incomplete line at the end, if exists.  The latter has been updated
+   to match the behaviour of the former.
+
+ * Many codepaths did not diagnose write failures correctly when disks
+   go full, due to their misuse of write_in_full() helper function,
+   which have been corrected.
+   (merge f48ecd38cb jk/write-in-full-fix later to maint).
+
+ * "git help co" now says "co is aliased to ...", not "git co is".
+   (merge b3a8076e0d ks/help-alias-label later to maint).
+
+ * "git archive", especially when used with pathspec, stored an empty
+   directory in its output, even though Git itself never does so.
+   This has been fixed.
+
+ * API error-proofing which happens to also squelch warnings from GCC.
+
+ * The explanation of the cut-line in the commit log editor has been
+   slightly tweaked.
+   (merge 8c4b1a3593 ks/commit-do-not-touch-cut-line later to maint).
+
+ * "git gc" tries to avoid running two instances at the same time by
+   reading and writing pid/host from and to a lock file; it used to
+   use an incorrect fscanf() format when reading, which has been
+   corrected.
+
+ * The scripts to drive TravisCI has been reorganized and then an
+   optimization to avoid spending cycles on a branch whose tip is
+   tagged has been implemented.
+   (merge 8376eb4a8f ls/travis-scriptify later to maint).
+
+ * The test linter has been taught that we do not like "echo -e".
+
+ * Code cmp.std.c nitpick.
+
+ * A regression fix for 2.11 that made the code to read the list of
+   alternate object stores overrun the end of the string.
+   (merge f0f7bebef7 jk/info-alternates-fix later to maint).
+
+ * "git describe --match" learned to take multiple patterns in v2.13
+   series, but the feature ignored the patterns after the first one
+   and did not work at all.  This has been fixed.
+
+ * "git filter-branch" cannot reproduce a history with a tag without
+   the tagger field, which only ancient versions of Git allowed to be
+   created.  This has been corrected.
+   (merge b2c1ca6b4b ic/fix-filter-branch-to-handle-tag-without-tagger later to maint).
+
+ * "git cat-file --textconv" started segfaulting recently, which
+   has been corrected.
+
+ * The built-in pattern to detect the "function header" for HTML did
+   not match <H1>..<H6> elements without any attributes, which has
+   been fixed.
+
+ * "git mailinfo" was loose in decoding quoted printable and produced
+   garbage when the two letters after the equal sign are not
+   hexadecimal.  This has been fixed.
+
+ * The machinery to create xdelta used in pack files received the
+   sizes of the data in size_t, but lost the higher bits of them by
+   storing them in "unsigned int" during the computation, which is
+   fixed.
+
+ * The delta format used in the packfile cannot reference data at
+   offset larger than what can be expressed in 4-byte, but the
+   generator for the data failed to make sure the offset does not
+   overflow.  This has been corrected.
+
+ * The documentation for '-X<option>' for merges was misleadingly
+   written to suggest that "-s theirs" exists, which is not the case.
+
+ * "git fast-export" with -M/-C option issued "copy" instruction on a
+   path that is simultaneously modified, which was incorrect.
+   (merge b3e8ca89cf jt/fast-export-copy-modify-fix later to maint).
+
+ * Many codepaths have been updated to squelch -Wsign-compare
+   warnings.
+   (merge 071bcaab64 rj/no-sign-compare later to maint).
+
+ * Memory leaks in various codepaths have been plugged.
+   (merge 4d01a7fa65 ma/leakplugs later to maint).
+
+ * Recent versions of "git rev-parse --parseopt" did not parse the
+   option specification that does not have the optional flags (*=?!)
+   correctly, which has been corrected.
+   (merge a6304fa4c2 bc/rev-parse-parseopt-fix later to maint).
+
+ * The checkpoint command "git fast-import" did not flush updates to
+   refs and marks unless at least one object was created since the
+   last checkpoint, which has been corrected, as these things can
+   happen without any new object getting created.
+   (merge 30e215a65c er/fast-import-dump-refs-on-checkpoint later to maint).
+
+ * Spell the name of our system as "Git" in the output from
+   request-pull script.
+
+ * Fixes for a handful memory access issues identified by valgrind.
+
+ * Backports a moral equivalent of 2015 fix to the poll() emulation
+   from the upstream gnulib to fix occasional breakages on HPE NonStop.
+
+ * Users with "color.ui = always" in their configuration were broken
+   by a recent change that made plumbing commands to pay attention to
+   them as the patch created internally by "git add -p" were colored
+   (heh) and made unusable.  This has been fixed by reverting the
+   offending change.
+
+ * In the "--format=..." option of the "git for-each-ref" command (and
+   its friends, i.e. the listing mode of "git branch/tag"), "%(atom:)"
+   (e.g. "%(refname:)", "%(body:)" used to error out.  Instead, treat
+   them as if the colon and an empty string that follows it were not
+   there.
+
+ * An ancient bug that made Git misbehave with creation/renaming of
+   refs has been fixed.
+
+ * "git fetch <there> <src>:<dst>" allows an object name on the <src>
+   side when the other side accepts such a request since Git v2.5, but
+   the documentation was left stale.
+   (merge 83558a412a jc/fetch-refspec-doc-update later to maint).
+
+ * Update the documentation for "git filter-branch" so that the filter
+   options are listed in the same order as they are applied, as
+   described in an earlier part of the doc.
+   (merge 07c4984508 dg/filter-branch-filter-order-doc later to maint).
 
  * Other minor doc, test and build updates and code cleanups.
-   (merge dff2813391 ab/ref-filter-no-contains later to maint).
    (merge f094b89a4d ma/parse-maybe-bool later to maint).
-   (merge 974ce8078c mf/no-dashed-subcommands later to maint).
-   (merge f81935cc4d jc/perl-git-comment-typofix later to maint).
-   (merge 57ea241ef0 rs/t3700-clean-leftover later to maint).
-   (merge 39b00fa4d4 jk/drop-sha1-entry-pos later to maint).
-   (merge 0b006014c8 jk/hashcmp-memcmp later to maint).
-   (merge 1e22a9917b rj/add-chmod-error-message later to maint).
-   (merge 881529c846 rs/apply-lose-prefix-length later to maint).
-   (merge 6355a76802 rs/find-pack-entry-bisection later to maint).
-   (merge de3ce210ed rs/merge-microcleanup later to maint).
-   (merge 7f0a02be2f ah/doc-empty-string-is-false later to maint).
-   (merge 70ec6bd63b rs/t1002-do-not-use-sum later to maint).
-   (merge 2456990dfd sb/sha1-file-cleanup later to maint).
-   (merge 2aac933c62 hv/t5526-andand-chain-fix later to maint).
-   (merge c8d0c4fe9b sb/submodule-parallel-update later to maint).
-   (merge 794b7e1674 mg/format-ref-doc-fix later to maint).
-   (merge 24da8a26a9 rs/commit-h-single-parent-cleanup later to maint).
-   (merge 4e36907fa3 jk/doc-the-this later to maint).
-   (merge 15d1d0951e bc/vcs-svn-cleanup later to maint).
-   (merge b8f43b120b jn/vcs-svn-cleanup later to maint).
-   (merge 4a4becfb23 jt/doc-pack-objects-fix later to maint).
+   (merge 6cdf8a7929 ma/ts-cleanups later to maint).
+   (merge 7560f547e6 ma/up-to-date later to maint).
+   (merge 0db3dc75f3 rs/apply-epoch later to maint).
+   (merge 276d0e35c0 ma/split-symref-update-fix later to maint).
+   (merge f777623514 ks/branch-tweak-error-message-for-extra-args later to maint).
+   (merge 33f3c683ec ks/verify-filename-non-option-error-message-tweak later to maint).
+   (merge 7cbbf9d6a2 ls/filter-process-delayed later to maint).
+   (merge 488aa65c8f wk/merge-options-gpg-sign-doc later to maint).
+   (merge e61cb19a27 jc/branch-force-doc-readability-fix later to maint).
index dc4e3f5..1ac0ae6 100644 (file)
@@ -3085,10 +3085,14 @@ submodule.<name>.url::
        See linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
 
 submodule.<name>.update::
-       The default update procedure for a submodule. This variable
-       is populated by `git submodule init` from the
-       linkgit:gitmodules[5] file. See description of 'update'
-       command in linkgit:git-submodule[1].
+       The method by which a submodule is updated by 'git submodule update',
+       which is the only affected command, others such as
+       'git checkout --recurse-submodules' are unaffected. It exists for
+       historical reasons, when 'git submodule' was the only command to
+       interact with submodules; settings like `submodule.active`
+       and `pull.rebase` are more specific. It is populated by
+       `git submodule init` from the linkgit:gitmodules[5] file.
+       See description of 'update' command in linkgit:git-submodule[1].
 
 submodule.<name>.branch::
        The remote branch name for a submodule, used by `git submodule
index f4169fb..b700bea 100644 (file)
@@ -61,6 +61,9 @@ OPTIONS
        the working tree.  Note that older versions of Git used
        to ignore removed files; use `--no-all` option if you want
        to add modified or new files but ignore removed ones.
++
+For more details about the <pathspec> syntax, see the 'pathspec' entry
+in linkgit:gitglossary[7].
 
 -n::
 --dry-run::
index 631cbd8..4ebc3d3 100644 (file)
@@ -66,7 +66,7 @@ OPTIONS
        disables it is in effect), make sure the patch is
        applicable to what the current index file records.  If
        the file to be patched in the working tree is not
-       up-to-date, it is flagged as an error.  This flag also
+       up to date, it is flagged as an error.  This flag also
        causes the index file to be updated.
 
 --cached::
@@ -259,7 +259,7 @@ treats these changes as follows.
 If `--index` is specified (explicitly or implicitly), then the submodule
 commits must match the index exactly for the patch to apply.  If any
 of the submodules are checked-out, then these check-outs are completely
-ignored, i.e., they are not required to be up-to-date or clean and they
+ignored, i.e., they are not required to be up to date or clean and they
 are not updated.
 
 If `--index` is not specified, then the submodule commits in the patch
index d0b3358..d6587c5 100644 (file)
@@ -18,6 +18,7 @@ SYNOPSIS
 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
 'git branch' --unset-upstream [<branchname>]
 'git branch' (-m | -M) [<oldbranch>] <newbranch>
+'git branch' (-c | -C) [<oldbranch>] <newbranch>
 'git branch' (-d | -D) [-r] <branchname>...
 'git branch' --edit-description [<branchname>]
 
@@ -64,6 +65,10 @@ If <oldbranch> had a corresponding reflog, it is renamed to match
 renaming. If <newbranch> exists, -M must be used to force the rename
 to happen.
 
+The `-c` and `-C` options have the exact same semantics as `-m` and
+`-M`, except instead of the branch being renamed it along with its
+config and reflog will be copied to a new name.
+
 With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
 specify more than one branch for deletion.  If the branch currently
 has a reflog then the reflog will also be deleted.
@@ -92,19 +97,19 @@ OPTIONS
        all changes made to the branch ref, enabling use of date
        based sha1 expressions such as "<branchname>@\{yesterday}".
        Note that in non-bare repositories, reflogs are usually
-       enabled by default by the `core.logallrefupdates` config option.
+       enabled by default by the `core.logAllRefUpdates` config option.
        The negated form `--no-create-reflog` only overrides an earlier
        `--create-reflog`, but currently does not negate the setting of
-       `core.logallrefupdates`.
+       `core.logAllRefUpdates`.
 
 -f::
 --force::
-       Reset <branchname> to <startpoint> if <branchname> exists
-       already. Without `-f` 'git branch' refuses to change an existing branch.
+       Reset <branchname> to <startpoint>, even if <branchname> exists
+       already. Without `-f`, 'git branch' refuses to change an existing branch.
        In combination with `-d` (or `--delete`), allow deleting the
        branch irrespective of its merged status. In combination with
        `-m` (or `--move`), allow renaming the branch even if the new
-       branch name already exists.
+       branch name already exists, the same applies for `-c` (or `--copy`).
 
 -m::
 --move::
@@ -113,6 +118,13 @@ OPTIONS
 -M::
        Shortcut for `--move --force`.
 
+-c::
+--copy::
+       Copy a branch and the corresponding reflog.
+
+-C::
+       Shortcut for `--copy --force`.
+
 --color[=<when>]::
        Color branches to highlight current, local, and
        remote-tracking branches.
@@ -195,10 +207,8 @@ start-point is either a local or remote-tracking branch.
        branch.autoSetupMerge configuration variable is true.
 
 --set-upstream::
-       If specified branch does not exist yet or if `--force` has been
-       given, acts exactly like `--track`. Otherwise sets up configuration
-       like `--track` would when creating the branch, except that where
-       branch points to is not changed.
+       As this option had confusing syntax, it is no longer supported.
+       Please use `--track` or `--set-upstream-to` instead.
 
 -u <upstream>::
 --set-upstream-to=<upstream>::
index 204541c..fb09cd6 100644 (file)
@@ -192,7 +192,7 @@ newline. The available atoms are:
        The 40-hex object name of the object.
 
 `objecttype`::
-       The type of of the object (the same as `cat-file -t` reports).
+       The type of the object (the same as `cat-file -t` reports).
 
 `objectsize`::
        The size, in bytes, of the object (the same as `cat-file -s`
index d6399c0..e108b0f 100644 (file)
@@ -13,7 +13,8 @@ SYNOPSIS
 'git checkout' [-q] [-f] [-m] [--detach] <commit>
 'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
-'git checkout' [-p|--patch] [<tree-ish>] [--] [<paths>...]
+'git checkout' [<tree-ish>] [--] <pathspec>...
+'git checkout' (-p|--patch) [<tree-ish>] [--] [<paths>...]
 
 DESCRIPTION
 -----------
@@ -38,7 +39,7 @@ $ git checkout -b <branch> --track <remote>/<branch>
 ------------
 +
 You could omit <branch>, in which case the command degenerates to
-"check out the current branch", which is a glorified no-op with a
+"check out the current branch", which is a glorified no-op with
 rather expensive side-effects to show only the tracking information,
 if exists, for the current branch.
 
@@ -78,20 +79,13 @@ be used to detach HEAD at the tip of the branch (`git checkout
 +
 Omitting <branch> detaches HEAD at the tip of the current branch.
 
-'git checkout' [-p|--patch] [<tree-ish>] [--] <pathspec>...::
+'git checkout' [<tree-ish>] [--] <pathspec>...::
 
-       When <paths> or `--patch` are given, 'git checkout' does *not*
-       switch branches.  It updates the named paths in the working tree
-       from the index file or from a named <tree-ish> (most often a
-       commit).  In this case, the `-b` and `--track` options are
-       meaningless and giving either of them results in an error.  The
-       <tree-ish> argument can be used to specify a specific tree-ish
-       (i.e.  commit, tag or tree) to update the index for the given
-       paths before updating the working tree.
-+
-'git checkout' with <paths> or `--patch` is used to restore modified or
-deleted paths to their original contents from the index or replace paths
-with the contents from a named <tree-ish> (most often a commit-ish).
+       Overwrite paths in the working tree by replacing with the
+       contents in the index or in the <tree-ish> (most often a
+       commit).  When a <tree-ish> is given, the paths that
+       match the <pathspec> are updated both in the index and in
+       the working tree.
 +
 The index may contain unmerged entries because of a previous failed merge.
 By default, if you try to check out such an entry from the index, the
@@ -101,6 +95,14 @@ specific side of the merge can be checked out of the index by
 using `--ours` or `--theirs`.  With `-m`, changes made to the working tree
 file can be discarded to re-create the original conflicted merge result.
 
+'git checkout' (-p|--patch) [<tree-ish>] [--] [<pathspec>...]::
+       This is similar to the "check out paths to the working tree
+       from either the index or from a tree-ish" mode described
+       above, but lets you use the interactive interface to show
+       the "diff" output and choose which hunks to use in the
+       result.  See below for the description of `--patch` option.
+
+
 OPTIONS
 -------
 -q::
index a336ae5..ba90066 100644 (file)
@@ -223,7 +223,7 @@ access method and requested operation.
 That means that even if you offer only read access (e.g. by using
 the pserver method), 'git-cvsserver' should have write access to
 the database to work reliably (otherwise you need to make sure
-that the database is up-to-date any time 'git-cvsserver' is executed).
+that the database is up to date any time 'git-cvsserver' is executed).
 
 By default it uses SQLite databases in the Git directory, named
 `gitcvs.<module_name>.sqlite`. Note that the SQLite backend creates
index 26f19d3..c924c94 100644 (file)
@@ -87,19 +87,23 @@ OPTIONS
 
 --match <pattern>::
        Only consider tags matching the given `glob(7)` pattern,
-       excluding the "refs/tags/" prefix.  This can be used to avoid
-       leaking private tags from the repository. If given multiple times, a
-       list of patterns will be accumulated, and tags matching any of the
-       patterns will be considered. Use `--no-match` to clear and reset the
-       list of patterns.
+       excluding the "refs/tags/" prefix. If used with `--all`, it also
+       considers local branches and remote-tracking references matching the
+       pattern, excluding respectively "refs/heads/" and "refs/remotes/"
+       prefix; references of other types are never considered. If given
+       multiple times, a list of patterns will be accumulated, and tags
+       matching any of the patterns will be considered.  Use `--no-match` to
+       clear and reset the list of patterns.
 
 --exclude <pattern>::
        Do not consider tags matching the given `glob(7)` pattern, excluding
-       the "refs/tags/" prefix. This can be used to narrow the tag space and
-       find only tags matching some meaningful criteria. If given multiple
-       times, a list of patterns will be accumulated and tags matching any
-       of the patterns will be excluded. When combined with --match a tag will
-       be considered when it matches at least one --match pattern and does not
+       the "refs/tags/" prefix. If used with `--all`, it also does not consider
+       local branches and remote-tracking references matching the pattern,
+       excluding respectively "refs/heads/" and "refs/remotes/" prefix;
+       references of other types are never considered. If given multiple times,
+       a list of patterns will be accumulated and tags matching any of the
+       patterns will be excluded. When combined with --match a tag will be
+       considered when it matches at least one --match pattern and does not
        match any of the --exclude patterns. Use `--no-exclude` to clear and
        reset the list of patterns.
 
index a171506..b380677 100644 (file)
@@ -85,7 +85,7 @@ a 'git write-tree' + 'git diff-tree'. Thus that's the default mode.
 The non-cached version asks the question:
 
   show me the differences between HEAD and the currently checked out
-  tree - index contents _and_ files that aren't up-to-date
+  tree - index contents _and_ files that aren't up to date
 
 which is obviously a very useful question too, since that tells you what
 you *could* commit. Again, the output matches the 'git diff-tree -r'
@@ -100,8 +100,8 @@ have not actually done a 'git update-index' on it yet - there is no
   torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD
   :100644 100664 7476bb... 000000...      kernel/sched.c
 
-i.e., it shows that the tree has changed, and that `kernel/sched.c` has is
-not up-to-date and may contain new stuff. The all-zero sha1 means that to
+i.e., it shows that the tree has changed, and that `kernel/sched.c` is
+not up to date and may contain new stuff. The all-zero sha1 means that to
 get the real diff, you need to look at the object in the working directory
 directly rather than do an object-to-object diff.
 
index 9e5169a..3a52e4d 100644 (file)
@@ -8,13 +8,13 @@ git-filter-branch - Rewrite branches
 SYNOPSIS
 --------
 [verse]
-'git filter-branch' [--setup <command>] [--env-filter <command>]
-       [--tree-filter <command>] [--index-filter <command>]
-       [--parent-filter <command>] [--msg-filter <command>]
-       [--commit-filter <command>] [--tag-name-filter <command>]
-       [--subdirectory-filter <directory>] [--prune-empty]
+'git filter-branch' [--setup <command>] [--subdirectory-filter <directory>]
+       [--env-filter <command>] [--tree-filter <command>]
+       [--index-filter <command>] [--parent-filter <command>]
+       [--msg-filter <command>] [--commit-filter <command>]
+       [--tag-name-filter <command>] [--prune-empty]
        [--original <namespace>] [-d <directory>] [-f | --force]
-       [--] [<rev-list options>...]
+       [--state-branch <branch>] [--] [<rev-list options>...]
 
 DESCRIPTION
 -----------
@@ -89,6 +89,11 @@ OPTIONS
        can be used or modified in the following filter steps except
        the commit filter, for technical reasons.
 
+--subdirectory-filter <directory>::
+       Only look at the history which touches the given subdirectory.
+       The result will contain that directory (and only that) as its
+       project root. Implies <<Remap_to_ancestor>>.
+
 --env-filter <command>::
        This filter may be used if you only need to modify the environment
        in which the commit will be performed.  Specifically, you might
@@ -167,11 +172,6 @@ be removed, buyer beware. There is also no support for changing the
 author or timestamp (or the tag message for that matter). Tags which point
 to other tags will be rewritten to point to the underlying commit.
 
---subdirectory-filter <directory>::
-       Only look at the history which touches the given subdirectory.
-       The result will contain that directory (and only that) as its
-       project root. Implies <<Remap_to_ancestor>>.
-
 --prune-empty::
        Some filters will generate empty commits that leave the tree untouched.
        This option instructs git-filter-branch to remove such commits if they
@@ -198,6 +198,12 @@ to other tags will be rewritten to point to the underlying commit.
        directory or when there are already refs starting with
        'refs/original/', unless forced.
 
+--state-branch <branch>::
+       This option will cause the mapping from old to new objects to
+       be loaded from named branch upon startup and saved as a new
+       commit to that branch upon exit, enabling incremental of large
+       trees. If '<branch>' does not exist it will be created.
+
 <rev-list options>...::
        Arguments for 'git rev-list'.  All positive refs included by
        these options are rewritten.  You may also specify options
index bb370c9..1d420e4 100644 (file)
@@ -10,8 +10,9 @@ SYNOPSIS
 [verse]
 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
                   [(--sort=<key>)...] [--format=<format>] [<pattern>...]
-                  [--points-at <object>] [(--merged | --no-merged) [<object>]]
-                  [--contains [<object>]] [--no-contains [<object>]]
+                  [--points-at=<object>]
+                  (--merged[=<object>] | --no-merged[=<object>])
+                  [--contains[=<object>]] [--no-contains[=<object>]]
 
 DESCRIPTION
 -----------
@@ -25,19 +26,25 @@ host language allowing their direct evaluation in that language.
 
 OPTIONS
 -------
-<count>::
+<pattern>...::
+       If one or more patterns are given, only refs are shown that
+       match against at least one pattern, either using fnmatch(3) or
+       literally, in the latter case matching completely or from the
+       beginning up to a slash.
+
+--count=<count>::
        By default the command shows all refs that match
        `<pattern>`.  This option makes it stop after showing
        that many refs.
 
-<key>::
+--sort=<key>::
        A field name to sort on.  Prefix `-` to sort in
        descending order of the value.  When unspecified,
        `refname` is used.  You may use the --sort=<key> option
        multiple times, in which case the last key becomes the primary
        key.
 
-<format>::
+--format=<format>::
        A string that interpolates `%(fieldname)` from a ref being shown
        and the object it points at.  If `fieldname`
        is prefixed with an asterisk (`*`) and the ref points
@@ -50,11 +57,10 @@ OPTIONS
        `xx`; for example `%00` interpolates to `\0` (NUL),
        `%09` to `\t` (TAB) and `%0a` to `\n` (LF).
 
-<pattern>...::
-       If one or more patterns are given, only refs are shown that
-       match against at least one pattern, either using fnmatch(3) or
-       literally, in the latter case matching completely or from the
-       beginning up to a slash.
+--color[=<when>]:
+       Respect any colors specified in the `--format` option. The
+       `<when>` field must be one of `always`, `never`, or `auto` (if
+       `<when>` is absent, behave as if `always` was given).
 
 --shell::
 --perl::
@@ -65,24 +71,24 @@ OPTIONS
        the specified host language.  This is meant to produce
        a scriptlet that can directly be `eval`ed.
 
---points-at <object>::
+--points-at=<object>::
        Only list refs which points at the given object.
 
---merged [<object>]::
+--merged[=<object>]::
        Only list refs whose tips are reachable from the
        specified commit (HEAD if not specified),
        incompatible with `--no-merged`.
 
---no-merged [<object>]::
+--no-merged[=<object>]::
        Only list refs whose tips are not reachable from the
        specified commit (HEAD if not specified),
        incompatible with `--merged`.
 
---contains [<object>]::
+--contains[=<object>]::
        Only list refs which contain the specified commit (HEAD if not
        specified).
 
---no-contains [<object>]::
+--no-contains[=<object>]::
        Only list refs which don't contain the specified commit (HEAD
        if not specified).
 
@@ -212,11 +218,15 @@ and `date` to extract the named component.
 The complete message in a commit and tag object is `contents`.
 Its first line is `contents:subject`, where subject is the concatenation
 of all lines of the commit message up to the first blank line.  The next
-line is 'contents:body', where body is all of the lines after the first
+line is `contents:body`, where body is all of the lines after the first
 blank line.  The optional GPG signature is `contents:signature`.  The
 first `N` lines of the message is obtained using `contents:lines=N`.
 Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
-are obtained as 'contents:trailers'.
+are obtained as `trailers` (or by using the historical alias
+`contents:trailers`).  Non-trailer lines from the trailer block can be omitted
+with `trailers:only`. Whitespace-continuations can be removed from trailers so
+that each trailer appears on a line by itself with its full content with
+`trailers:unfold`. Both can be used together as `trailers:unfold,only`.
 
 For sorting purposes, fields with numeric values sort in numeric order
 (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`).
index 720c785..18b4947 100644 (file)
@@ -289,6 +289,9 @@ providing this option will cause it to die.
 <pathspec>...::
        If given, limit the search to paths matching at least one pattern.
        Both leading paths match and glob(7) patterns are supported.
++
+For more details about the <pathspec> syntax, see the 'pathspec' entry
+in linkgit:gitglossary[7].
 
 Examples
 --------
@@ -305,6 +308,9 @@ Examples
        Looks for a line that has `NODE` or `Unexpected` in
        files that have lines that match both.
 
+`git grep solution -- :^Documentation`::
+       Looks for `solution`, excluding files in `Documentation`.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
index 615e6ba..3c6927b 100644 (file)
@@ -72,12 +72,6 @@ include::merge-options.txt[]
        agrees to a Developer Certificate of Origin
        (see http://developercertificate.org/ for more information).
 
--S[<keyid>]::
---gpg-sign[=<keyid>]::
-       GPG-sign the resulting merge commit. The `keyid` argument is
-       optional and defaults to the committer identity; if specified,
-       it must be stuck to the option without a space.
-
 -m <msg>::
        Set the commit message to be used for the merge commit (in
        case one is created).
@@ -141,7 +135,7 @@ exception is when the changed index entries are in the state that
 would result from the merge already.)
 
 If all named commits are already ancestors of `HEAD`, 'git merge'
-will exit early with the message "Already up-to-date."
+will exit early with the message "Already up to date."
 
 FAST-FORWARD MERGE
 ------------------
index be7db30..4367729 100644 (file)
@@ -171,7 +171,7 @@ OPTIONS
        object that does not have notes attached to it.
 
 --stdin::
-       Also read the object names to remove notes from from the standard
+       Also read the object names to remove notes from the standard
        input (there is no reason you cannot combine this with object
        names from the command line).
 
index 02576d8..72bd809 100644 (file)
@@ -179,6 +179,7 @@ Here are the "carry forward" rules, where "I" denotes the index,
 "clean" means that index and work tree coincide, and "exists"/"nothing"
 refer to the presence of a path in the specified commit:
 
+....
        I                   H        M        Result
        -------------------------------------------------------
      0  nothing             nothing  nothing  (does not happen)
@@ -217,6 +218,7 @@ refer to the presence of a path in the specified commit:
      19 no    no    yes     exists   exists   keep index
      20 yes   yes   no      exists   exists   use M
      21 no    yes   no      exists   exists   fail
+....
 
 In all "keep index" cases, the index entry stays as in the
 original index file.  If the entry is not up to date,
index 4f6bed6..3cedfb0 100644 (file)
@@ -334,7 +334,7 @@ which makes little sense.
 
 -f::
 --force-rebase::
-       Force a rebase even if the current branch is up-to-date and
+       Force a rebase even if the current branch is up to date and
        the command without `--force` would return without doing anything.
 +
 You may find this (or --no-ff with an interactive rebase) helpful after
@@ -430,13 +430,15 @@ without an explicit `--interactive`.
 --autosquash::
 --no-autosquash::
        When the commit log message begins with "squash! ..." (or
-       "fixup! ..."), and there is a commit whose title begins with
-       the same ..., automatically modify the todo list of rebase -i
-       so that the commit marked for squashing comes right after the
-       commit to be modified, and change the action of the moved
-       commit from `pick` to `squash` (or `fixup`).  Ignores subsequent
-       "fixup! " or "squash! " after the first, in case you referred to an
-       earlier fixup/squash with `git commit --fixup/--squash`.
+       "fixup! ..."), and there is already a commit in the todo list that
+       matches the same `...`, automatically modify the todo list of rebase
+       -i so that the commit marked for squashing comes right after the
+       commit to be modified, and change the action of the moved commit
+       from `pick` to `squash` (or `fixup`).  A commit matches the `...` if
+       the commit subject matches, or if the `...` refers to the commit's
+       hash. As a fall-back, partial matches of the commit subject work,
+       too.  The recommended way to create fixup/squash commits is by using
+       the `--fixup`/`--squash` options of linkgit:git-commit[1].
 +
 This option is only valid when the `--interactive` option is used.
 +
index 9ee083c..031f31f 100644 (file)
@@ -205,7 +205,7 @@ development on the topic branch:
 ------------
 
 you could run `git rebase master topic`, to bring yourself
-up-to-date before your topic is ready to be sent upstream.
+up to date before your topic is ready to be sent upstream.
 This would result in falling back to a three-way merge, and it
 would conflict the same way as the test merge you resolved earlier.
 'git rerere' will be run by 'git rebase' to help you resolve this
index b1293f2..0917b82 100644 (file)
@@ -235,6 +235,9 @@ print a message to stderr and exit with nonzero status.
 --is-bare-repository::
        When the repository is bare print "true", otherwise "false".
 
+--is-shallow-repository::
+       When the repository is shallow print "true", otherwise "false".
+
 --resolve-git-dir <path>::
        Check if <path> is a valid repository or a gitfile that
        points at a valid repository, and print the location of the
index 683e591..b5c4622 100644 (file)
@@ -146,7 +146,7 @@ the submodule's history. If it exists the submodule.<name> section
 in the linkgit:gitmodules[5] file will also be removed and that file
 will be staged (unless --cached or -n are used).
 
-A submodule is considered up-to-date when the HEAD is the same as
+A submodule is considered up to date when the HEAD is the same as
 recorded in the index, no tracked files are modified and no untracked
 files that aren't ignored are present in the submodules work tree.
 Ignored files are deemed expendable and won't stop a submodule's work
index 2e30a3e..54cf256 100644 (file)
@@ -79,6 +79,22 @@ EOF
 $ chmod +x $HOME/git-shell-commands/no-interactive-login
 ----------------
 
+To enable git-cvsserver access (which should generally have the
+`no-interactive-login` example above as a prerequisite, as creating
+the git-shell-commands directory allows interactive logins):
+
+----------------
+$ cat >$HOME/git-shell-commands/cvs <<\EOF
+if ! test $# = 1 && test "$1" = "server"
+then
+       echo >&2 "git-cvsserver only handles \"server\""
+       exit 1
+fi
+exec git cvsserver server
+EOF
+$ chmod +x $HOME/git-shell-commands/cvs
+----------------
+
 SEE ALSO
 --------
 ssh(1),
index d47f198..9f3a78a 100644 (file)
@@ -111,6 +111,8 @@ configuration variable documented in linkgit:git-config[1].
        without options are equivalent to 'always' and 'never'
        respectively.
 
+<pathspec>...::
+       See the 'pathspec' entry in linkgit:gitglossary[7].
 
 OUTPUT
 ------
index aa2aeab..636e090 100644 (file)
@@ -424,7 +424,7 @@ Any other arguments are passed directly to 'git log'
 'set-tree'::
        You should consider using 'dcommit' instead of this command.
        Commit specified commit or tree objects to SVN.  This relies on
-       your imported fetch data being up-to-date.  This makes
+       your imported fetch data being up to date.  This makes
        absolutely no attempts to do patching when committing to SVN, it
        simply overwrites files with those specified in the tree or
        commit.  All merging is assumed to have taken place
index 543fb42..956fc01 100644 (file)
@@ -115,6 +115,11 @@ options for details.
        variable if it exists, or lexicographic order otherwise. See
        linkgit:git-config[1].
 
+--color[=<when>]:
+       Respect any colors specified in the `--format` option. The
+       `<when>` field must be one of `always`, `never`, or `auto` (if
+       `<when>` is absent, behave as if `always` was given).
+
 -i::
 --ignore-case::
        Sorting and filtering tags are case insensitive.
@@ -174,7 +179,7 @@ This option is only applicable when listing tags without annotation lines.
        `core.logAllRefUpdates` in linkgit:git-config[1].
        The negated form `--no-create-reflog` only overrides an earlier
        `--create-reflog`, but currently does not negate the setting of
-       `core.logallrefupdates`.
+       `core.logAllRefUpdates`.
 
 <tagname>::
        The name of the tag to create, delete, or describe.
index 1579abf..75c7dd9 100644 (file)
@@ -153,7 +153,7 @@ you will need to handle the situation manually.
 +
 Version 4 performs a simple pathname compression that reduces index
 size by 30%-50% on large repositories, which results in faster load
-time. Version 4 is relatively young (first released in in 1.8.0 in
+time. Version 4 is relatively young (first released in 1.8.0 in
 October 2012). Other Git implementations such as JGit and libgit2
 may not support it yet.
 
@@ -214,7 +214,7 @@ will remove the intended effect of the option.
 Using --refresh
 ---------------
 `--refresh` does not calculate a new sha1 file or bring the index
-up-to-date for mode/content changes. But what it *does* do is to
+up to date for mode/content changes. But what it *does* do is to
 "re-match" the stat information of a file with the index, so that you
 can refresh the index for a file that hasn't been changed but where
 the stat entry is out of date.
index 6e3a676..7a1d629 100644 (file)
@@ -75,7 +75,7 @@ example the following invocations are equivalent:
 Note that omitting the `=` in `git -c foo.bar ...` is allowed and sets
 `foo.bar` to the boolean true value (just like `[foo]bar` would in a
 config file). Including the equals but with an empty value (like `git -c
-foo.bar= ...`) sets `foo.bar` to the empty string which ` git config
+foo.bar= ...`) sets `foo.bar` to the empty string which `git config
 --bool` will convert to `false`.
 
 --exec-path[=<path>]::
@@ -159,6 +159,10 @@ foo.bar= ...`) sets `foo.bar` to the empty string which ` git config
        Add "icase" magic to all pathspec. This is equivalent to setting
        the `GIT_ICASE_PATHSPECS` environment variable to `1`.
 
+--no-optional-locks::
+       Do not perform optional operations that require locks. This is
+       equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`.
+
 GIT COMMANDS
 ------------
 
@@ -697,6 +701,14 @@ of clones and fetches.
        which feed potentially-untrusted URLS to git commands.  See
        linkgit:git-config[1] for more details.
 
+`GIT_OPTIONAL_LOCKS`::
+       If set to `0`, Git will complete any requested operation without
+       performing any optional sub-operations that require taking a lock.
+       For example, this will prevent `git status` from refreshing the
+       index as a side effect. This is useful for processes running in
+       the background which do not want to cause lock contention with
+       other operations on the repository.  Defaults to `1`.
+
 Discussion[[Discussion]]
 ------------------------
 
index c4f2be2..4c68bc1 100644 (file)
@@ -151,7 +151,10 @@ unspecified.
 
 This attribute sets a specific line-ending style to be used in the
 working directory.  It enables end-of-line conversion without any
-content checks, effectively setting the `text` attribute.
+content checks, effectively setting the `text` attribute.  Note that
+setting this attribute on paths which are in the index with CRLF line
+endings may make the paths to be considered dirty.  Adding the path to
+the index again will normalize the line endings in the index.
 
 Set to string value "crlf"::
 
index 7577f27..e29a9ef 100644 (file)
@@ -631,7 +631,7 @@ So after you do a `cp -a` to create a new copy, you'll want to do
 $ git update-index --refresh
 ----------------
 +
-in the new repository to make sure that the index file is up-to-date.
+in the new repository to make sure that the index file is up to date.
 
 Note that the second point is true even across machines. You can
 duplicate a remote Git repository with *any* regular copy mechanism, be it
@@ -701,7 +701,7 @@ $ git checkout-index -u -a
 ----------------
 
 where the `-u` flag means that you want the checkout to keep the index
-up-to-date (so that you don't have to refresh it afterward), and the
+up to date (so that you don't have to refresh it afterward), and the
 `-a` flag means "check out all files" (if you have a stale copy or an
 older version of a checked out tree you may also need to add the `-f`
 flag first, to tell 'git checkout-index' to *force* overwriting of any old
@@ -1283,7 +1283,7 @@ run a single command, 'git-receive-pack'.
 
 First, you need to create an empty repository on the remote
 machine that will house your public repository. This empty
-repository will be populated and be kept up-to-date by pushing
+repository will be populated and be kept up to date by pushing
 into it later. Obviously, this repository creation needs to be
 done only once.
 
@@ -1450,7 +1450,7 @@ transport protocols (HTTP), you need to keep this repository
 would contain a call to 'git update-server-info'
 but you need to manually enable the hook with
 `mv post-update.sample post-update`.  This makes sure
-'git update-server-info' keeps the necessary files up-to-date.
+'git update-server-info' keeps the necessary files up to date.
 
 3. Push into the public repository from your primary
    repository.
index 623ed1a..5d3f455 100644 (file)
@@ -127,11 +127,10 @@ help message found in the commented portion of the commit template.
 commit-msg
 ~~~~~~~~~~
 
-This hook is invoked by 'git commit', and can be bypassed
-with the `--no-verify` option.  It takes a single parameter, the
-name of the file that holds the proposed commit log message.
-Exiting with a non-zero status causes the 'git commit' to
-abort.
+This hook is invoked by 'git commit' and 'git merge', and can be
+bypassed with the `--no-verify` option.  It takes a single parameter,
+the name of the file that holds the proposed commit log message.
+Exiting with a non-zero status causes the command to abort.
 
 The hook is allowed to edit the message file in place, and can be used
 to normalize the message into some project standard format. It
@@ -369,7 +368,7 @@ them.
 
 When enabled, the default 'post-update' hook runs
 'git update-server-info' to keep the information used by dumb
-transports (e.g., HTTP) up-to-date.  If you are publishing
+transports (e.g., HTTP) up to date.  If you are publishing
 a Git repository that is accessible via HTTP, you should
 probably enable this hook.
 
index f51ed4e..adf9554 100644 (file)
@@ -71,7 +71,7 @@ objects/info/packs::
        This file is to help dumb transports discover what packs
        are available in this object store.  Whenever a pack is
        added or removed, `git update-server-info` should be run
-       to keep this file up-to-date if the repository is
+       to keep this file up to date if the repository is
        published for dumb transports.  'git repack' does this
        by default.
 
index 794b833..242de31 100644 (file)
@@ -109,7 +109,7 @@ summary of the situation with 'git status':
 $ git status
 On branch master
 Changes to be committed:
-Your branch is up-to-date with 'origin/master'.
+Your branch is up to date with 'origin/master'.
   (use "git reset HEAD <file>..." to unstage)
 
        modified:   file1
index b71b943..6b8888d 100644 (file)
@@ -407,7 +407,7 @@ these forms:
 
 exclude;;
        After a path matches any non-exclude pathspec, it will be run
-       through all exclude pathspec (magic signature: `!` or its
+       through all exclude pathspecs (magic signature: `!` or its
        synonym `^`). If it matches, the path is ignored.  When there
        is no non-exclude pathspec, the exclusion is applied to the
        result set as if invoked without any pathspec.
index 5b4a62e..2552ab8 100644 (file)
@@ -39,9 +39,15 @@ set to `no` at the beginning of them.
 
 --ff-only::
        Refuse to merge and exit with a non-zero status unless the
-       current `HEAD` is already up-to-date or the merge can be
+       current `HEAD` is already up to date or the merge can be
        resolved as a fast-forward.
 
+-S[<keyid>]::
+--gpg-sign[=<keyid>]::
+       GPG-sign the resulting merge commit. The `keyid` argument is
+       optional and defaults to the committer identity; if specified,
+       it must be stuck to the option without a space.
+
 --log[=<n>]::
 --no-log::
        In addition to branch names, populate the log message with
index 2eb92b9..a09d597 100644 (file)
@@ -39,7 +39,8 @@ even look at what the other tree contains at all.  It discards everything
 the other tree did, declaring 'our' history contains all that happened in it.
 
 theirs;;
-       This is the opposite of 'ours'.
+       This is the opposite of 'ours'; note that, unlike 'ours', there is
+       no 'theirs' merge stragegy to confuse this merge option with.
 
 patience;;
        With this option, 'merge-recursive' spends a little extra time
index 1ebbf1d..c579793 100644 (file)
@@ -23,9 +23,11 @@ ifdef::git-pull[]
 endif::git-pull[]
 +
 The format of a <refspec> parameter is an optional plus
-`+`, followed by the source ref <src>, followed
+`+`, followed by the source <src>, followed
 by a colon `:`, followed by the destination ref <dst>.
-The colon can be omitted when <dst> is empty.
+The colon can be omitted when <dst> is empty.  <src> is
+typically a ref, but it can also be a fully spelled hex object
+name.
 +
 `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
 it requests fetching everything up to the given tag.
index a6cf9eb..7d860bf 100644 (file)
@@ -184,6 +184,14 @@ explicitly.
        Pretend as if all objects mentioned by reflogs are listed on the
        command line as `<commit>`.
 
+--single-worktree::
+       By default, all working trees will be examined by the
+       following options when there are more than one (see
+       linkgit:git-worktree[1]): `--all`, `--reflog` and
+       `--indexed-objects`.
+       This option forces them to examine the current working tree
+       only.
+
 --ignore-missing::
        Upon seeing an invalid object name in the input, pretend as if
        the bad input was not given.
index cfc0630..870c8ed 100644 (file)
@@ -8,7 +8,7 @@ always NULL-terminated at the element pointed to by `argv[argc]`. This
 makes the result suitable for passing to functions expecting to receive
 argv from main(), or the link:api-run-command.html[run-command API].
 
-The link:api-string-list.html[string-list API] is similar, but cannot be
+The string-list API (documented in string-list.h) is similar, but cannot be
 used for these purposes; instead of storing a straight string pointer,
 it contains an item structure with a `util` field that is not compatible
 with the traditional argv interface.
index 7a83a3a..9a778b0 100644 (file)
@@ -186,10 +186,6 @@ parsing is successful, the return value is the result.
 Same as `git_config_bool`, except that integers are returned as-is, and
 an `is_bool` flag is unset.
 
-`git_config_maybe_bool`::
-Deprecated. Use `git_parse_maybe_bool` instead. They are exactly the
-same, except this function takes an unused argument `name`.
-
 `git_parse_maybe_bool`::
 Same as `git_config_bool`, except that it returns -1 on error rather
 than dying.
index 37379d8..46c3d5c 100644 (file)
@@ -32,11 +32,8 @@ Iteration functions
 
 * `for_each_glob_ref_in()` the previous and `for_each_ref_in()` combined.
 
-* `head_ref_submodule()`, `for_each_ref_submodule()`,
-  `for_each_ref_in_submodule()`, `for_each_tag_ref_submodule()`,
-  `for_each_branch_ref_submodule()`, `for_each_remote_ref_submodule()`
-  do the same as the functions described above but for a specified
-  submodule.
+* Use `refs_` API for accessing submodules. The submodule ref store could
+  be obtained with `get_submodule_ref_store()`.
 
 * `for_each_rawref()` can be used to learn about broken ref and symref.
 
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
deleted file mode 100644 (file)
index c08402b..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-string-list API
-===============
-
-The string_list API offers a data structure and functions to handle
-sorted and unsorted string lists.  A "sorted" list is one whose
-entries are sorted by string value in `strcmp()` order.
-
-The 'string_list' struct used to be called 'path_list', but was renamed
-because it is not specific to paths.
-
-The caller:
-
-. Allocates and clears a `struct string_list` variable.
-
-. Initializes the members. You might want to set the flag `strdup_strings`
-  if the strings should be strdup()ed. For example, this is necessary
-  when you add something like git_path("..."), since that function returns
-  a static buffer that will change with the next call to git_path().
-+
-If you need something advanced, you can manually malloc() the `items`
-member (you need this if you add things later) and you should set the
-`nr` and `alloc` members in that case, too.
-
-. Adds new items to the list, using `string_list_append`,
-  `string_list_append_nodup`, `string_list_insert`,
-  `string_list_split`, and/or `string_list_split_in_place`.
-
-. Can check if a string is in the list using `string_list_has_string` or
-  `unsorted_string_list_has_string` and get it from the list using
-  `string_list_lookup` for sorted lists.
-
-. Can sort an unsorted list using `string_list_sort`.
-
-. Can remove duplicate items from a sorted list using
-  `string_list_remove_duplicates`.
-
-. Can remove individual items of an unsorted list using
-  `unsorted_string_list_delete_item`.
-
-. Can remove items not matching a criterion from a sorted or unsorted
-  list using `filter_string_list`, or remove empty strings using
-  `string_list_remove_empty_items`.
-
-. Finally it should free the list using `string_list_clear`.
-
-Example:
-
-----
-struct string_list list = STRING_LIST_INIT_NODUP;
-int i;
-
-string_list_append(&list, "foo");
-string_list_append(&list, "bar");
-for (i = 0; i < list.nr; i++)
-       printf("%s\n", list.items[i].string)
-----
-
-NOTE: It is more efficient to build an unsorted list and sort it
-afterwards, instead of building a sorted list (`O(n log n)` instead of
-`O(n^2)`).
-+
-However, if you use the list to check if a certain string was added
-already, you should not do that (using unsorted_string_list_has_string()),
-because the complexity would be quadratic again (but with a worse factor).
-
-Functions
----------
-
-* General ones (works with sorted and unsorted lists as well)
-
-`string_list_init`::
-
-       Initialize the members of the string_list, set `strdup_strings`
-       member according to the value of the second parameter.
-
-`filter_string_list`::
-
-       Apply a function to each item in a list, retaining only the
-       items for which the function returns true.  If free_util is
-       true, call free() on the util members of any items that have
-       to be deleted.  Preserve the order of the items that are
-       retained.
-
-`string_list_remove_empty_items`::
-
-       Remove any empty strings from the list.  If free_util is true,
-       call free() on the util members of any items that have to be
-       deleted.  Preserve the order of the items that are retained.
-
-`print_string_list`::
-
-       Dump a string_list to stdout, useful mainly for debugging purposes. It
-       can take an optional header argument and it writes out the
-       string-pointer pairs of the string_list, each one in its own line.
-
-`string_list_clear`::
-
-       Free a string_list. The `string` pointer of the items will be freed in
-       case the `strdup_strings` member of the string_list is set. The second
-       parameter controls if the `util` pointer of the items should be freed
-       or not.
-
-* Functions for sorted lists only
-
-`string_list_has_string`::
-
-       Determine if the string_list has a given string or not.
-
-`string_list_insert`::
-
-       Insert a new element to the string_list. The returned pointer can be
-       handy if you want to write something to the `util` pointer of the
-       string_list_item containing the just added string. If the given
-       string already exists the insertion will be skipped and the
-       pointer to the existing item returned.
-+
-Since this function uses xrealloc() (which die()s if it fails) if the
-list needs to grow, it is safe not to check the pointer. I.e. you may
-write `string_list_insert(...)->util = ...;`.
-
-`string_list_lookup`::
-
-       Look up a given string in the string_list, returning the containing
-       string_list_item. If the string is not found, NULL is returned.
-
-`string_list_remove_duplicates`::
-
-       Remove all but the first of consecutive entries that have the
-       same string value.  If free_util is true, call free() on the
-       util members of any items that have to be deleted.
-
-* Functions for unsorted lists only
-
-`string_list_append`::
-
-       Append a new string to the end of the string_list.  If
-       `strdup_string` is set, then the string argument is copied;
-       otherwise the new `string_list_entry` refers to the input
-       string.
-
-`string_list_append_nodup`::
-
-       Append a new string to the end of the string_list.  The new
-       `string_list_entry` always refers to the input string, even if
-       `strdup_string` is set.  This function can be used to hand
-       ownership of a malloc()ed string to a `string_list` that has
-       `strdup_string` set.
-
-`string_list_sort`::
-
-       Sort the list's entries by string value in `strcmp()` order.
-
-`unsorted_string_list_has_string`::
-
-       It's like `string_list_has_string()` but for unsorted lists.
-
-`unsorted_string_list_lookup`::
-
-       It's like `string_list_lookup()` but for unsorted lists.
-+
-The above two functions need to look through all items, as opposed to their
-counterpart for sorted lists, which performs a binary search.
-
-`unsorted_string_list_delete_item`::
-
-       Remove an item from a string_list. The `string` pointer of the items
-       will be freed in case the `strdup_strings` member of the string_list
-       is set. The third parameter controls if the `util` pointer of the
-       items should be freed or not.
-
-`string_list_split`::
-`string_list_split_in_place`::
-
-       Split a string into substrings on a delimiter character and
-       append the substrings to a `string_list`.  If `maxsplit` is
-       non-negative, then split at most `maxsplit` times.  Return the
-       number of substrings appended to the list.
-+
-`string_list_split` requires a `string_list` that has `strdup_strings`
-set to true; it leaves the input string untouched and makes copies of
-the substrings in newly-allocated memory.
-`string_list_split_in_place` requires a `string_list` that has
-`strdup_strings` set to false; it splits the input string in place,
-overwriting the delimiter characters with NULs and creating new
-string_list_items that point into the original string (the original
-string must therefore not be modified or freed while the `string_list`
-is in use).
-
-
-Data structures
----------------
-
-* `struct string_list_item`
-
-Represents an item of the list. The `string` member is a pointer to the
-string, and you may use the `util` member for any purpose, if you want.
-
-* `struct string_list`
-
-Represents the list itself.
-
-. The array of items are available via the `items` member.
-. The `nr` member contains the number of items stored in the list.
-. The `alloc` member is used to avoid reallocating at every insertion.
-  You should not tamper with it.
-. Setting the `strdup_strings` member to 1 will strdup() the strings
-  before adding them, see above.
-. The `compare_strings_fn` member is used to specify a custom compare
-  function, otherwise `strcmp()` is used as the default function.
diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt
new file mode 100644 (file)
index 0000000..417ba49
--- /dev/null
@@ -0,0 +1,797 @@
+Git hash function transition
+============================
+
+Objective
+---------
+Migrate Git from SHA-1 to a stronger hash function.
+
+Background
+----------
+At its core, the Git version control system is a content addressable
+filesystem. It uses the SHA-1 hash function to name content. For
+example, files, directories, and revisions are referred to by hash
+values unlike in other traditional version control systems where files
+or versions are referred to via sequential numbers. The use of a hash
+function to address its content delivers a few advantages:
+
+* Integrity checking is easy. Bit flips, for example, are easily
+  detected, as the hash of corrupted content does not match its name.
+* Lookup of objects is fast.
+
+Using a cryptographically secure hash function brings additional
+advantages:
+
+* Object names can be signed and third parties can trust the hash to
+  address the signed object and all objects it references.
+* Communication using Git protocol and out of band communication
+  methods have a short reliable string that can be used to reliably
+  address stored content.
+
+Over time some flaws in SHA-1 have been discovered by security
+researchers. https://shattered.io demonstrated a practical SHA-1 hash
+collision. As a result, SHA-1 cannot be considered cryptographically
+secure any more. This impacts the communication of hash values because
+we cannot trust that a given hash value represents the known good
+version of content that the speaker intended.
+
+SHA-1 still possesses the other properties such as fast object lookup
+and safe error checking, but other hash functions are equally suitable
+that are believed to be cryptographically secure.
+
+Goals
+-----
+Where NewHash is a strong 256-bit hash function to replace SHA-1 (see
+"Selection of a New Hash", below):
+
+1. The transition to NewHash can be done one local repository at a time.
+   a. Requiring no action by any other party.
+   b. A NewHash repository can communicate with SHA-1 Git servers
+      (push/fetch).
+   c. Users can use SHA-1 and NewHash identifiers for objects
+      interchangeably (see "Object names on the command line", below).
+   d. New signed objects make use of a stronger hash function than
+      SHA-1 for their security guarantees.
+2. Allow a complete transition away from SHA-1.
+   a. Local metadata for SHA-1 compatibility can be removed from a
+      repository if compatibility with SHA-1 is no longer needed.
+3. Maintainability throughout the process.
+   a. The object format is kept simple and consistent.
+   b. Creation of a generalized repository conversion tool.
+
+Non-Goals
+---------
+1. Add NewHash support to Git protocol. This is valuable and the
+   logical next step but it is out of scope for this initial design.
+2. Transparently improving the security of existing SHA-1 signed
+   objects.
+3. Intermixing objects using multiple hash functions in a single
+   repository.
+4. Taking the opportunity to fix other bugs in Git's formats and
+   protocols.
+5. Shallow clones and fetches into a NewHash repository. (This will
+   change when we add NewHash support to Git protocol.)
+6. Skip fetching some submodules of a project into a NewHash
+   repository. (This also depends on NewHash support in Git
+   protocol.)
+
+Overview
+--------
+We introduce a new repository format extension. Repositories with this
+extension enabled use NewHash instead of SHA-1 to name their objects.
+This affects both object names and object content --- both the names
+of objects and all references to other objects within an object are
+switched to the new hash function.
+
+NewHash repositories cannot be read by older versions of Git.
+
+Alongside the packfile, a NewHash repository stores a bidirectional
+mapping between NewHash and SHA-1 object names. The mapping is generated
+locally and can be verified using "git fsck". Object lookups use this
+mapping to allow naming objects using either their SHA-1 and NewHash names
+interchangeably.
+
+"git cat-file" and "git hash-object" gain options to display an object
+in its sha1 form and write an object given its sha1 form. This
+requires all objects referenced by that object to be present in the
+object database so that they can be named using the appropriate name
+(using the bidirectional hash mapping).
+
+Fetches from a SHA-1 based server convert the fetched objects into
+NewHash form and record the mapping in the bidirectional mapping table
+(see below for details). Pushes to a SHA-1 based server convert the
+objects being pushed into sha1 form so the server does not have to be
+aware of the hash function the client is using.
+
+Detailed Design
+---------------
+Repository format extension
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A NewHash repository uses repository format version `1` (see
+Documentation/technical/repository-version.txt) with extensions
+`objectFormat` and `compatObjectFormat`:
+
+       [core]
+               repositoryFormatVersion = 1
+       [extensions]
+               objectFormat = newhash
+               compatObjectFormat = sha1
+
+Specifying a repository format extension ensures that versions of Git
+not aware of NewHash do not try to operate on these repositories,
+instead producing an error message:
+
+       $ git status
+       fatal: unknown repository extensions found:
+               objectformat
+               compatobjectformat
+
+See the "Transition plan" section below for more details on these
+repository extensions.
+
+Object names
+~~~~~~~~~~~~
+Objects can be named by their 40 hexadecimal digit sha1-name or 64
+hexadecimal digit newhash-name, plus names derived from those (see
+gitrevisions(7)).
+
+The sha1-name of an object is the SHA-1 of the concatenation of its
+type, length, a nul byte, and the object's sha1-content. This is the
+traditional <sha1> used in Git to name objects.
+
+The newhash-name of an object is the NewHash of the concatenation of its
+type, length, a nul byte, and the object's newhash-content.
+
+Object format
+~~~~~~~~~~~~~
+The content as a byte sequence of a tag, commit, or tree object named
+by sha1 and newhash differ because an object named by newhash-name refers to
+other objects by their newhash-names and an object named by sha1-name
+refers to other objects by their sha1-names.
+
+The newhash-content of an object is the same as its sha1-content, except
+that objects referenced by the object are named using their newhash-names
+instead of sha1-names. Because a blob object does not refer to any
+other object, its sha1-content and newhash-content are the same.
+
+The format allows round-trip conversion between newhash-content and
+sha1-content.
+
+Object storage
+~~~~~~~~~~~~~~
+Loose objects use zlib compression and packed objects use the packed
+format described in Documentation/technical/pack-format.txt, just like
+today. The content that is compressed and stored uses newhash-content
+instead of sha1-content.
+
+Pack index
+~~~~~~~~~~
+Pack index (.idx) files use a new v3 format that supports multiple
+hash functions. They have the following format (all integers are in
+network byte order):
+
+- A header appears at the beginning and consists of the following:
+  - The 4-byte pack index signature: '\377t0c'
+  - 4-byte version number: 3
+  - 4-byte length of the header section, including the signature and
+    version number
+  - 4-byte number of objects contained in the pack
+  - 4-byte number of object formats in this pack index: 2
+  - For each object format:
+    - 4-byte format identifier (e.g., 'sha1' for SHA-1)
+    - 4-byte length in bytes of shortened object names. This is the
+      shortest possible length needed to make names in the shortened
+      object name table unambiguous.
+    - 4-byte integer, recording where tables relating to this format
+      are stored in this index file, as an offset from the beginning.
+  - 4-byte offset to the trailer from the beginning of this file.
+  - Zero or more additional key/value pairs (4-byte key, 4-byte
+    value). Only one key is supported: 'PSRC'. See the "Loose objects
+    and unreachable objects" section for supported values and how this
+    is used.  All other keys are reserved. Readers must ignore
+    unrecognized keys.
+- Zero or more NUL bytes. This can optionally be used to improve the
+  alignment of the full object name table below.
+- Tables for the first object format:
+  - A sorted table of shortened object names.  These are prefixes of
+    the names of all objects in this pack file, packed together
+    without offset values to reduce the cache footprint of the binary
+    search for a specific object name.
+
+  - A table of full object names in pack order. This allows resolving
+    a reference to "the nth object in the pack file" (from a
+    reachability bitmap or from the next table of another object
+    format) to its object name.
+
+  - A table of 4-byte values mapping object name order to pack order.
+    For an object in the table of sorted shortened object names, the
+    value at the corresponding index in this table is the index in the
+    previous table for that same object.
+
+    This can be used to look up the object in reachability bitmaps or
+    to look up its name in another object format.
+
+  - A table of 4-byte CRC32 values of the packed object data, in the
+    order that the objects appear in the pack file. This is to allow
+    compressed data to be copied directly from pack to pack during
+    repacking without undetected data corruption.
+
+  - A table of 4-byte offset values. For an object in the table of
+    sorted shortened object names, the value at the corresponding
+    index in this table indicates where that object can be found in
+    the pack file. These are usually 31-bit pack file offsets, but
+    large offsets are encoded as an index into the next table with the
+    most significant bit set.
+
+  - A table of 8-byte offset entries (empty for pack files less than
+    2 GiB). Pack files are organized with heavily used objects toward
+    the front, so most object references should not need to refer to
+    this table.
+- Zero or more NUL bytes.
+- Tables for the second object format, with the same layout as above,
+  up to and not including the table of CRC32 values.
+- Zero or more NUL bytes.
+- The trailer consists of the following:
+  - A copy of the 20-byte NewHash checksum at the end of the
+    corresponding packfile.
+
+  - 20-byte NewHash checksum of all of the above.
+
+Loose object index
+~~~~~~~~~~~~~~~~~~
+A new file $GIT_OBJECT_DIR/loose-object-idx contains information about
+all loose objects. Its format is
+
+  # loose-object-idx
+  (newhash-name SP sha1-name LF)*
+
+where the object names are in hexadecimal format. The file is not
+sorted.
+
+The loose object index is protected against concurrent writes by a
+lock file $GIT_OBJECT_DIR/loose-object-idx.lock. To add a new loose
+object:
+
+1. Write the loose object to a temporary file, like today.
+2. Open loose-object-idx.lock with O_CREAT | O_EXCL to acquire the lock.
+3. Rename the loose object into place.
+4. Open loose-object-idx with O_APPEND and write the new object
+5. Unlink loose-object-idx.lock to release the lock.
+
+To remove entries (e.g. in "git pack-refs" or "git-prune"):
+
+1. Open loose-object-idx.lock with O_CREAT | O_EXCL to acquire the
+   lock.
+2. Write the new content to loose-object-idx.lock.
+3. Unlink any loose objects being removed.
+4. Rename to replace loose-object-idx, releasing the lock.
+
+Translation table
+~~~~~~~~~~~~~~~~~
+The index files support a bidirectional mapping between sha1-names
+and newhash-names. The lookup proceeds similarly to ordinary object
+lookups. For example, to convert a sha1-name to a newhash-name:
+
+ 1. Look for the object in idx files. If a match is present in the
+    idx's sorted list of truncated sha1-names, then:
+    a. Read the corresponding entry in the sha1-name order to pack
+       name order mapping.
+    b. Read the corresponding entry in the full sha1-name table to
+       verify we found the right object. If it is, then
+    c. Read the corresponding entry in the full newhash-name table.
+       That is the object's newhash-name.
+ 2. Check for a loose object. Read lines from loose-object-idx until
+    we find a match.
+
+Step (1) takes the same amount of time as an ordinary object lookup:
+O(number of packs * log(objects per pack)). Step (2) takes O(number of
+loose objects) time. To maintain good performance it will be necessary
+to keep the number of loose objects low. See the "Loose objects and
+unreachable objects" section below for more details.
+
+Since all operations that make new objects (e.g., "git commit") add
+the new objects to the corresponding index, this mapping is possible
+for all objects in the object store.
+
+Reading an object's sha1-content
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The sha1-content of an object can be read by converting all newhash-names
+its newhash-content references to sha1-names using the translation table.
+
+Fetch
+~~~~~
+Fetching from a SHA-1 based server requires translating between SHA-1
+and NewHash based representations on the fly.
+
+SHA-1s named in the ref advertisement that are present on the client
+can be translated to NewHash and looked up as local objects using the
+translation table.
+
+Negotiation proceeds as today. Any "have"s generated locally are
+converted to SHA-1 before being sent to the server, and SHA-1s
+mentioned by the server are converted to NewHash when looking them up
+locally.
+
+After negotiation, the server sends a packfile containing the
+requested objects. We convert the packfile to NewHash format using
+the following steps:
+
+1. index-pack: inflate each object in the packfile and compute its
+   SHA-1. Objects can contain deltas in OBJ_REF_DELTA format against
+   objects the client has locally. These objects can be looked up
+   using the translation table and their sha1-content read as
+   described above to resolve the deltas.
+2. topological sort: starting at the "want"s from the negotiation
+   phase, walk through objects in the pack and emit a list of them,
+   excluding blobs, in reverse topologically sorted order, with each
+   object coming later in the list than all objects it references.
+   (This list only contains objects reachable from the "wants". If the
+   pack from the server contained additional extraneous objects, then
+   they will be discarded.)
+3. convert to newhash: open a new (newhash) packfile. Read the topologically
+   sorted list just generated. For each object, inflate its
+   sha1-content, convert to newhash-content, and write it to the newhash
+   pack. Record the new sha1<->newhash mapping entry for use in the idx.
+4. sort: reorder entries in the new pack to match the order of objects
+   in the pack the server generated and include blobs. Write a newhash idx
+   file
+5. clean up: remove the SHA-1 based pack file, index, and
+   topologically sorted list obtained from the server in steps 1
+   and 2.
+
+Step 3 requires every object referenced by the new object to be in the
+translation table. This is why the topological sort step is necessary.
+
+As an optimization, step 1 could write a file describing what non-blob
+objects each object it has inflated from the packfile references. This
+makes the topological sort in step 2 possible without inflating the
+objects in the packfile for a second time. The objects need to be
+inflated again in step 3, for a total of two inflations.
+
+Step 4 is probably necessary for good read-time performance. "git
+pack-objects" on the server optimizes the pack file for good data
+locality (see Documentation/technical/pack-heuristics.txt).
+
+Details of this process are likely to change. It will take some
+experimenting to get this to perform well.
+
+Push
+~~~~
+Push is simpler than fetch because the objects referenced by the
+pushed objects are already in the translation table. The sha1-content
+of each object being pushed can be read as described in the "Reading
+an object's sha1-content" section to generate the pack written by git
+send-pack.
+
+Signed Commits
+~~~~~~~~~~~~~~
+We add a new field "gpgsig-newhash" to the commit object format to allow
+signing commits without relying on SHA-1. It is similar to the
+existing "gpgsig" field. Its signed payload is the newhash-content of the
+commit object with any "gpgsig" and "gpgsig-newhash" fields removed.
+
+This means commits can be signed
+1. using SHA-1 only, as in existing signed commit objects
+2. using both SHA-1 and NewHash, by using both gpgsig-newhash and gpgsig
+   fields.
+3. using only NewHash, by only using the gpgsig-newhash field.
+
+Old versions of "git verify-commit" can verify the gpgsig signature in
+cases (1) and (2) without modifications and view case (3) as an
+ordinary unsigned commit.
+
+Signed Tags
+~~~~~~~~~~~
+We add a new field "gpgsig-newhash" to the tag object format to allow
+signing tags without relying on SHA-1. Its signed payload is the
+newhash-content of the tag with its gpgsig-newhash field and "-----BEGIN PGP
+SIGNATURE-----" delimited in-body signature removed.
+
+This means tags can be signed
+1. using SHA-1 only, as in existing signed tag objects
+2. using both SHA-1 and NewHash, by using gpgsig-newhash and an in-body
+   signature.
+3. using only NewHash, by only using the gpgsig-newhash field.
+
+Mergetag embedding
+~~~~~~~~~~~~~~~~~~
+The mergetag field in the sha1-content of a commit contains the
+sha1-content of a tag that was merged by that commit.
+
+The mergetag field in the newhash-content of the same commit contains the
+newhash-content of the same tag.
+
+Submodules
+~~~~~~~~~~
+To convert recorded submodule pointers, you need to have the converted
+submodule repository in place. The translation table of the submodule
+can be used to look up the new hash.
+
+Loose objects and unreachable objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Fast lookups in the loose-object-idx require that the number of loose
+objects not grow too high.
+
+"git gc --auto" currently waits for there to be 6700 loose objects
+present before consolidating them into a packfile. We will need to
+measure to find a more appropriate threshold for it to use.
+
+"git gc --auto" currently waits for there to be 50 packs present
+before combining packfiles. Packing loose objects more aggressively
+may cause the number of pack files to grow too quickly. This can be
+mitigated by using a strategy similar to Martin Fick's exponential
+rolling garbage collection script:
+https://gerrit-review.googlesource.com/c/gerrit/+/35215
+
+"git gc" currently expels any unreachable objects it encounters in
+pack files to loose objects in an attempt to prevent a race when
+pruning them (in case another process is simultaneously writing a new
+object that refers to the about-to-be-deleted object). This leads to
+an explosion in the number of loose objects present and disk space
+usage due to the objects in delta form being replaced with independent
+loose objects.  Worse, the race is still present for loose objects.
+
+Instead, "git gc" will need to move unreachable objects to a new
+packfile marked as UNREACHABLE_GARBAGE (using the PSRC field; see
+below). To avoid the race when writing new objects referring to an
+about-to-be-deleted object, code paths that write new objects will
+need to copy any objects from UNREACHABLE_GARBAGE packs that they
+refer to to new, non-UNREACHABLE_GARBAGE packs (or loose objects).
+UNREACHABLE_GARBAGE are then safe to delete if their creation time (as
+indicated by the file's mtime) is long enough ago.
+
+To avoid a proliferation of UNREACHABLE_GARBAGE packs, they can be
+combined under certain circumstances. If "gc.garbageTtl" is set to
+greater than one day, then packs created within a single calendar day,
+UTC, can be coalesced together. The resulting packfile would have an
+mtime before midnight on that day, so this makes the effective maximum
+ttl the garbageTtl + 1 day. If "gc.garbageTtl" is less than one day,
+then we divide the calendar day into intervals one-third of that ttl
+in duration. Packs created within the same interval can be coalesced
+together. The resulting packfile would have an mtime before the end of
+the interval, so this makes the effective maximum ttl equal to the
+garbageTtl * 4/3.
+
+This rule comes from Thirumala Reddy Mutchukota's JGit change
+https://git.eclipse.org/r/90465.
+
+The UNREACHABLE_GARBAGE setting goes in the PSRC field of the pack
+index. More generally, that field indicates where a pack came from:
+
+ - 1 (PACK_SOURCE_RECEIVE) for a pack received over the network
+ - 2 (PACK_SOURCE_AUTO) for a pack created by a lightweight
+   "gc --auto" operation
+ - 3 (PACK_SOURCE_GC) for a pack created by a full gc
+ - 4 (PACK_SOURCE_UNREACHABLE_GARBAGE) for potential garbage
+   discovered by gc
+ - 5 (PACK_SOURCE_INSERT) for locally created objects that were
+   written directly to a pack file, e.g. from "git add ."
+
+This information can be useful for debugging and for "gc --auto" to
+make appropriate choices about which packs to coalesce.
+
+Caveats
+-------
+Invalid objects
+~~~~~~~~~~~~~~~
+The conversion from sha1-content to newhash-content retains any
+brokenness in the original object (e.g., tree entry modes encoded with
+leading 0, tree objects whose paths are not sorted correctly, and
+commit objects without an author or committer). This is a deliberate
+feature of the design to allow the conversion to round-trip.
+
+More profoundly broken objects (e.g., a commit with a truncated "tree"
+header line) cannot be converted but were not usable by current Git
+anyway.
+
+Shallow clone and submodules
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Because it requires all referenced objects to be available in the
+locally generated translation table, this design does not support
+shallow clone or unfetched submodules. Protocol improvements might
+allow lifting this restriction.
+
+Alternates
+~~~~~~~~~~
+For the same reason, a newhash repository cannot borrow objects from a
+sha1 repository using objects/info/alternates or
+$GIT_ALTERNATE_OBJECT_REPOSITORIES.
+
+git notes
+~~~~~~~~~
+The "git notes" tool annotates objects using their sha1-name as key.
+This design does not describe a way to migrate notes trees to use
+newhash-names. That migration is expected to happen separately (for
+example using a file at the root of the notes tree to describe which
+hash it uses).
+
+Server-side cost
+~~~~~~~~~~~~~~~~
+Until Git protocol gains NewHash support, using NewHash based storage
+on public-facing Git servers is strongly discouraged. Once Git
+protocol gains NewHash support, NewHash based servers are likely not
+to support SHA-1 compatibility, to avoid what may be a very expensive
+hash reencode during clone and to encourage peers to modernize.
+
+The design described here allows fetches by SHA-1 clients of a
+personal NewHash repository because it's not much more difficult than
+allowing pushes from that repository. This support needs to be guarded
+by a configuration option --- servers like git.kernel.org that serve a
+large number of clients would not be expected to bear that cost.
+
+Meaning of signatures
+~~~~~~~~~~~~~~~~~~~~~
+The signed payload for signed commits and tags does not explicitly
+name the hash used to identify objects. If some day Git adopts a new
+hash function with the same length as the current SHA-1 (40
+hexadecimal digit) or NewHash (64 hexadecimal digit) objects then the
+intent behind the PGP signed payload in an object signature is
+unclear:
+
+       object e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7
+       type commit
+       tag v2.12.0
+       tagger Junio C Hamano <gitster@pobox.com> 1487962205 -0800
+
+       Git 2.12
+
+Does this mean Git v2.12.0 is the commit with sha1-name
+e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7 or the commit with
+new-40-digit-hash-name e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7?
+
+Fortunately NewHash and SHA-1 have different lengths. If Git starts
+using another hash with the same length to name objects, then it will
+need to change the format of signed payloads using that hash to
+address this issue.
+
+Object names on the command line
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+To support the transition (see Transition plan below), this design
+supports four different modes of operation:
+
+ 1. ("dark launch") Treat object names input by the user as SHA-1 and
+    convert any object names written to output to SHA-1, but store
+    objects using NewHash.  This allows users to test the code with no
+    visible behavior change except for performance.  This allows
+    allows running even tests that assume the SHA-1 hash function, to
+    sanity-check the behavior of the new mode.
+
+ 2. ("early transition") Allow both SHA-1 and NewHash object names in
+    input. Any object names written to output use SHA-1. This allows
+    users to continue to make use of SHA-1 to communicate with peers
+    (e.g. by email) that have not migrated yet and prepares for mode 3.
+
+ 3. ("late transition") Allow both SHA-1 and NewHash object names in
+    input. Any object names written to output use NewHash. In this
+    mode, users are using a more secure object naming method by
+    default.  The disruption is minimal as long as most of their peers
+    are in mode 2 or mode 3.
+
+ 4. ("post-transition") Treat object names input by the user as
+    NewHash and write output using NewHash. This is safer than mode 3
+    because there is less risk that input is incorrectly interpreted
+    using the wrong hash function.
+
+The mode is specified in configuration.
+
+The user can also explicitly specify which format to use for a
+particular revision specifier and for output, overriding the mode. For
+example:
+
+git --output-format=sha1 log abac87a^{sha1}..f787cac^{newhash}
+
+Selection of a New Hash
+-----------------------
+In early 2005, around the time that Git was written,  Xiaoyun Wang,
+Yiqun Lisa Yin, and Hongbo Yu announced an attack finding SHA-1
+collisions in 2^69 operations. In August they published details.
+Luckily, no practical demonstrations of a collision in full SHA-1 were
+published until 10 years later, in 2017.
+
+The hash function NewHash to replace SHA-1 should be stronger than
+SHA-1 was: we would like it to be trustworthy and useful in practice
+for at least 10 years.
+
+Some other relevant properties:
+
+1. A 256-bit hash (long enough to match common security practice; not
+   excessively long to hurt performance and disk usage).
+
+2. High quality implementations should be widely available (e.g. in
+   OpenSSL).
+
+3. The hash function's properties should match Git's needs (e.g. Git
+   requires collision and 2nd preimage resistance and does not require
+   length extension resistance).
+
+4. As a tiebreaker, the hash should be fast to compute (fortunately
+   many contenders are faster than SHA-1).
+
+Some hashes under consideration are SHA-256, SHA-512/256, SHA-256x16,
+K12, and BLAKE2bp-256.
+
+Transition plan
+---------------
+Some initial steps can be implemented independently of one another:
+- adding a hash function API (vtable)
+- teaching fsck to tolerate the gpgsig-newhash field
+- excluding gpgsig-* from the fields copied by "git commit --amend"
+- annotating tests that depend on SHA-1 values with a SHA1 test
+  prerequisite
+- using "struct object_id", GIT_MAX_RAWSZ, and GIT_MAX_HEXSZ
+  consistently instead of "unsigned char *" and the hardcoded
+  constants 20 and 40.
+- introducing index v3
+- adding support for the PSRC field and safer object pruning
+
+
+The first user-visible change is the introduction of the objectFormat
+extension (without compatObjectFormat). This requires:
+- implementing the loose-object-idx
+- teaching fsck about this mode of operation
+- using the hash function API (vtable) when computing object names
+- signing objects and verifying signatures
+- rejecting attempts to fetch from or push to an incompatible
+  repository
+
+Next comes introduction of compatObjectFormat:
+- translating object names between object formats
+- translating object content between object formats
+- generating and verifying signatures in the compat format
+- adding appropriate index entries when adding a new object to the
+  object store
+- --output-format option
+- ^{sha1} and ^{newhash} revision notation
+- configuration to specify default input and output format (see
+  "Object names on the command line" above)
+
+The next step is supporting fetches and pushes to SHA-1 repositories:
+- allow pushes to a repository using the compat format
+- generate a topologically sorted list of the SHA-1 names of fetched
+  objects
+- convert the fetched packfile to newhash format and generate an idx
+  file
+- re-sort to match the order of objects in the fetched packfile
+
+The infrastructure supporting fetch also allows converting an existing
+repository. In converted repositories and new clones, end users can
+gain support for the new hash function without any visible change in
+behavior (see "dark launch" in the "Object names on the command line"
+section). In particular this allows users to verify NewHash signatures
+on objects in the repository, and it should ensure the transition code
+is stable in production in preparation for using it more widely.
+
+Over time projects would encourage their users to adopt the "early
+transition" and then "late transition" modes to take advantage of the
+new, more futureproof NewHash object names.
+
+When objectFormat and compatObjectFormat are both set, commands
+generating signatures would generate both SHA-1 and NewHash signatures
+by default to support both new and old users.
+
+In projects using NewHash heavily, users could be encouraged to adopt
+the "post-transition" mode to avoid accidentally making implicit use
+of SHA-1 object names.
+
+Once a critical mass of users have upgraded to a version of Git that
+can verify NewHash signatures and have converted their existing
+repositories to support verifying them, we can add support for a
+setting to generate only NewHash signatures. This is expected to be at
+least a year later.
+
+That is also a good moment to advertise the ability to convert
+repositories to use NewHash only, stripping out all SHA-1 related
+metadata. This improves performance by eliminating translation
+overhead and security by avoiding the possibility of accidentally
+relying on the safety of SHA-1.
+
+Updating Git's protocols to allow a server to specify which hash
+functions it supports is also an important part of this transition. It
+is not discussed in detail in this document but this transition plan
+assumes it happens. :)
+
+Alternatives considered
+-----------------------
+Upgrading everyone working on a particular project on a flag day
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Projects like the Linux kernel are large and complex enough that
+flipping the switch for all projects based on the repository at once
+is infeasible.
+
+Not only would all developers and server operators supporting
+developers have to switch on the same flag day, but supporting tooling
+(continuous integration, code review, bug trackers, etc) would have to
+be adapted as well. This also makes it difficult to get early feedback
+from some project participants testing before it is time for mass
+adoption.
+
+Using hash functions in parallel
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(e.g. https://public-inbox.org/git/22708.8913.864049.452252@chiark.greenend.org.uk/ )
+Objects newly created would be addressed by the new hash, but inside
+such an object (e.g. commit) it is still possible to address objects
+using the old hash function.
+* You cannot trust its history (needed for bisectability) in the
+  future without further work
+* Maintenance burden as the number of supported hash functions grows
+  (they will never go away, so they accumulate). In this proposal, by
+  comparison, converted objects lose all references to SHA-1.
+
+Signed objects with multiple hashes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Instead of introducing the gpgsig-newhash field in commit and tag objects
+for newhash-content based signatures, an earlier version of this design
+added "hash newhash <newhash-name>" fields to strengthen the existing
+sha1-content based signatures.
+
+In other words, a single signature was used to attest to the object
+content using both hash functions. This had some advantages:
+* Using one signature instead of two speeds up the signing process.
+* Having one signed payload with both hashes allows the signer to
+  attest to the sha1-name and newhash-name referring to the same object.
+* All users consume the same signature. Broken signatures are likely
+  to be detected quickly using current versions of git.
+
+However, it also came with disadvantages:
+* Verifying a signed object requires access to the sha1-names of all
+  objects it references, even after the transition is complete and
+  translation table is no longer needed for anything else. To support
+  this, the design added fields such as "hash sha1 tree <sha1-name>"
+  and "hash sha1 parent <sha1-name>" to the newhash-content of a signed
+  commit, complicating the conversion process.
+* Allowing signed objects without a sha1 (for after the transition is
+  complete) complicated the design further, requiring a "nohash sha1"
+  field to suppress including "hash sha1" fields in the newhash-content
+  and signed payload.
+
+Lazily populated translation table
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some of the work of building the translation table could be deferred to
+push time, but that would significantly complicate and slow down pushes.
+Calculating the sha1-name at object creation time at the same time it is
+being streamed to disk and having its newhash-name calculated should be
+an acceptable cost.
+
+Document History
+----------------
+
+2017-03-03
+bmwill@google.com, jonathantanmy@google.com, jrnieder@gmail.com,
+sbeller@google.com
+
+Initial version sent to
+http://public-inbox.org/git/20170304011251.GA26789@aiede.mtv.corp.google.com
+
+2017-03-03 jrnieder@gmail.com
+Incorporated suggestions from jonathantanmy and sbeller:
+* describe purpose of signed objects with each hash type
+* redefine signed object verification using object content under the
+  first hash function
+
+2017-03-06 jrnieder@gmail.com
+* Use SHA3-256 instead of SHA2 (thanks, Linus and brian m. carlson).[1][2]
+* Make sha3-based signatures a separate field, avoiding the need for
+  "hash" and "nohash" fields (thanks to peff[3]).
+* Add a sorting phase to fetch (thanks to Junio for noticing the need
+  for this).
+* Omit blobs from the topological sort during fetch (thanks to peff).
+* Discuss alternates, git notes, and git servers in the caveats
+  section (thanks to Junio Hamano, brian m. carlson[4], and Shawn
+  Pearce).
+* Clarify language throughout (thanks to various commenters,
+  especially Junio).
+
+2017-09-27 jrnieder@gmail.com, sbeller@google.com
+* use placeholder NewHash instead of SHA3-256
+* describe criteria for picking a hash function.
+* include a transition plan (thanks especially to Brandon Williams
+  for fleshing these ideas out)
+* define the translation table (thanks, Shawn Pearce[5], Jonathan
+  Tan, and Masaya Suzuki)
+* avoid loose object overhead by packing more aggressively in
+  "git gc --auto"
+
+[1] http://public-inbox.org/git/CA+55aFzJtejiCjV0e43+9oR3QuJK2PiFiLQemytoLpyJWe6P9w@mail.gmail.com/
+[2] http://public-inbox.org/git/CA+55aFz+gkAsDZ24zmePQuEs1XPS9BP_s8O7Q4wQ7LV7X5-oDA@mail.gmail.com/
+[3] http://public-inbox.org/git/20170306084353.nrns455dvkdsfgo5@sigill.intra.peff.net/
+[4] http://public-inbox.org/git/20170304224936.rqqtkdvfjgyezsht@genre.crustytoothpaste.net
+[5] https://public-inbox.org/git/CAJo=hJtoX9=AyLHHpUJS7fueV9ciZ_MNpnEPHUz8Whui6g9F0A@mail.gmail.com/
index a349171..ed1eae8 100644 (file)
@@ -199,7 +199,7 @@ After reference and capabilities discovery, the client can decide to
 terminate the connection by sending a flush-pkt, telling the server it can
 now gracefully terminate, and disconnect, when it does not need any pack
 data. This can happen with the ls-remote command, and also can happen when
-the client already is up-to-date.
+the client already is up to date.
 
 Otherwise, it enters the negotiation phase, where the client and
 server determine what the minimal packfile necessary for transport is,
index c79d4a7..1f1c33d 100644 (file)
@@ -32,7 +32,7 @@ or the result.
 If multiple cases apply, the one used is listed first.
 
 A result which changes the index is an error if the index is not empty
-and not up-to-date.
+and not up to date.
 
 Entries marked '+' have stat information. Spaces marked '*' don't
 affect the result.
@@ -65,7 +65,7 @@ empty, no entry is left for that stage). Otherwise, the given entry is
 left in stage 0, and there are no other entries.
 
 A result of "no merge" is an error if the index is not empty and not
-up-to-date.
+up to date.
 
 *empty* means that the tree must not have a directory-file conflict
  with the entry.
index bc29298..b4d88af 100644 (file)
@@ -2044,10 +2044,12 @@ If a push would not result in a <<fast-forwards,fast-forward>> of the
 remote branch, then it will fail with an error like:
 
 -------------------------------------------------
-error: remote 'refs/heads/master' is not an ancestor of
- local  'refs/heads/master'.
- Maybe you are not up-to-date and need to pull first?
-error: failed to push to 'ssh://yourserver.com/~you/proj.git'
+ ! [rejected]        master -> master (non-fast-forward)
+error: failed to push some refs to '...'
+hint: Updates were rejected because the tip of your current branch is behind
+hint: its remote counterpart. Integrate the remote changes (e.g.
+hint: 'git pull ...') before pushing again.
+hint: See the 'Note about fast-forwards' in 'git push --help' for details.
 -------------------------------------------------
 
 This can happen, for example, if you:
@@ -2193,7 +2195,7 @@ $ cd work
 Linus's tree will be stored in the remote-tracking branch named origin/master,
 and can be updated using linkgit:git-fetch[1]; you can track other
 public trees using linkgit:git-remote[1] to set up a "remote" and
-linkgit:git-fetch[1] to keep them up-to-date; see
+linkgit:git-fetch[1] to keep them up to date; see
 <<repositories-and-branches>>.
 
 Now create the branches in which you are going to work; these start out
index 75beb2e..9ef24f2 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.14.GIT
+DEF_VER=v2.15.0-rc2
 
 LF='
 '
index f2bb7f2..cd75985 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -162,6 +162,11 @@ all::
 # algorithm. This is slower, but may detect attempted collision attacks.
 # Takes priority over other *_SHA1 knobs.
 #
+# Define DC_SHA1_EXTERNAL in addition to DC_SHA1 if you want to build / link
+# git with the external SHA1 collision-detect library.
+# Without this option, i.e. the default behavior is to build git with its
+# own built-in code (or submodule).
+#
 # Define DC_SHA1_SUBMODULE in addition to DC_SHA1 to use the
 # sha1collisiondetection shipped as a submodule instead of the
 # non-submodule copy in sha1dc/. This is an experimental option used
@@ -200,6 +205,9 @@ all::
 #
 # Define NO_MMAP if you want to avoid mmap.
 #
+# Define MMAP_PREVENTS_DELETE if a file that is currently mmapped cannot be
+# deleted or cannot be replaced using rename().
+#
 # Define NO_SYS_POLL_H if you don't have sys/poll.h.
 #
 # Define NO_POLL if you do not have or don't want to use poll().
@@ -816,6 +824,7 @@ LIB_OBJS += notes-cache.o
 LIB_OBJS += notes-merge.o
 LIB_OBJS += notes-utils.o
 LIB_OBJS += object.o
+LIB_OBJS += oidmap.o
 LIB_OBJS += oidset.o
 LIB_OBJS += packfile.o
 LIB_OBJS += pack-bitmap.o
@@ -1036,6 +1045,9 @@ BASIC_CFLAGS += -fno-omit-frame-pointer
 ifneq ($(filter undefined,$(SANITIZERS)),)
 BASIC_CFLAGS += -DNO_UNALIGNED_LOADS
 endif
+ifneq ($(filter leak,$(SANITIZERS)),)
+BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
+endif
 endif
 
 ifndef sysconfdir
@@ -1383,6 +1395,9 @@ else
                COMPAT_OBJS += compat/win32mmap.o
        endif
 endif
+ifdef MMAP_PREVENTS_DELETE
+       BASIC_CFLAGS += -DMMAP_PREVENTS_DELETE
+endif
 ifdef OBJECT_CREATION_USES_RENAMES
        COMPAT_CFLAGS += -DOBJECT_CREATION_MODE=1
 endif
@@ -1475,6 +1490,15 @@ ifdef APPLE_COMMON_CRYPTO
        BASIC_CFLAGS += -DSHA1_APPLE
 else
        DC_SHA1 := YesPlease
+       BASIC_CFLAGS += -DSHA1_DC
+       LIB_OBJS += sha1dc_git.o
+ifdef DC_SHA1_EXTERNAL
+       ifdef DC_SHA1_SUBMODULE
+$(error Only set DC_SHA1_EXTERNAL or DC_SHA1_SUBMODULE, not both)
+       endif
+       BASIC_CFLAGS += -DDC_SHA1_EXTERNAL
+       EXTLIBS += -lsha1detectcoll
+else
 ifdef DC_SHA1_SUBMODULE
        LIB_OBJS += sha1collisiondetection/lib/sha1.o
        LIB_OBJS += sha1collisiondetection/lib/ubc_check.o
@@ -1484,17 +1508,15 @@ else
        LIB_OBJS += sha1dc/ubc_check.o
 endif
        BASIC_CFLAGS += \
-               -DSHA1_DC \
                -DSHA1DC_NO_STANDARD_INCLUDES \
                -DSHA1DC_INIT_SAFE_HASH_DEFAULT=0 \
                -DSHA1DC_CUSTOM_INCLUDE_SHA1_C="\"cache.h\"" \
-               -DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C="\"sha1dc_git.c\"" \
-               -DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H="\"sha1dc_git.h\"" \
                -DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="\"git-compat-util.h\""
 endif
 endif
 endif
 endif
+endif
 
 ifdef SHA1_MAX_BLOCK_SIZE
        LIB_OBJS += compat/sha1-chunked.o
@@ -2442,6 +2464,10 @@ $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
 .PHONY: sparse $(SP_OBJ)
 sparse: $(SP_OBJ)
 
+.PHONY: style
+style:
+       git clang-format --style file --diff --extensions c,h
+
 check: common-cmds.h
        @if sparse; \
        then \
index 708aff8..9857985 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -202,6 +202,10 @@ error_out:
        return retval;
 }
 
+/*
+ * Resolve `path` into an absolute, cleaned-up path. The return value
+ * comes from a shared buffer.
+ */
 const char *real_path(const char *path)
 {
        static struct strbuf realpath = STRBUF_INIT;
diff --git a/apply.c b/apply.c
index 8666621..c022af5 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -812,16 +812,13 @@ static int has_epoch_timestamp(const char *nameline)
         * 1970-01-01, and the seconds part must be "00".
         */
        const char stamp_regexp[] =
-               "^(1969-12-31|1970-01-01)"
-               " "
-               "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
+               "^[0-2][0-9]:([0-5][0-9]):00(\\.0+)?"
                " "
                "([-+][0-2][0-9]:?[0-5][0-9])\n";
        const char *timestamp = NULL, *cp, *colon;
        static regex_t *stamp;
        regmatch_t m[10];
-       int zoneoffset;
-       int hourminute;
+       int zoneoffset, epoch_hour, hour, minute;
        int status;
 
        for (cp = nameline; *cp != '\n'; cp++) {
@@ -830,6 +827,18 @@ static int has_epoch_timestamp(const char *nameline)
        }
        if (!timestamp)
                return 0;
+
+       /*
+        * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
+        * (west of GMT) or 1970-01-01 (east of GMT)
+        */
+       if (skip_prefix(timestamp, "1969-12-31 ", &timestamp))
+               epoch_hour = 24;
+       else if (skip_prefix(timestamp, "1970-01-01 ", &timestamp))
+               epoch_hour = 0;
+       else
+               return 0;
+
        if (!stamp) {
                stamp = xmalloc(sizeof(*stamp));
                if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) {
@@ -847,6 +856,9 @@ static int has_epoch_timestamp(const char *nameline)
                return 0;
        }
 
+       hour = strtol(timestamp, NULL, 10);
+       minute = strtol(timestamp + m[1].rm_so, NULL, 10);
+
        zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10);
        if (*colon == ':')
                zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10);
@@ -855,20 +867,7 @@ static int has_epoch_timestamp(const char *nameline)
        if (timestamp[m[3].rm_so] == '-')
                zoneoffset = -zoneoffset;
 
-       /*
-        * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
-        * (west of GMT) or 1970-01-01 (east of GMT)
-        */
-       if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) ||
-           (0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10)))
-               return 0;
-
-       hourminute = (strtol(timestamp + 11, NULL, 10) * 60 +
-                     strtol(timestamp + 14, NULL, 10) -
-                     zoneoffset);
-
-       return ((zoneoffset < 0 && hourminute == 1440) ||
-               (0 <= zoneoffset && !hourminute));
+       return hour * 60 + minute - zoneoffset == epoch_hour * 60;
 }
 
 /*
@@ -2921,6 +2920,7 @@ static int apply_one_fragment(struct apply_state *state,
                        if (plen && (ws_rule & WS_BLANK_AT_EOF) &&
                            ws_blank_line(patch + 1, plen, ws_rule))
                                is_blank_context = 1;
+                       /* fallthrough */
                case '-':
                        memcpy(old, patch + 1, plen);
                        add_line_info(&preimage, old, plen,
@@ -2928,7 +2928,7 @@ static int apply_one_fragment(struct apply_state *state,
                        old += plen;
                        if (first == '-')
                                break;
-               /* Fall-through for ' ' */
+                       /* fallthrough */
                case '+':
                        /* --no-add does not add new lines */
                        if (first == '+' && state->no_add)
index 557dd2d..1e41f4b 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -103,17 +103,34 @@ struct archiver_context {
        struct directory *bottom;
 };
 
+static const struct attr_check *get_archive_attrs(const char *path)
+{
+       static struct attr_check *check;
+       if (!check)
+               check = attr_check_initl("export-ignore", "export-subst", NULL);
+       return git_check_attr(path, check) ? NULL : check;
+}
+
+static int check_attr_export_ignore(const struct attr_check *check)
+{
+       return check && ATTR_TRUE(check->items[0].value);
+}
+
+static int check_attr_export_subst(const struct attr_check *check)
+{
+       return check && ATTR_TRUE(check->items[1].value);
+}
+
 static int write_archive_entry(const unsigned char *sha1, const char *base,
                int baselen, const char *filename, unsigned mode, int stage,
                void *context)
 {
        static struct strbuf path = STRBUF_INIT;
-       static struct attr_check *check;
        struct archiver_context *c = context;
        struct archiver_args *args = c->args;
        write_archive_entry_fn_t write_entry = c->write_entry;
-       const char *path_without_prefix;
        int err;
+       const char *path_without_prefix;
 
        args->convert = 0;
        strbuf_reset(&path);
@@ -125,12 +142,12 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
                strbuf_addch(&path, '/');
        path_without_prefix = path.buf + args->baselen;
 
-       if (!check)
-               check = attr_check_initl("export-ignore", "export-subst", NULL);
-       if (!git_check_attr(path_without_prefix, check)) {
-               if (ATTR_TRUE(check->items[0].value))
+       if (!S_ISDIR(mode)) {
+               const struct attr_check *check;
+               check = get_archive_attrs(path_without_prefix);
+               if (check_attr_export_ignore(check))
                        return 0;
-               args->convert = ATTR_TRUE(check->items[1].value);
+               args->convert = check_attr_export_subst(check);
        }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
@@ -147,14 +164,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        return write_entry(args, sha1, path.buf, path.len, mode);
 }
 
-static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base,
-               const char *filename, unsigned mode, int stage,
-               void *context)
-{
-       return write_archive_entry(sha1, base->buf, base->len,
-                                    filename, mode, stage, context);
-}
-
 static void queue_directory(const unsigned char *sha1,
                struct strbuf *base, const char *filename,
                unsigned mode, int stage, struct archiver_context *c)
@@ -204,6 +213,17 @@ static int queue_or_write_archive_entry(const unsigned char *sha1,
        }
 
        if (S_ISDIR(mode)) {
+               size_t baselen = base->len;
+               const struct attr_check *check;
+
+               /* Borrow base, but restore its original value when done. */
+               strbuf_addstr(base, filename);
+               strbuf_addch(base, '/');
+               check = get_archive_attrs(base->buf);
+               strbuf_setlen(base, baselen);
+
+               if (check_attr_export_ignore(check))
+                       return 0;
                queue_directory(sha1, base, filename,
                                mode, stage, c);
                return READ_TREE_RECURSIVE;
@@ -257,9 +277,7 @@ int write_archive_entries(struct archiver_args *args,
        }
 
        err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
-                                 args->pathspec.has_wildcard ?
-                                 queue_or_write_archive_entry :
-                                 write_archive_entry_buf,
+                                 queue_or_write_archive_entry,
                                  &context);
        if (err == READ_TREE_RECURSIVE)
                err = 0;
diff --git a/attr.c b/attr.c
index 2f49151..dfc3a55 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -151,10 +151,12 @@ struct all_attrs_item {
 static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
 {
        int i;
+       unsigned int size;
 
        hashmap_lock(map);
 
-       if (map->map.size < check->all_attrs_nr)
+       size = hashmap_get_size(&map->map);
+       if (size < check->all_attrs_nr)
                die("BUG: interned attributes shouldn't be deleted");
 
        /*
@@ -163,13 +165,13 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
         * field), reallocate the provided attr_check instance's all_attrs
         * field and fill each entry with its corresponding git_attr.
         */
-       if (map->map.size != check->all_attrs_nr) {
+       if (size != check->all_attrs_nr) {
                struct attr_hash_entry *e;
                struct hashmap_iter iter;
                hashmap_iter_init(&map->map, &iter);
 
-               REALLOC_ARRAY(check->all_attrs, map->map.size);
-               check->all_attrs_nr = map->map.size;
+               REALLOC_ARRAY(check->all_attrs, size);
+               check->all_attrs_nr = size;
 
                while ((e = hashmap_iter_next(&iter))) {
                        const struct git_attr *a = e->value;
@@ -237,10 +239,11 @@ static const struct git_attr *git_attr_internal(const char *name, int namelen)
 
        if (!a) {
                FLEX_ALLOC_MEM(a, name, name, namelen);
-               a->attr_nr = g_attr_hashmap.map.size;
+               a->attr_nr = hashmap_get_size(&g_attr_hashmap.map);
 
                attr_hashmap_add(&g_attr_hashmap, a->name, namelen, a);
-               assert(a->attr_nr == (g_attr_hashmap.map.size - 1));
+               assert(a->attr_nr ==
+                      (hashmap_get_size(&g_attr_hashmap.map) - 1));
        }
 
        hashmap_unlock(&g_attr_hashmap);
index 2549eaf..96beeb5 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -826,7 +826,8 @@ static int check_ancestors(const char *prefix)
 
        /* Clean up objects used, as they will be reused. */
        clear_commit_marks_for_object_array(&pending_copy, ALL_REV_FLAGS);
-       free(pending_copy.objects);
+
+       object_array_clear(&pending_copy);
 
        return res;
 }
index 36541d0..4377ce2 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -90,24 +90,24 @@ int install_branch_config(int flag, const char *local, const char *origin, const
                if (shortname) {
                        if (origin)
                                printf_ln(rebasing ?
-                                         _("Branch %s set up to track remote branch %s from %s by rebasing.") :
-                                         _("Branch %s set up to track remote branch %s from %s."),
+                                         _("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") :
+                                         _("Branch '%s' set up to track remote branch '%s' from '%s'."),
                                          local, shortname, origin);
                        else
                                printf_ln(rebasing ?
-                                         _("Branch %s set up to track local branch %s by rebasing.") :
-                                         _("Branch %s set up to track local branch %s."),
+                                         _("Branch '%s' set up to track local branch '%s' by rebasing.") :
+                                         _("Branch '%s' set up to track local branch '%s'."),
                                          local, shortname);
                } else {
                        if (origin)
                                printf_ln(rebasing ?
-                                         _("Branch %s set up to track remote ref %s by rebasing.") :
-                                         _("Branch %s set up to track remote ref %s."),
+                                         _("Branch '%s' set up to track remote ref '%s' by rebasing.") :
+                                         _("Branch '%s' set up to track remote ref '%s'."),
                                          local, remote);
                        else
                                printf_ln(rebasing ?
-                                         _("Branch %s set up to track local ref %s by rebasing.") :
-                                         _("Branch %s set up to track local ref %s."),
+                                         _("Branch '%s' set up to track local ref '%s' by rebasing.") :
+                                         _("Branch '%s' set up to track local ref '%s'."),
                                          local, remote);
                }
        }
@@ -191,9 +191,8 @@ int validate_new_branchname(const char *name, struct strbuf *ref,
 
        if (!attr_only) {
                const char *head;
-               struct object_id oid;
 
-               head = resolve_ref_unsafe("HEAD", 0, oid.hash, NULL);
+               head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
                if (!is_bare_repository() && head && !strcmp(head, ref->buf))
                        die(_("Cannot force update the current branch."));
        }
@@ -357,8 +356,9 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref,
 
                if (worktrees[i]->is_detached)
                        continue;
-               if (worktrees[i]->head_ref &&
-                   strcmp(oldref, worktrees[i]->head_ref))
+               if (!worktrees[i]->head_ref)
+                       continue;
+               if (strcmp(oldref, worktrees[i]->head_ref))
                        continue;
 
                refs = get_worktree_ref_store(worktrees[i]);
index c20548e..a648cf4 100644 (file)
@@ -119,6 +119,7 @@ int add_files_to_cache(const char *prefix,
        rev.diffopt.flags |= DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
        rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
        run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
+       clear_pathspec(&rev.prune_data);
        return !!data.add_errors;
 }
 
@@ -514,5 +515,7 @@ finish:
                        die(_("Unable to write new index file"));
        }
 
+       UNLEAK(pathspec);
+       UNLEAK(dir);
        return exit_status;
 }
index c369dd1..d7513f5 100644 (file)
@@ -671,9 +671,7 @@ static int detect_patch_format(const char **paths)
                goto done;
        }
 
-       strbuf_reset(&l2);
        strbuf_getline(&l2, fp);
-       strbuf_reset(&l3);
        strbuf_getline(&l3, fp);
 
        /*
@@ -696,6 +694,8 @@ static int detect_patch_format(const char **paths)
 done:
        fclose(fp);
        strbuf_release(&l1);
+       strbuf_release(&l2);
+       strbuf_release(&l3);
        return ret;
 }
 
@@ -881,6 +881,7 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
 static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
 {
        struct strbuf sb = STRBUF_INIT;
+       int rc = 0;
 
        while (!strbuf_getline_lf(&sb, in)) {
                const char *str;
@@ -894,19 +895,27 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
 
                        errno = 0;
                        timestamp = parse_timestamp(str, &end, 10);
-                       if (errno)
-                               return error(_("invalid timestamp"));
+                       if (errno) {
+                               rc = error(_("invalid timestamp"));
+                               goto exit;
+                       }
 
-                       if (!skip_prefix(end, " ", &str))
-                               return error(_("invalid Date line"));
+                       if (!skip_prefix(end, " ", &str)) {
+                               rc = error(_("invalid Date line"));
+                               goto exit;
+                       }
 
                        errno = 0;
                        tz = strtol(str, &end, 10);
-                       if (errno)
-                               return error(_("invalid timezone offset"));
+                       if (errno) {
+                               rc = error(_("invalid timezone offset"));
+                               goto exit;
+                       }
 
-                       if (*end)
-                               return error(_("invalid Date line"));
+                       if (*end) {
+                               rc = error(_("invalid Date line"));
+                               goto exit;
+                       }
 
                        /*
                         * mercurial's timezone is in seconds west of UTC,
@@ -931,9 +940,9 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
                fwrite(sb.buf, 1, sb.len, out);
                strbuf_reset(&sb);
        }
-
+exit:
        strbuf_release(&sb);
-       return 0;
+       return rc;
 }
 
 /**
@@ -2096,6 +2105,7 @@ static int safe_to_abort(const struct am_state *state)
                        die(_("could not parse %s"), am_path(state, "abort-safety"));
        } else
                oidclr(&abort_safety);
+       strbuf_release(&sb);
 
        if (get_oid("HEAD", &head))
                oidclr(&head);
index e0daf17..67adaef 100644 (file)
@@ -488,7 +488,7 @@ static int read_ancestry(const char *graft_file)
                return -1;
        while (!strbuf_getwholeline(&buf, fp, '\n')) {
                /* The format is just "Commit Parent1 Parent2 ...\n" */
-               struct commit_graft *graft = read_graft_line(buf.buf, buf.len);
+               struct commit_graft *graft = read_graft_line(&buf);
                if (graft)
                        register_commit_graft(graft, 0);
        }
index 16d391b..79dc918 100644 (file)
@@ -28,6 +28,7 @@ static const char * const builtin_branch_usage[] = {
        N_("git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"),
        N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
        N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
+       N_("git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"),
        N_("git branch [<options>] [-r | -a] [--points-at]"),
        N_("git branch [<options>] [-r | -a] [--format]"),
        NULL
@@ -92,7 +93,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)
                        return config_error_nonbool(var);
                return color_parse(value, branch_colors[slot]);
        }
-       return git_default_config(var, value, cb);
+       return git_color_default_config(var, value, cb);
 }
 
 static const char *branch_get_color(enum color_branch ix)
@@ -216,7 +217,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                if (!head_rev)
                        die(_("Couldn't look up commit object for HEAD"));
        }
-       for (i = 0; i < argc; i++, strbuf_release(&bname)) {
+       for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
                char *target = NULL;
                int flags = 0;
 
@@ -281,8 +282,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
        }
 
        free(name);
+       strbuf_release(&bname);
 
-       return(ret);
+       return ret;
 }
 
 static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
@@ -352,7 +354,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r
                        strbuf_addf(&obname, "%%(objectname:short=%d)", filter->abbrev);
 
                strbuf_addf(&local, "%%(align:%d,left)%%(refname:lstrip=2)%%(end)", maxwidth);
-               strbuf_addf(&local, "%s", branch_get_color(BRANCH_COLOR_RESET));
+               strbuf_addstr(&local, branch_get_color(BRANCH_COLOR_RESET));
                strbuf_addf(&local, " %s ", obname.buf);
 
                if (filter->verbose > 1)
@@ -456,15 +458,19 @@ static void reject_rebase_or_bisect_branch(const char *target)
        free_worktrees(worktrees);
 }
 
-static void rename_branch(const char *oldname, const char *newname, int force)
+static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
 {
        struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
        struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
        int recovery = 0;
        int clobber_head_ok;
 
-       if (!oldname)
-               die(_("cannot rename the current branch while not on any."));
+       if (!oldname) {
+               if (copy)
+                       die(_("cannot copy the current branch while not on any."));
+               else
+                       die(_("cannot rename the current branch while not on any."));
+       }
 
        if (strbuf_check_branch_ref(&oldref, oldname)) {
                /*
@@ -487,16 +493,29 @@ static void rename_branch(const char *oldname, const char *newname, int force)
 
        reject_rebase_or_bisect_branch(oldref.buf);
 
-       strbuf_addf(&logmsg, "Branch: renamed %s to %s",
-                oldref.buf, newref.buf);
+       if (copy)
+               strbuf_addf(&logmsg, "Branch: copied %s to %s",
+                           oldref.buf, newref.buf);
+       else
+               strbuf_addf(&logmsg, "Branch: renamed %s to %s",
+                           oldref.buf, newref.buf);
 
-       if (rename_ref(oldref.buf, newref.buf, logmsg.buf))
+       if (!copy && rename_ref(oldref.buf, newref.buf, logmsg.buf))
                die(_("Branch rename failed"));
+       if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
+               die(_("Branch copy failed"));
 
-       if (recovery)
-               warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11);
+       if (recovery) {
+               if (copy)
+                       warning(_("Copied a misnamed branch '%s' away"),
+                               oldref.buf + 11);
+               else
+                       warning(_("Renamed a misnamed branch '%s' away"),
+                               oldref.buf + 11);
+       }
 
-       if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
+       if (!copy &&
+           replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
                die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
 
        strbuf_release(&logmsg);
@@ -505,8 +524,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)
        strbuf_release(&oldref);
        strbuf_addf(&newsection, "branch.%s", newref.buf + 11);
        strbuf_release(&newref);
-       if (git_config_rename_section(oldsection.buf, newsection.buf) < 0)
+       if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
                die(_("Branch is renamed, but update of config-file failed"));
+       if (copy && strcmp(oldname, newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
+               die(_("Branch is copied, but update of config-file failed"));
        strbuf_release(&oldsection);
        strbuf_release(&newsection);
 }
@@ -544,7 +565,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, force = 0, list = 0;
+       int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
        int reflog = 0, edit_description = 0;
        int quiet = 0, unset_upstream = 0;
        const char *new_upstream = NULL;
@@ -561,8 +582,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT__QUIET(&quiet, N_("suppress informational messages")),
                OPT_SET_INT('t', "track",  &track, N_("set up tracking mode (see git-pull(1))"),
                        BRANCH_TRACK_EXPLICIT),
-               OPT_SET_INT( 0, "set-upstream",  &track, N_("change upstream info"),
-                       BRANCH_TRACK_OVERRIDE),
+               { OPTION_SET_INT, 0, "set-upstream", &track, NULL, N_("do not use"),
+                       PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, BRANCH_TRACK_OVERRIDE },
                OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")),
                OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("Unset the upstream info")),
                OPT__COLOR(&branch_use_color, N_("use colored output")),
@@ -581,6 +602,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
                OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
                OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
+               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(0, "list", &list, N_("list branch names")),
                OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
                OPT_BOOL(0, "edit-description", &edit_description,
@@ -624,14 +647,14 @@ 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 && !edit_description && !new_upstream && !unset_upstream && argc == 0)
+       if (!delete && !rename && !copy && !edit_description && !new_upstream && !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 + !!new_upstream +
+       if (!!delete + !!rename + !!copy + !!new_upstream +
            list + unset_upstream > 1)
                usage_with_options(builtin_branch_usage, options);
 
@@ -649,6 +672,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        if (force) {
                delete *= 2;
                rename *= 2;
+               copy *= 2;
        }
 
        if (delete) {
@@ -703,20 +727,29 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
                if (edit_branch_description(branch_name))
                        return 1;
+       } else if (copy) {
+               if (!argc)
+                       die(_("branch name required"));
+               else if (argc == 1)
+                       copy_or_rename_branch(head, argv[0], 1, copy > 1);
+               else if (argc == 2)
+                       copy_or_rename_branch(argv[0], argv[1], 1, copy > 1);
+               else
+                       die(_("too many branches for a copy operation"));
        } else if (rename) {
                if (!argc)
                        die(_("branch name required"));
                else if (argc == 1)
-                       rename_branch(head, argv[0], rename > 1);
+                       copy_or_rename_branch(head, argv[0], 0, rename > 1);
                else if (argc == 2)
-                       rename_branch(argv[0], argv[1], rename > 1);
+                       copy_or_rename_branch(argv[0], argv[1], 0, rename > 1);
                else
-                       die(_("too many branches for a rename operation"));
+                       die(_("too many arguments for a rename operation"));
        } else if (new_upstream) {
                struct branch *branch = branch_get(argv[0]);
 
                if (argc > 1)
-                       die(_("too many branches to set new upstream"));
+                       die(_("too many arguments to set new upstream"));
 
                if (!branch) {
                        if (!argc || !strcmp(argv[0], "HEAD"))
@@ -739,7 +772,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                struct strbuf buf = STRBUF_INIT;
 
                if (argc > 1)
-                       die(_("too many branches to unset upstream"));
+                       die(_("too many arguments to unset upstream"));
 
                if (!branch) {
                        if (!argc || !strcmp(argv[0], "HEAD"))
@@ -759,8 +792,6 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                strbuf_release(&buf);
        } else if (argc > 0 && argc <= 2) {
                struct branch *branch = branch_get(argv[0]);
-               int branch_existed = 0, remote_tracking = 0;
-               struct strbuf buf = STRBUF_INIT;
 
                if (!strcmp(argv[0], "HEAD"))
                        die(_("it does not make sense to create 'HEAD' manually"));
@@ -772,28 +803,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                        die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
 
                if (track == BRANCH_TRACK_OVERRIDE)
-                       fprintf(stderr, _("The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to\n"));
-
-               strbuf_addf(&buf, "refs/remotes/%s", branch->name);
-               remote_tracking = ref_exists(buf.buf);
-               strbuf_release(&buf);
+                       die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead."));
 
-               branch_existed = ref_exists(branch->refname);
                create_branch(argv[0], (argc == 2) ? argv[1] : head,
                              force, reflog, 0, quiet, track);
 
-               /*
-                * We only show the instructions if the user gave us
-                * one branch which doesn't exist locally, but is the
-                * name of a remote-tracking branch.
-                */
-               if (argc == 1 && track == BRANCH_TRACK_OVERRIDE &&
-                   !branch_existed && remote_tracking) {
-                       fprintf(stderr, _("\nIf you wanted to make '%s' track '%s', do this:\n\n"), head, branch->name);
-                       fprintf(stderr, "    git branch -d %s\n", branch->name);
-                       fprintf(stderr, "    git branch --set-upstream-to %s\n", branch->name);
-               }
-
        } else
                usage_with_options(builtin_branch_usage, options);
 
index 4ccbfaa..f5fa4fd 100644 (file)
@@ -97,7 +97,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                return !has_object_file(&oid);
 
        case 'w':
-               if (!path[0])
+               if (!path)
                        die("git cat-file --filters %s: <object> must be "
                            "<sha1:path>", obj_name);
 
@@ -107,12 +107,13 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                break;
 
        case 'c':
-               if (!path[0])
+               if (!path)
                        die("git cat-file --textconv %s: <object> must be <sha1:path>",
                            obj_name);
 
                if (textconv_object(path, obj_context.mode, &oid, 1, &buf, &size))
                        break;
+               /* else fallthrough */
 
        case 'p':
                type = sha1_object_info(oid.hash, NULL);
index eac4994..6c40ff1 100644 (file)
@@ -45,6 +45,7 @@ static int check_ref_format_branch(const char *arg)
        if (strbuf_check_branch_ref(&sb, arg))
                die("'%s' is not a valid branch name", arg);
        printf("%s\n", sb.buf + 11);
+       strbuf_release(&sb);
        return 0;
 }
 
index 5c202b7..fc4f8fd 100644 (file)
@@ -436,6 +436,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
                 * update paths in the work tree, and we cannot revert
                 * them.
                 */
+               /* fallthrough */
        case 0:
                return 0;
        default:
@@ -796,9 +797,14 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
        for_each_ref(add_pending_uninteresting_ref, &revs);
        add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING);
 
+       /* Save pending objects, so they can be cleaned up later. */
        refs = revs.pending;
        revs.leak_pending = 1;
 
+       /*
+        * prepare_revision_walk (together with .leak_pending = 1) makes us
+        * the sole owner of the list of pending objects.
+        */
        if (prepare_revision_walk(&revs))
                die(_("internal error in revision walk"));
        if (!(old->object.flags & UNINTERESTING))
@@ -806,8 +812,10 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
        else
                describe_detached_head(_("Previous HEAD position was"), old);
 
+       /* Clean up objects used, as they will be reused. */
        clear_commit_marks_for_object_array(&refs, ALL_REV_FLAGS);
-       free(refs.objects);
+
+       object_array_clear(&refs);
 }
 
 static int switch_branches(const struct checkout_opts *opts,
@@ -1116,9 +1124,8 @@ static int checkout_branch(struct checkout_opts *opts,
 
        if (new->path && !opts->force_detach && !opts->new_branch &&
            !opts->ignore_other_worktrees) {
-               struct object_id oid;
                int flag;
-               char *head_ref = resolve_refdup("HEAD", 0, oid.hash, &flag);
+               char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag);
                if (head_ref &&
                    (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)))
                        die_if_checked_out(new->path, 1);
@@ -1290,6 +1297,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                strbuf_release(&buf);
        }
 
+       UNLEAK(opts);
        if (opts.patch_mode || opts.pathspec.nr)
                return checkout_paths(&opts, new.name);
        else
index 21a7a32..189e206 100644 (file)
@@ -126,7 +126,8 @@ static int git_clean_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return git_default_config(var, value, cb);
+       /* inspect the color.ui config variable and others */
+       return git_color_default_config(var, value, cb);
 }
 
 static const char *clean_get_color(enum color_clean ix)
@@ -167,7 +168,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
                }
 
                *dir_gone = 0;
-               return 0;
+               goto out;
        }
 
        dir = opendir(path->buf);
@@ -181,7 +182,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
                        warning_errno(_(msg_warn_remove_failed), quoted.buf);
                        *dir_gone = 0;
                }
-               return res;
+               ret = res;
+               goto out;
        }
 
        strbuf_complete(path, '/');
@@ -249,6 +251,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
                for (i = 0; i < dels.nr; i++)
                        printf(dry_run ?  _(msg_would_remove) : _(msg_remove), dels.items[i].string);
        }
+out:
+       strbuf_release(&quoted);
        string_list_clear(&dels, 0);
        return ret;
 }
index 8d11b57..dbddd98 100644 (file)
@@ -507,8 +507,8 @@ static void remove_junk(void)
        if (junk_work_tree) {
                strbuf_addstr(&sb, junk_work_tree);
                remove_dir_recursively(&sb, 0);
-               strbuf_reset(&sb);
        }
+       strbuf_release(&sb);
 }
 
 static void remove_junk_on_signal(int signo)
index 19e898f..2177251 100644 (file)
@@ -102,7 +102,6 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
                        if (fd && close(fd))
                                die_errno("git commit-tree: failed to close '%s'",
                                          argv[i]);
-                       strbuf_complete_line(&buffer);
                        continue;
                }
 
index b3b04f5..d75b380 100644 (file)
@@ -335,7 +335,7 @@ static void refresh_cache_or_die(int refresh_flags)
 static const char *prepare_index(int argc, const char **argv, const char *prefix,
                                 const struct commit *current_head, int is_status)
 {
-       struct string_list partial;
+       struct string_list partial = STRING_LIST_INIT_DUP;
        struct pathspec pathspec;
        int refresh_flags = REFRESH_QUIET;
        const char *ret;
@@ -380,7 +380,8 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
                        warning(_("Failed to update main cache tree"));
 
                commit_style = COMMIT_NORMAL;
-               return get_lock_file_path(&index_lock);
+               ret = get_lock_file_path(&index_lock);
+               goto out;
        }
 
        /*
@@ -403,7 +404,8 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
                if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
                        die(_("unable to write new_index file"));
                commit_style = COMMIT_NORMAL;
-               return get_lock_file_path(&index_lock);
+               ret = get_lock_file_path(&index_lock);
+               goto out;
        }
 
        /*
@@ -429,7 +431,8 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
                        rollback_lock_file(&index_lock);
                }
                commit_style = COMMIT_AS_IS;
-               return get_index_file();
+               ret = get_index_file();
+               goto out;
        }
 
        /*
@@ -460,7 +463,6 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
                        die(_("cannot do a partial commit during a cherry-pick."));
        }
 
-       string_list_init(&partial, 1);
        if (list_paths(&partial, !current_head ? NULL : "HEAD", prefix, &pathspec))
                exit(1);
 
@@ -490,6 +492,9 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
        discard_cache();
        ret = get_lock_file_path(&false_lock);
        read_cache_from(ret);
+out:
+       string_list_clear(&partial, 0);
+       clear_pathspec(&pathspec);
        return ret;
 }
 
@@ -1387,7 +1392,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        read_cache_preload(&s.pathspec);
        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &s.pathspec, NULL, NULL);
 
-       fd = hold_locked_index(&index_lock, 0);
+       if (use_optional_locks())
+               fd = hold_locked_index(&index_lock, 0);
+       else
+               fd = -1;
 
        s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
        if (!s.is_initial)
@@ -1431,7 +1439,6 @@ static void print_summary(const char *prefix, const struct object_id *oid,
        struct rev_info rev;
        struct commit *commit;
        struct strbuf format = STRBUF_INIT;
-       struct object_id junk_oid;
        const char *head;
        struct pretty_print_context pctx = {0};
        struct strbuf author_ident = STRBUF_INIT;
@@ -1484,7 +1491,7 @@ static void print_summary(const char *prefix, const struct object_id *oid,
        rev.diffopt.break_opt = 0;
        diff_setup_done(&rev.diffopt);
 
-       head = resolve_ref_unsafe("HEAD", 0, junk_oid.hash, NULL);
+       head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
        if (!strcmp(head, "HEAD"))
                head = _("detached HEAD");
        else
@@ -1818,6 +1825,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        if (!quiet)
                print_summary(prefix, &oid, !current_head);
 
-       strbuf_release(&err);
+       UNLEAK(err);
+       UNLEAK(sb);
        return 0;
 }
index 70ff231..d13daee 100644 (file)
@@ -518,10 +518,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                        die("$HOME not set");
 
                if (access_or_warn(user_config, R_OK, 0) &&
-                   xdg_config && !access_or_warn(xdg_config, R_OK, 0))
+                   xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
                        given_config_source.file = xdg_config;
-               else
+                       free(user_config);
+               } else {
                        given_config_source.file = user_config;
+                       free(xdg_config);
+               }
        }
        else if (use_system_config)
                given_config_source.file = git_etc_gitconfig();
@@ -628,6 +631,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                check_write();
                check_argc(argc, 2, 2);
                value = normalize_value(argv[0], argv[1]);
+               UNLEAK(value);
                ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
                if (ret == CONFIG_NOTHING_SET)
                        error(_("cannot overwrite multiple values with a single value\n"
@@ -638,6 +642,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                check_write();
                check_argc(argc, 2, 3);
                value = normalize_value(argv[0], argv[1]);
+               UNLEAK(value);
                return git_config_set_multivar_in_file_gently(given_config_source.file,
                                                              argv[0], value, argv[2], 0);
        }
@@ -645,6 +650,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                check_write();
                check_argc(argc, 2, 2);
                value = normalize_value(argv[0], argv[1]);
+               UNLEAK(value);
                return git_config_set_multivar_in_file_gently(given_config_source.file,
                                                              argv[0], value,
                                                              CONFIG_REGEX_NONE, 0);
@@ -653,6 +659,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                check_write();
                check_argc(argc, 2, 3);
                value = normalize_value(argv[0], argv[1]);
+               UNLEAK(value);
                return git_config_set_multivar_in_file_gently(given_config_source.file,
                                                              argv[0], value, argv[2], 1);
        }
index 9c13c68..29075db 100644 (file)
@@ -129,13 +129,24 @@ static void add_to_known_names(const char *path,
 
 static int get_name(const char *path, const struct object_id *oid, int flag, void *cb_data)
 {
-       int is_tag = starts_with(path, "refs/tags/");
+       int is_tag = 0;
        struct object_id peeled;
        int is_annotated, prio;
-
-       /* Reject anything outside refs/tags/ unless --all */
-       if (!all && !is_tag)
+       const char *path_to_match = NULL;
+
+       if (skip_prefix(path, "refs/tags/", &path_to_match)) {
+               is_tag = 1;
+       } else if (all) {
+               if ((exclude_patterns.nr || patterns.nr) &&
+                   !skip_prefix(path, "refs/heads/", &path_to_match) &&
+                   !skip_prefix(path, "refs/remotes/", &path_to_match)) {
+                       /* Only accept reference of known type if there are match/exclude patterns */
+                       return 0;
+               }
+       } else {
+               /* Reject anything outside refs/tags/ unless --all */
                return 0;
+       }
 
        /*
         * If we're given exclude patterns, first exclude any tag which match
@@ -144,11 +155,8 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
        if (exclude_patterns.nr) {
                struct string_list_item *item;
 
-               if (!is_tag)
-                       return 0;
-
                for_each_string_list_item(item, &exclude_patterns) {
-                       if (!wildmatch(item->string, path + 10, 0))
+                       if (!wildmatch(item->string, path_to_match, 0))
                                return 0;
                }
        }
@@ -158,18 +166,18 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
         * pattern.
         */
        if (patterns.nr) {
+               int found = 0;
                struct string_list_item *item;
 
-               if (!is_tag)
-                       return 0;
-
                for_each_string_list_item(item, &patterns) {
-                       if (!wildmatch(item->string, path + 10, 0))
+                       if (!wildmatch(item->string, path_to_match, 0)) {
+                               found = 1;
                                break;
+                       }
+               }
 
-                       /* If we get here, no pattern matched. */
+               if (!found)
                        return 0;
-               }
        }
 
        /* Is it annotated? */
@@ -508,7 +516,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 
        hashmap_init(&names, commit_name_cmp, NULL, 0);
        for_each_rawref(get_name, NULL);
-       if (!names.size && !always)
+       if (!hashmap_get_size(&names) && !always)
                die(_("No names found, cannot describe anything."));
 
        if (argc == 0) {
index 9d772f8..522f4fd 100644 (file)
@@ -56,5 +56,6 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
                return -1;
        }
        result = run_diff_index(&rev, cached);
+       UNLEAK(rev);
        return diff_result_code(&rev.diffopt, result);
 }
index 7e3ebce..f5bbd4d 100644 (file)
@@ -464,5 +464,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        result = diff_result_code(&rev.diffopt, result);
        if (1 < rev.diffopt.skip_stat_unmatch)
                refresh_index_quietly();
+       UNLEAK(rev);
+       UNLEAK(ent);
+       UNLEAK(blob);
        return result;
 }
index d412c0a..2fb60d6 100644 (file)
@@ -344,6 +344,7 @@ static void show_filemodify(struct diff_queue_struct *q,
                            struct diff_options *options, void *data)
 {
        int i;
+       struct string_list *changed = data;
 
        /*
         * Handle files below a directory first, in case they are all deleted
@@ -359,20 +360,31 @@ static void show_filemodify(struct diff_queue_struct *q,
                case DIFF_STATUS_DELETED:
                        printf("D ");
                        print_path(spec->path);
+                       string_list_insert(changed, spec->path);
                        putchar('\n');
                        break;
 
                case DIFF_STATUS_COPIED:
                case DIFF_STATUS_RENAMED:
-                       printf("%c ", q->queue[i]->status);
-                       print_path(ospec->path);
-                       putchar(' ');
-                       print_path(spec->path);
-                       putchar('\n');
-
-                       if (!oidcmp(&ospec->oid, &spec->oid) &&
-                           ospec->mode == spec->mode)
-                               break;
+                       /*
+                        * If a change in the file corresponding to ospec->path
+                        * has been observed, we cannot trust its contents
+                        * because the diff is calculated based on the prior
+                        * contents, not the current contents.  So, declare a
+                        * copy or rename only if there was no change observed.
+                        */
+                       if (!string_list_has_string(changed, ospec->path)) {
+                               printf("%c ", q->queue[i]->status);
+                               print_path(ospec->path);
+                               putchar(' ');
+                               print_path(spec->path);
+                               string_list_insert(changed, spec->path);
+                               putchar('\n');
+
+                               if (!oidcmp(&ospec->oid, &spec->oid) &&
+                                   ospec->mode == spec->mode)
+                                       break;
+                       }
                        /* fallthrough */
 
                case DIFF_STATUS_TYPE_CHANGED:
@@ -393,6 +405,7 @@ static void show_filemodify(struct diff_queue_struct *q,
                                       get_object_mark(object));
                        }
                        print_path(spec->path);
+                       string_list_insert(changed, spec->path);
                        putchar('\n');
                        break;
 
@@ -528,7 +541,8 @@ static void anonymize_ident_line(const char **beg, const char **end)
        *end = out->buf + out->len;
 }
 
-static void handle_commit(struct commit *commit, struct rev_info *rev)
+static void handle_commit(struct commit *commit, struct rev_info *rev,
+                         struct string_list *paths_of_changed_objects)
 {
        int saved_output_format = rev->diffopt.output_format;
        const char *commit_buffer;
@@ -615,6 +629,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
        if (full_tree)
                printf("deleteall\n");
        log_tree_diff_flush(rev);
+       string_list_clear(paths_of_changed_objects, 0);
        rev->diffopt.output_format = saved_output_format;
 
        printf("\n");
@@ -630,15 +645,15 @@ static void *anonymize_tag(const void *old, size_t *len)
        return strbuf_detach(&out, len);
 }
 
-static void handle_tail(struct object_array *commits, struct rev_info *revs)
+static void handle_tail(struct object_array *commits, struct rev_info *revs,
+                       struct string_list *paths_of_changed_objects)
 {
        struct commit *commit;
        while (commits->nr) {
-               commit = (struct commit *)commits->objects[commits->nr - 1].item;
+               commit = (struct commit *)object_array_pop(commits);
                if (has_unshown_parent(commit))
                        return;
-               handle_commit(commit, revs);
-               commits->nr--;
+               handle_commit(commit, revs, paths_of_changed_objects);
        }
 }
 
@@ -977,6 +992,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        char *export_filename = NULL, *import_filename = NULL;
        uint32_t lastimportid;
        struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
+       struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
        struct option options[] = {
                OPT_INTEGER(0, "progress", &progress,
                            N_("show progress after <n> objects")),
@@ -1049,14 +1065,15 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
        revs.diffopt.format_callback = show_filemodify;
+       revs.diffopt.format_callback_data = &paths_of_changed_objects;
        DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
        while ((commit = get_revision(&revs))) {
                if (has_unshown_parent(commit)) {
                        add_object_array(&commit->object, NULL, &commits);
                }
                else {
-                       handle_commit(commit, &revs);
-                       handle_tail(&commits, &revs);
+                       handle_commit(commit, &revs, &paths_of_changed_objects);
+                       handle_tail(&commits, &revs, &paths_of_changed_objects);
                }
        }
 
index 5d7c921..e931be9 100644 (file)
@@ -36,6 +36,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
                OPT_GROUP(""),
                OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
                OPT_STRING(  0 , "format", &format.format, N_("format"), N_("format to use for the output")),
+               OPT__COLOR(&format.use_color, N_("respect format colors")),
                OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
                            N_("field name to sort on"), &parse_opt_ref_sorting),
                OPT_CALLBACK(0, "points-at", &filter.points_at,
index 1e4c471..56afe40 100644 (file)
@@ -182,12 +182,7 @@ static int traverse_reachable(void)
        if (show_progress)
                progress = start_delayed_progress(_("Checking connectivity"), 0);
        while (pending.nr) {
-               struct object_array_entry *entry;
-               struct object *obj;
-
-               entry = pending.objects + --pending.nr;
-               obj = entry->item;
-               result |= traverse_one_object(obj);
+               result |= traverse_one_object(object_array_pop(&pending));
                display_progress(progress, ++nr);
        }
        stop_progress(&progress);
index 3c78fcb..3c5eae0 100644 (file)
@@ -47,7 +47,7 @@ static struct argv_array prune = ARGV_ARRAY_INIT;
 static struct argv_array prune_worktrees = ARGV_ARRAY_INIT;
 static struct argv_array rerere = ARGV_ARRAY_INIT;
 
-static struct tempfile pidfile;
+static struct tempfile *pidfile;
 static struct lock_file log_lock;
 
 static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
@@ -78,7 +78,7 @@ static void process_log_file(void)
                 */
                int saved_errno = errno;
                fprintf(stderr, _("Failed to fstat %s: %s"),
-                       get_tempfile_path(&log_lock.tempfile),
+                       get_tempfile_path(log_lock.tempfile),
                        strerror(saved_errno));
                fflush(stderr);
                commit_lock_file(&log_lock);
@@ -242,7 +242,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
        int fd;
        char *pidfile_path;
 
-       if (is_tempfile_active(&pidfile))
+       if (is_tempfile_active(pidfile))
                /* already locked */
                return NULL;
 
@@ -258,7 +258,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
                int should_exit;
 
                if (!scan_fmt)
-                       scan_fmt = xstrfmt("%s %%%dc", "%"SCNuMAX, HOST_NAME_MAX);
+                       scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX);
                fp = fopen(pidfile_path, "r");
                memset(locking_host, 0, sizeof(locking_host));
                should_exit =
@@ -293,7 +293,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
        write_in_full(fd, sb.buf, sb.len);
        strbuf_release(&sb);
        commit_lock_file(&lock);
-       register_tempfile(&pidfile, pidfile_path);
+       pidfile = register_tempfile(pidfile_path);
        free(pidfile_path);
        return NULL;
 }
index e21c541..2706fcf 100644 (file)
@@ -26,15 +26,16 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
                usage(builtin_get_tar_commit_id_usage);
 
        n = read_in_full(0, buffer, HEADERSIZE);
-       if (n < HEADERSIZE)
-               die("git get-tar-commit-id: read error");
+       if (n < 0)
+               die_errno("git get-tar-commit-id: read error");
+       if (n != HEADERSIZE)
+               die_errno("git get-tar-commit-id: EOF before reading tar header");
        if (header->typeflag[0] != 'g')
                return 1;
        if (!skip_prefix(content, "52 comment=", &comment))
                return 1;
 
-       n = write_in_full(1, comment, 41);
-       if (n < 41)
+       if (write_in_full(1, comment, 41) < 0)
                die_errno("git get-tar-commit-id: write error");
 
        return 0;
index 19e2394..2d65f27 100644 (file)
@@ -275,7 +275,7 @@ static int wait_all(void)
 static int grep_cmd_config(const char *var, const char *value, void *cb)
 {
        int st = grep_config(var, value, cb);
-       if (git_default_config(var, value, cb) < 0)
+       if (git_color_default_config(var, value, cb) < 0)
                st = -1;
 
        if (!strcmp(var, "grep.threads")) {
index 334a849..d3c8fc4 100644 (file)
@@ -131,6 +131,7 @@ static void exec_woman_emacs(const char *path, const char *page)
                strbuf_addf(&man_page, "(woman \"%s\")", page);
                execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL);
                warning_errno(_("failed to exec '%s'"), path);
+               strbuf_release(&man_page);
        }
 }
 
@@ -152,6 +153,7 @@ static void exec_man_konqueror(const char *path, const char *page)
                strbuf_addf(&man_page, "man:%s(1)", page);
                execlp(path, filename, "newTab", man_page.buf, (char *)NULL);
                warning_errno(_("failed to exec '%s'"), path);
+               strbuf_release(&man_page);
        }
 }
 
@@ -169,6 +171,7 @@ static void exec_man_cmd(const char *cmd, const char *page)
        strbuf_addf(&shell_cmd, "%s %s", cmd, page);
        execl(SHELL_PATH, SHELL_PATH, "-c", shell_cmd.buf, (char *)NULL);
        warning(_("failed to exec '%s'"), cmd);
+       strbuf_release(&shell_cmd);
 }
 
 static void add_man_viewer(const char *name)
@@ -438,7 +441,7 @@ static const char *check_git_cmd(const char* cmd)
 
        alias = alias_lookup(cmd);
        if (alias) {
-               printf_ln(_("`git %s' is aliased to `%s'"), cmd, alias);
+               printf_ln(_("'%s' is aliased to '%s'"), cmd, alias);
                free(alias);
                exit(0);
        }
index f2be145..8ec459f 100644 (file)
@@ -633,7 +633,7 @@ static int find_ofs_delta(const off_t offset, enum object_type type)
        int first = 0, last = nr_ofs_deltas;
 
        while (first < last) {
-               int next = (first + last) / 2;
+               int next = first + (last - first) / 2;
                struct ofs_delta_entry *delta = &ofs_deltas[next];
                int cmp;
 
@@ -687,7 +687,7 @@ static int find_ref_delta(const unsigned char *sha1, enum object_type type)
        int first = 0, last = nr_ref_deltas;
 
        while (first < last) {
-               int next = (first + last) / 2;
+               int next = first + (last - first) / 2;
                struct ref_delta_entry *delta = &ref_deltas[next];
                int cmp;
 
index 47823f9..c9b7946 100644 (file)
@@ -579,6 +579,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                        set_git_work_tree(work_tree);
        }
 
+       UNLEAK(real_git_dir);
+
        flags |= INIT_DB_EXIST_OK;
        return init_db(git_dir, real_git_dir, template_dir, flags);
 }
index f8cccbc..d81a090 100644 (file)
@@ -1660,10 +1660,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                        check_head = 1;
 
                if (check_head) {
-                       struct object_id oid;
                        const char *ref, *v;
                        ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
-                                                oid.hash, NULL);
+                                                NULL, NULL);
                        if (ref && skip_prefix(ref, "refs/heads/", &v))
                                branch_name = xstrdup(v);
                        else
index e1339e6..8c713c4 100644 (file)
@@ -673,5 +673,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                return bad ? 1 : 0;
        }
 
+       UNLEAK(dir);
        return 0;
 }
index 7df3fe3..ab5ffe8 100644 (file)
@@ -73,6 +73,7 @@ static int show_progress = -1;
 static int default_to_upstream = 1;
 static int signoff;
 static const char *sign_commit;
+static int verify_msg = 1;
 
 static struct strategy all_strategy[] = {
        { "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -236,6 +237,7 @@ static struct option builtin_merge_options[] = {
          N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
        OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
        OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")),
+       OPT_BOOL(0, "verify", &verify_msg, N_("verify commit-msg hook")),
        OPT_END()
 };
 
@@ -253,6 +255,7 @@ static int save_state(struct object_id *stash)
        struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf buffer = STRBUF_INIT;
        const char *argv[] = {"stash", "create", NULL};
+       int rc = -1;
 
        cp.argv = argv;
        cp.out = -1;
@@ -266,11 +269,14 @@ static int save_state(struct object_id *stash)
        if (finish_command(&cp) || len < 0)
                die(_("stash failed"));
        else if (!len)          /* no changes */
-               return -1;
+               goto out;
        strbuf_setlen(&buffer, buffer.len-1);
        if (get_oid(buffer.buf, stash))
                die(_("not a valid object: %s"), buffer.buf);
-       return 0;
+       rc = 0;
+out:
+       strbuf_release(&buffer);
+       return rc;
 }
 
 static void read_empty(unsigned const char *sha1, int verbose)
@@ -780,6 +786,12 @@ static void prepare_to_commit(struct commit_list *remoteheads)
                if (launch_editor(git_path_merge_msg(), NULL, NULL))
                        abort_commit(remoteheads, NULL);
        }
+
+       if (verify_msg && run_commit_hook(0 < option_edit, get_index_file(),
+                                         "commit-msg",
+                                         git_path_merge_msg(), NULL))
+               abort_commit(remoteheads, NULL);
+
        read_merge_msg(&msg);
        strbuf_stripspace(&msg, 0 < option_edit);
        if (!msg.len)
@@ -934,6 +946,7 @@ static void write_merge_heads(struct commit_list *remoteheads)
        if (fast_forward == FF_NO)
                strbuf_addstr(&buf, "no-ff");
        write_file_buf(git_path_merge_mode(), buf.buf, buf.len);
+       strbuf_release(&buf);
 }
 
 static void write_merge_state(struct commit_list *remoteheads)
@@ -1359,7 +1372,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                 * If head can reach all the merge then we are up to date.
                 * but first the most common case of merging one remote.
                 */
-               finish_up_to_date(_("Already up-to-date."));
+               finish_up_to_date(_("Already up to date."));
                goto done;
        } else if (fast_forward != FF_NO && !remoteheads->next &&
                        !common->next &&
@@ -1442,7 +1455,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        }
                }
                if (up_to_date) {
-                       finish_up_to_date(_("Already up-to-date. Yeeah!"));
+                       finish_up_to_date(_("Already up to date. Yeeah!"));
                        goto done;
                }
        }
index c41ea7c..9e088eb 100644 (file)
@@ -253,7 +253,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
                struct commit *commit = (struct commit *)o;
                int from_tag = starts_with(path, "refs/tags/");
 
-               if (taggerdate == ULONG_MAX)
+               if (taggerdate == TIME_MAX)
                        taggerdate = ((struct commit *)o)->date;
                path = name_ref_abbrev(path, can_abbreviate_output);
                name_rev(commit, xstrdup(path), taggerdate, 0, 0,
@@ -494,5 +494,6 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
                                  always, allow_undefined, data.name_only);
        }
 
+       UNLEAK(revs);
        return 0;
 }
index 4303848..8e54f2d 100644 (file)
@@ -328,6 +328,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
        } else {
                finish_copy_notes_for_rewrite(c, msg);
        }
+       strbuf_release(&buf);
        return ret;
 }
 
index 82ad6e0..6e77dfd 100644 (file)
@@ -1012,7 +1012,7 @@ static int want_object_in_pack(const unsigned char *sha1,
                        return want;
        }
 
-       for (entry = packed_git_mru->head; entry; entry = entry->next) {
+       for (entry = packed_git_mru.head; entry; entry = entry->next) {
                struct packed_git *p = entry->item;
                off_t offset;
 
@@ -1030,7 +1030,7 @@ static int want_object_in_pack(const unsigned char *sha1,
                        }
                        want = want_found_object(exclude, p);
                        if (!exclude && want > 0)
-                               mru_mark(packed_git_mru, entry);
+                               mru_mark(&packed_git_mru, entry);
                        if (want != -1)
                                return want;
                }
@@ -1277,7 +1277,7 @@ static int done_pbase_path_pos(unsigned hash)
        int lo = 0;
        int hi = done_pbase_paths_num;
        while (lo < hi) {
-               int mi = (hi + lo) / 2;
+               int mi = lo + (hi - lo) / 2;
                if (done_pbase_paths[mi] == hash)
                        return mi;
                if (done_pbase_paths[mi] < hash)
@@ -2171,7 +2171,10 @@ static void *threaded_find_deltas(void *arg)
 {
        struct thread_params *me = arg;
 
+       progress_lock();
        while (me->remaining) {
+               progress_unlock();
+
                find_deltas(me->list, &me->remaining,
                            me->window, me->depth, me->processed);
 
@@ -2193,7 +2196,10 @@ static void *threaded_find_deltas(void *arg)
                        pthread_cond_wait(&me->cond, &me->mutex);
                me->data_ready = 0;
                pthread_mutex_unlock(&me->mutex);
+
+               progress_lock();
        }
+       progress_unlock();
        /* leave ->working 1 so that this doesn't get more work assigned */
        return NULL;
 }
@@ -2557,8 +2563,8 @@ struct in_pack_object {
 };
 
 struct in_pack {
-       int alloc;
-       int nr;
+       unsigned int alloc;
+       unsigned int nr;
        struct in_pack_object *array;
 };
 
index 7fe2814..6f772e8 100644 (file)
@@ -325,6 +325,10 @@ static int git_pull_config(const char *var, const char *value, void *cb)
        if (!strcmp(var, "rebase.autostash")) {
                config_autostash = git_config_bool(var, value);
                return 0;
+       } else if (!strcmp(var, "submodule.recurse")) {
+               recurse_submodules = git_config_bool(var, value) ?
+                       RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
+               return 0;
        }
        return git_default_config(var, value, cb);
 }
@@ -815,6 +819,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
        if (!getenv("GIT_REFLOG_ACTION"))
                set_reflog_message(argc, argv);
 
+       git_config(git_pull_config, NULL);
+
        argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
 
        parse_repo_refspecs(argc, argv, &repo, &refspecs);
@@ -825,8 +831,6 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
        if (opt_rebase < 0)
                opt_rebase = config_get_rebase();
 
-       git_config(git_pull_config, NULL);
-
        if (read_cache_unmerged())
                die_resolve_conflict("pull");
 
index c82b4dc..f851936 100644 (file)
@@ -12,15 +12,30 @@ static const char * const builtin_rebase_helper_usage[] = {
 int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
 {
        struct replay_opts opts = REPLAY_OPTS_INIT;
+       int keep_empty = 0;
        enum {
-               CONTINUE = 1, ABORT
+               CONTINUE = 1, ABORT, MAKE_SCRIPT, SHORTEN_SHA1S, EXPAND_SHA1S,
+               CHECK_TODO_LIST, SKIP_UNNECESSARY_PICKS, REARRANGE_SQUASH
        } command = 0;
        struct option options[] = {
                OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
+               OPT_BOOL(0, "keep-empty", &keep_empty, N_("keep empty commits")),
                OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
                                CONTINUE),
                OPT_CMDMODE(0, "abort", &command, N_("abort rebase"),
                                ABORT),
+               OPT_CMDMODE(0, "make-script", &command,
+                       N_("make rebase script"), MAKE_SCRIPT),
+               OPT_CMDMODE(0, "shorten-ids", &command,
+                       N_("shorten SHA-1s in the todo list"), SHORTEN_SHA1S),
+               OPT_CMDMODE(0, "expand-ids", &command,
+                       N_("expand SHA-1s in the todo list"), EXPAND_SHA1S),
+               OPT_CMDMODE(0, "check-todo-list", &command,
+                       N_("check the todo list"), CHECK_TODO_LIST),
+               OPT_CMDMODE(0, "skip-unnecessary-picks", &command,
+                       N_("skip unnecessary picks"), SKIP_UNNECESSARY_PICKS),
+               OPT_CMDMODE(0, "rearrange-squash", &command,
+                       N_("rearrange fixup/squash lines"), REARRANGE_SQUASH),
                OPT_END()
        };
 
@@ -37,5 +52,17 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
                return !!sequencer_continue(&opts);
        if (command == ABORT && argc == 1)
                return !!sequencer_remove_state(&opts);
+       if (command == MAKE_SCRIPT && argc > 1)
+               return !!sequencer_make_script(keep_empty, stdout, argc, argv);
+       if (command == SHORTEN_SHA1S && argc == 1)
+               return !!transform_todo_ids(1);
+       if (command == EXPAND_SHA1S && argc == 1)
+               return !!transform_todo_ids(0);
+       if (command == CHECK_TODO_LIST && argc == 1)
+               return !!check_todo_list();
+       if (command == SKIP_UNNECESSARY_PICKS && argc == 1)
+               return !!skip_unnecessary_picks();
+       if (command == REARRANGE_SQUASH && argc == 1)
+               return !!rearrange_squash();
        usage_with_options(builtin_rebase_helper_usage, options);
 }
index 52c63eb..cc48767 100644 (file)
@@ -743,7 +743,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,
                size_t n;
                if (feed(feed_state, &buf, &n))
                        break;
-               if (write_in_full(proc.in, buf, n) != n)
+               if (write_in_full(proc.in, buf, n) < 0)
                        break;
        }
        close(proc.in);
@@ -1207,11 +1207,10 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
        const char *dst_name;
        struct string_list_item *item;
        struct command *dst_cmd;
-       unsigned char sha1[GIT_MAX_RAWSZ];
        int flag;
 
        strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
-       dst_name = resolve_ref_unsafe(buf.buf, 0, sha1, &flag);
+       dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
        strbuf_release(&buf);
 
        if (!(flag & REF_ISSYMREF))
@@ -1459,7 +1458,6 @@ static void execute_commands(struct command *commands,
 {
        struct check_connected_options opt = CHECK_CONNECTED_INIT;
        struct command *cmd;
-       struct object_id oid;
        struct iterate_data data;
        struct async muxer;
        int err_fd = 0;
@@ -1516,7 +1514,7 @@ static void execute_commands(struct command *commands,
        check_aliased_updates(commands);
 
        free(head_name_to_free);
-       head_name = head_name_to_free = resolve_refdup("HEAD", 0, oid.hash, NULL);
+       head_name = head_name_to_free = resolve_refdup("HEAD", 0, NULL, NULL);
 
        if (use_atomic)
                execute_commands_atomic(commands, si);
index e237d92..2067cca 100644 (file)
@@ -126,7 +126,7 @@ static int commit_is_complete(struct commit *commit)
                struct commit *c;
                struct commit_list *parent;
 
-               c = (struct commit *)study.objects[--study.nr].item;
+               c = (struct commit *)object_array_pop(&study);
                if (!c->object.parsed && !parse_object(&c->object.oid))
                        c->object.flags |= INCOMPLETE;
 
@@ -182,8 +182,8 @@ static int commit_is_complete(struct commit *commit)
                        found.objects[i].item->flags |= SEEN;
        }
        /* free object arrays */
-       free(study.objects);
-       free(found.objects);
+       object_array_clear(&study);
+       object_array_clear(&found);
        return !is_incomplete;
 }
 
index bfb21ba..6a9127a 100644 (file)
@@ -57,7 +57,7 @@ static char *strip_escapes(const char *str, const char *service,
                                special = str[rpos];
                                if (rpos == 1)
                                        break;
-                               /* Fall-through to error. */
+                               /* fallthrough */
                        default:
                                die("Bad remote-ext placeholder '%%%c'.",
                                        str[rpos]);
index a995ea8..4f5cac9 100644 (file)
@@ -558,19 +558,19 @@ static int read_remote_branches(const char *refname,
        struct strbuf buf = STRBUF_INIT;
        struct string_list_item *item;
        int flag;
-       struct object_id orig_oid;
        const char *symref;
 
        strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
        if (starts_with(refname, buf.buf)) {
                item = string_list_append(rename->remote_branches, xstrdup(refname));
                symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING,
-                                           orig_oid.hash, &flag);
+                                           NULL, &flag);
                if (flag & REF_ISSYMREF)
                        item->util = xstrdup(symref);
                else
                        item->util = NULL;
        }
+       strbuf_release(&buf);
 
        return 0;
 }
@@ -595,6 +595,7 @@ static int migrate_file(struct remote *remote)
                unlink_or_warn(git_path("remotes/%s", remote->name));
        else if (remote->origin == REMOTE_BRANCHES)
                unlink_or_warn(git_path("branches/%s", remote->name));
+       strbuf_release(&buf);
 
        return 0;
 }
@@ -1563,9 +1564,7 @@ static int set_url(int argc, const char **argv)
                                                       "^$", 0);
                else
                        git_config_set(name_buf.buf, newurl);
-               strbuf_release(&name_buf);
-
-               return 0;
+               goto out;
        }
 
        /* Old URL specified. Demand that one matches. */
@@ -1588,6 +1587,8 @@ static int set_url(int argc, const char **argv)
                git_config_set_multivar(name_buf.buf, newurl, oldurl, 0);
        else
                git_config_set_multivar(name_buf.buf, NULL, oldurl, 1);
+out:
+       strbuf_release(&name_buf);
        return 0;
 }
 
index ffb66e2..0bc4029 100644 (file)
@@ -18,7 +18,7 @@ static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
 {
        int i;
        for (i = 0; i < nbuf; i++)
-               if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
+               if (write_in_full(1, ptr[i].ptr, ptr[i].size) < 0)
                        return -1;
        return 0;
 }
index d72c7d1..9cd89b2 100644 (file)
@@ -44,10 +44,11 @@ static inline int is_merge(void)
 
 static int reset_index(const struct object_id *oid, int reset_type, int quiet)
 {
-       int nr = 1;
+       int i, nr = 0;
        struct tree_desc desc[2];
        struct tree *tree;
        struct unpack_trees_options opts;
+       int ret = -1;
 
        memset(&opts, 0, sizeof(opts));
        opts.head_idx = 1;
@@ -75,23 +76,32 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet)
                struct object_id head_oid;
                if (get_oid("HEAD", &head_oid))
                        return error(_("You do not have a valid HEAD."));
-               if (!fill_tree_descriptor(desc, &head_oid))
+               if (!fill_tree_descriptor(desc + nr, &head_oid))
                        return error(_("Failed to find tree of HEAD."));
                nr++;
                opts.fn = twoway_merge;
        }
 
-       if (!fill_tree_descriptor(desc + nr - 1, oid))
-               return error(_("Failed to find tree of %s."), oid_to_hex(oid));
+       if (!fill_tree_descriptor(desc + nr, oid)) {
+               error(_("Failed to find tree of %s."), oid_to_hex(oid));
+               goto out;
+       }
+       nr++;
+
        if (unpack_trees(nr, desc, &opts))
-               return -1;
+               goto out;
 
        if (reset_type == MIXED || reset_type == HARD) {
                tree = parse_tree_indirect(oid);
                prime_cache_tree(&the_index, tree);
        }
 
-       return 0;
+       ret = 0;
+
+out:
+       for (i = 0; i < nr; i++)
+               free((void *)desc[i].buffer);
+       return ret;
 }
 
 static void print_new_head_line(struct commit *commit)
@@ -367,8 +377,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                die_if_unmerged_cache(reset_type);
 
        if (reset_type != SOFT) {
-               struct lock_file *lock = xcalloc(1, sizeof(*lock));
-               hold_locked_index(lock, LOCK_DIE_ON_ERROR);
+               struct lock_file lock = LOCK_INIT;
+               hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
                if (reset_type == MIXED) {
                        int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
                        if (read_from_tree(&pathspec, &oid, intent_to_add))
@@ -384,7 +394,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                                die(_("Could not reset index file to revision '%s'."), rev);
                }
 
-               if (write_locked_index(&the_index, lock, COMMIT_LOCK))
+               if (write_locked_index(&the_index, &lock, COMMIT_LOCK))
                        die(_("Could not write new index file."));
        }
 
index 2bd28d3..a8d7e6f 100644 (file)
@@ -387,6 +387,14 @@ static const char *skipspaces(const char *s)
        return s;
 }
 
+static char *findspace(const char *s)
+{
+       for (; *s; s++)
+               if (isspace(*s))
+                       return (char*)s;
+       return NULL;
+}
+
 static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 {
        static int keep_dashdash = 0, stop_at_non_option = 0;
@@ -434,7 +442,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
        /* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
        while (strbuf_getline(&sb, stdin) != EOF) {
                const char *s;
-               const char *help;
+               char *help;
                struct option *o;
 
                if (!sb.len)
@@ -444,15 +452,17 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
                memset(opts + onb, 0, sizeof(opts[onb]));
 
                o = &opts[onb++];
-               help = strchr(sb.buf, ' ');
-               if (!help || *sb.buf == ' ') {
+               help = findspace(sb.buf);
+               if (!help || sb.buf == help) {
                        o->type = OPTION_GROUP;
                        o->help = xstrdup(skipspaces(sb.buf));
                        continue;
                }
 
+               *help = '\0';
+
                o->type = OPTION_CALLBACK;
-               o->help = xstrdup(skipspaces(help));
+               o->help = xstrdup(skipspaces(help+1));
                o->value = &parsed;
                o->flags = PARSE_OPT_NOARG;
                o->callback = &parseopt_dump;
@@ -757,8 +767,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--bisect")) {
-                               for_each_ref_in("refs/bisect/bad", show_reference, NULL);
-                               for_each_ref_in("refs/bisect/good", anti_reference, NULL);
+                               for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0);
+                               for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0);
                                continue;
                        }
                        if (opt_with_value(arg, "--branches", &arg)) {
@@ -868,6 +878,11 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                                : "false");
                                continue;
                        }
+                       if (!strcmp(arg, "--is-shallow-repository")) {
+                               printf("%s\n", is_repository_shallow() ? "true"
+                                               : "false");
+                               continue;
+                       }
                        if (!strcmp(arg, "--shared-index-path")) {
                                if (read_cache() < 0)
                                        die(_("Could not read the index"));
index 43c4799..e29875b 100644 (file)
@@ -52,26 +52,8 @@ static void insert_one_record(struct shortlog *log,
                              const char *oneline)
 {
        struct string_list_item *item;
-       const char *mailbuf, *namebuf;
-       size_t namelen, maillen;
-       struct strbuf namemailbuf = STRBUF_INIT;
-       struct ident_split ident;
 
-       if (split_ident_line(&ident, author, strlen(author)))
-               return;
-
-       namebuf = ident.name_begin;
-       mailbuf = ident.mail_begin;
-       namelen = ident.name_end - ident.name_begin;
-       maillen = ident.mail_end - ident.mail_begin;
-
-       map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
-       strbuf_add(&namemailbuf, namebuf, namelen);
-
-       if (log->email)
-               strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
-
-       item = string_list_insert(&log->list, namemailbuf.buf);
+       item = string_list_insert(&log->list, author);
 
        if (log->summary)
                item->util = (void *)(UTIL_TO_INT(item) + 1);
@@ -114,9 +96,33 @@ static void insert_one_record(struct shortlog *log,
        }
 }
 
+static int parse_stdin_author(struct shortlog *log,
+                              struct strbuf *out, const char *in)
+{
+       const char *mailbuf, *namebuf;
+       size_t namelen, maillen;
+       struct ident_split ident;
+
+       if (split_ident_line(&ident, in, strlen(in)))
+               return -1;
+
+       namebuf = ident.name_begin;
+       mailbuf = ident.mail_begin;
+       namelen = ident.name_end - ident.name_begin;
+       maillen = ident.mail_end - ident.mail_begin;
+
+       map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
+       strbuf_add(out, namebuf, namelen);
+       if (log->email)
+               strbuf_addf(out, " <%.*s>", (int)maillen, mailbuf);
+
+       return 0;
+}
+
 static void read_from_stdin(struct shortlog *log)
 {
        struct strbuf author = STRBUF_INIT;
+       struct strbuf mapped_author = STRBUF_INIT;
        struct strbuf oneline = STRBUF_INIT;
        static const char *author_match[2] = { "Author: ", "author " };
        static const char *committer_match[2] = { "Commit: ", "committer " };
@@ -134,9 +140,15 @@ static void read_from_stdin(struct shortlog *log)
                while (strbuf_getline_lf(&oneline, stdin) != EOF &&
                       !oneline.len)
                        ; /* discard blanks */
-               insert_one_record(log, v, oneline.buf);
+
+               strbuf_reset(&mapped_author);
+               if (parse_stdin_author(log, &mapped_author, v) < 0)
+                       continue;
+
+               insert_one_record(log, mapped_author.buf, oneline.buf);
        }
        strbuf_release(&author);
+       strbuf_release(&mapped_author);
        strbuf_release(&oneline);
 }
 
@@ -153,7 +165,9 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
        ctx.date_mode.type = DATE_NORMAL;
        ctx.output_encoding = get_log_output_encoding();
 
-       fmt = log->committer ? "%cn <%ce>" : "%an <%ae>";
+       fmt = log->committer ?
+               (log->email ? "%cN <%cE>" : "%cN") :
+               (log->email ? "%aN <%aE>" : "%aN");
 
        format_commit_message(commit, fmt, &author, &ctx);
        if (!log->summary) {
index 84547d6..6fa1f62 100644 (file)
@@ -554,7 +554,7 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return git_default_config(var, value, cb);
+       return git_color_default_config(var, value, cb);
 }
 
 static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
index 818fe74..06ed02f 100644 (file)
@@ -17,9 +17,8 @@
 static char *get_default_remote(void)
 {
        char *dest = NULL, *ret;
-       unsigned char sha1[20];
        struct strbuf sb = STRBUF_INIT;
-       const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+       const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 
        if (!refname)
                die(_("No such ref: %s"), "HEAD");
@@ -1089,8 +1088,7 @@ static const char *remote_submodule_branch(const char *path)
                return "master";
 
        if (!strcmp(branch, ".")) {
-               unsigned char sha1[20];
-               const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+               const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 
                if (!refname)
                        die(_("No such ref: %s"), "HEAD");
@@ -1189,6 +1187,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
                                                break;
                                        die("HEAD does not match the named branch in the superproject");
                                }
+                               /* fallthrough */
                        default:
                                die("src refspec '%s' must name a ref",
                                    rs->src);
index df75cb9..17aabaa 100644 (file)
@@ -12,9 +12,8 @@ static const char * const git_symbolic_ref_usage[] = {
 
 static int check_symref(const char *HEAD, int quiet, int shorten, int print)
 {
-       unsigned char sha1[20];
        int flag;
-       const char *refname = resolve_ref_unsafe(HEAD, 0, sha1, &flag);
+       const char *refname = resolve_ref_unsafe(HEAD, 0, NULL, &flag);
 
        if (!refname)
                die("No such ref: %s", HEAD);
index c627794..b38329b 100644 (file)
@@ -158,7 +158,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)
 
        if (starts_with(var, "column."))
                return git_column_config(var, value, "tag", &colopts);
-       return git_default_config(var, value, cb);
+       return git_color_default_config(var, value, cb);
 }
 
 static void write_tag_body(int fd, const struct object_id *oid)
@@ -411,6 +411,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                },
                OPT_STRING(  0 , "format", &format.format, N_("format"),
                           N_("format to use for the output")),
+               OPT__COLOR(&format.use_color, N_("respect format colors")),
                OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
                OPT_END()
        };
@@ -552,9 +553,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        if (force && !is_null_oid(&prev) && oidcmp(&prev, &object))
                printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev.hash, DEFAULT_ABBREV));
 
-       strbuf_release(&err);
-       strbuf_release(&buf);
-       strbuf_release(&ref);
-       strbuf_release(&reflog_msg);
+       UNLEAK(buf);
+       UNLEAK(ref);
+       UNLEAK(reflog_msg);
+       UNLEAK(msg);
+       UNLEAK(err);
        return 0;
 }
index 281ca1d..32e0155 100644 (file)
@@ -15,7 +15,7 @@ static char *create_temp_file(struct object_id *oid)
 
        xsnprintf(path, sizeof(path), ".merge_file_XXXXXX");
        fd = xmkstemp(path);
-       if (write_in_full(fd, buf, size)