Merge branch 'jl/nor-or-nand-and'
authorJunio C Hamano <gitster@pobox.com>
Tue, 8 Apr 2014 19:00:27 +0000 (12:00 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 8 Apr 2014 19:00:28 +0000 (12:00 -0700)
Eradicate mistaken use of "nor" (that is, essentially "nor" used
not in "neither A nor B" ;-)) from in-code comments, command output
strings, and documentations.

* jl/nor-or-nand-and:
code and test: fix misuses of "nor"
comments: fix misuses of "nor"
contrib: fix misuses of "nor"
Documentation: fix misuses of "nor"

21 files changed:
1  2 
Documentation/CodingGuidelines
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-push.txt
Documentation/git-reset.txt
Documentation/rev-list-options.txt
Makefile
builtin/apply.c
builtin/checkout.c
builtin/clean.c
builtin/commit.c
builtin/pack-objects.c
diff.c
git-add--interactive.perl
git-am.sh
gitweb/gitweb.perl
http.h
remote.c
sha1_file.c
t/t7104-reset-hard.sh
t/t9400-git-cvsserver-server.sh
index ed432a80ca62eeb6a75e08870d9c8f8eaf4ab6d8,b99fa87f6853775c6c021de2fab1c320e5175561..dab5c61bfe4649e603e986d008c66b410038050b
@@@ -91,13 -91,13 +91,13 @@@ For shell scripts specifically (not exh
     E.g.: my_function () {
  
   - As to use of grep, stick to a subset of BRE (namely, no \{m,n\},
-    [::], [==], nor [..]) for portability.
+    [::], [==], or [..]) for portability.
  
     - We do not use \{m,n\};
  
     - We do not use -E;
  
-    - We do not use ? nor + (which are \{0,1\} and \{1,\}
+    - We do not use ? or + (which are \{0,1\} and \{1,\}
       respectively in BRE) but that goes without saying as these
       are ERE elements not BRE (note that \? and \+ are not even part
       of BRE -- making them accessible from BRE is a GNU extension).
@@@ -126,17 -126,6 +126,17 @@@ For C programs
     "char * string".  This makes it easier to understand code
     like "char *string, c;".
  
 + - Use whitespace around operators and keywords, but not inside
 +   parentheses and not around functions. So:
 +
 +        while (condition)
 +              func(bar + 1);
 +
 +   and not:
 +
 +        while( condition )
 +              func (bar+1);
 +
   - We avoid using braces unnecessarily.  I.e.
  
        if (bla) {
diff --combined Documentation/config.txt
index 84c7e3f11ae9b8b13815abc3b30db0489f493c30,c26a7c8469826c2650f03e310b8aa360e44c35c6..d8b6cc9654e24c6644986d60ca40eb6d264e6ca8
@@@ -78,8 -78,8 +78,8 @@@ be escaped: use `\"` for `"` and `\\` f
  
  The following escape sequences (beside `\"` and `\\`) are recognized:
  `\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)
- and `\b` for backspace (BS).  No other char escape sequence, nor octal
char sequences are valid.
+ and `\b` for backspace (BS).  Other char escape sequences (including octal
escape sequences) are invalid.
  
  Variable values ending in a `\` are continued on the next line in the
  customary UNIX fashion.
@@@ -131,13 -131,8 +131,13 @@@ Variable
  
  Note that this list is non-comprehensive and not necessarily complete.
  For command-specific variables, you will find a more detailed description
 -in the appropriate manual page. You will find a description of non-core
 -porcelain configuration variables in the respective porcelain documentation.
 +in the appropriate manual page.
 +
 +Other git-related tools may and do use their own variables.  When
 +inventing new variables for use in your own tool, make sure their
 +names do not conflict with those that are used by Git itself and
 +other popular tools, and describe them in your documentation.
 +
  
  advice.*::
        These variables control various optional help messages designed to
  --
        pushUpdateRejected::
                Set this variable to 'false' if you want to disable
 -              'pushNonFFCurrent', 'pushNonFFDefault',
 +              'pushNonFFCurrent',
                'pushNonFFMatching', 'pushAlreadyExists',
                'pushFetchFirst', and 'pushNeedsForce'
                simultaneously.
        pushNonFFCurrent::
                Advice shown when linkgit:git-push[1] fails due to a
                non-fast-forward update to the current branch.
 -      pushNonFFDefault::
 -              Advice to set 'push.default' to 'upstream' or 'current'
 -              when you ran linkgit:git-push[1] and pushed 'matching
 -              refs' by default (i.e. you did not provide an explicit
 -              refspec, and no 'push.default' configuration was set)
 -              and it resulted in a non-fast-forward error.
        pushNonFFMatching::
                Advice shown when you ran linkgit:git-push[1] and pushed
                'matching refs' explicitly (i.e. you used ':', or
@@@ -826,7 -827,7 +826,7 @@@ color.diff:
        commands will only use color when output is to the terminal.
        Defaults to false.
  +
- This does not affect linkgit:git-format-patch[1] nor the
+ This does not affect linkgit:git-format-patch[1] or the
  'git-diff-{asterisk}' plumbing commands.  Can be overridden on the
  command line with the `--color[=<when>]` option.
  
@@@ -991,14 -992,6 +991,14 @@@ commit.cleanup:
        have to remove the help lines that begin with `#` in the commit log
        template yourself, if you do this).
  
 +commit.gpgsign::
 +
 +      A boolean to specify whether all commits should be GPG signed.
 +      Use of this option when doing operations such as rebase can
 +      result in a large number of commits being signed. It may be
 +      convenient to use an agent to avoid typing your GPG passphrase
 +      several times.
 +
  commit.status::
        A boolean to enable/disable inclusion of status information in the
        commit message template when using an editor to prepare the commit
@@@ -1156,11 -1149,6 +1156,11 @@@ filter.<driver>.smudge:
        object to a worktree file upon checkout.  See
        linkgit:gitattributes[5] for details.
  
 +gc.aggressiveDepth::
 +      The depth parameter used in the delta compression
 +      algorithm used by 'git gc --aggressive'.  This defaults
 +      to 250.
 +
  gc.aggressiveWindow::
        The window size parameter used in the delta compression
        algorithm used by 'git gc --aggressive'.  This defaults
@@@ -1179,10 -1167,6 +1179,10 @@@ gc.autopacklimit:
        --auto` consolidates them into one larger pack.  The
        default value is 50.  Setting this to 0 disables it.
  
 +gc.autodetach::
 +      Make `git gc --auto` return immediately andrun in background
 +      if the system supports it. Default is true.
 +
  gc.packrefs::
        Running `git pack-refs` in a repository renders it
        unclonable by Git versions prior to 1.5.1.2 over dumb
@@@ -1617,10 -1601,6 +1617,10 @@@ imap:
        The configuration variables in the 'imap' section are described
        in linkgit:git-imap-send[1].
  
 +index.version::
 +      Specify the version with which new index files should be
 +      initialized.  This does not affect existing repositories.
 +
  init.templatedir::
        Specify the directory from which templates will be copied.
        (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
@@@ -1653,7 -1633,7 +1653,7 @@@ interactive.singlekey:
        linkgit:git-add[1], linkgit:git-checkout[1], linkgit:git-commit[1],
        linkgit:git-reset[1], and linkgit:git-stash[1]. Note that this
        setting is silently ignored if portable keystroke input
 -      is not available.
 +      is not available; requires the Perl module Term::ReadKey.
  
  log.abbrevCommit::
        If true, makes linkgit:git-log[1], linkgit:git-show[1], and
@@@ -1882,31 -1862,6 +1882,31 @@@ pack.packSizeLimit:
        Common unit suffixes of 'k', 'm', or 'g' are
        supported.
  
 +pack.useBitmaps::
 +      When true, git will use pack bitmaps (if available) when packing
 +      to stdout (e.g., during the server side of a fetch). Defaults to
 +      true. You should not generally need to turn this off unless
 +      you are debugging pack bitmaps.
 +
 +pack.writebitmaps::
 +      When true, git will write a bitmap index when packing all
 +      objects to disk (e.g., when `git repack -a` is run).  This
 +      index can speed up the "counting objects" phase of subsequent
 +      packs created for clones and fetches, at the cost of some disk
 +      space and extra time spent on the initial repack.  Defaults to
 +      false.
 +
 +pack.writeBitmapHashCache::
 +      When true, git will include a "hash cache" section in the bitmap
 +      index (if one is written). This cache can be used to feed git's
 +      delta heuristics, potentially leading to better deltas between
 +      bitmapped and non-bitmapped objects (e.g., when serving a fetch
 +      between an older, bitmapped pack and objects that have been
 +      pushed since the last gc). The downside is that it consumes 4
 +      bytes per object of disk space, and that JGit's bitmap
 +      implementation does not understand it, causing it to complain if
 +      Git and JGit are used on the same repository. Defaults to false.
 +
  pager.<cmd>::
        If the value is boolean, turns on or off pagination of the
        output of a particular Git subcommand when writing to a tty.
@@@ -1926,16 -1881,6 +1926,16 @@@ pretty.<name>:
        Note that an alias with the same name as a built-in format
        will be silently ignored.
  
 +pull.ff::
 +      By default, Git does not create an extra merge commit when merging
 +      a commit that is a descendant of the current commit. Instead, the
 +      tip of the current branch is fast-forwarded. When set to `false`,
 +      this variable tells Git to create an extra merge commit in such
 +      a case (equivalent to giving the `--no-ff` option from the command
 +      line). When set to `only`, only such fast-forward merges are
 +      allowed (equivalent to giving the `--ff-only` option from the
 +      command line).
 +
  pull.rebase::
        When true, rebase branches on top of the fetched branch, instead
        of merging the default branch from the default remote when "git
@@@ -1988,7 -1933,7 +1988,7 @@@ When pushing to a remote that is differ
  pull from, work as `current`.  This is the safest option and is suited
  for beginners.
  +
 -This mode will become the default in Git 2.0.
 +This mode has become the default in Git 2.0.
  
  * `matching` - push all branches having the same name on both ends.
    This makes the repository you are pushing to remember the set of
@@@ -2007,8 -1952,8 +2007,8 @@@ suitable for pushing into a shared cent
  people may add new branches there, or update the tip of existing
  branches outside your control.
  +
 -This is currently the default, but Git 2.0 will change the default
 -to `simple`.
 +This used to be the default, but not since Git 2.0 (`simple` is the
 +new default).
  
  --
  
@@@ -2166,13 -2111,6 +2166,13 @@@ repack.usedeltabaseoffset:
        "false" and repack. Access from old Git versions over the
        native protocol are unaffected by this option.
  
 +repack.packKeptObjects::
 +      If set to true, makes `git repack` act as if
 +      `--pack-kept-objects` was passed. See linkgit:git-repack[1] for
 +      details. Defaults to `false` normally, but `true` if a bitmap
 +      index is being written (either via `--write-bitmap-index` or
 +      `pack.writeBitmaps`).
 +
  rerere.autoupdate::
        When set to true, `git-rerere` updates the index with the
        resulting contents after it cleanly resolves conflicts using
@@@ -2353,13 -2291,6 +2353,13 @@@ transfer.unpackLimit:
        not set, the value of this variable is used instead.
        The default value is 100.
  
 +uploadarchive.allowUnreachable::
 +      If true, allow clients to use `git archive --remote` to request
 +      any tree, whether reachable from the ref tips or not. See the
 +      discussion in the `SECURITY` section of
 +      linkgit:git-upload-archive[1] for more details. Defaults to
 +      `false`.
 +
  uploadpack.hiderefs::
        String(s) `upload-pack` uses to decide which refs to omit
        from its initial advertisement.  Use more than one
index 895922e27cc4250d26818b4ca4ba42f1d2004fed,f3ab3748bc4311b44099ad650521adcb667085de..96315261102953b8f34694e0a793f023eea795f5
@@@ -53,14 -53,8 +53,14 @@@ OPTION
        Files to add content from.  Fileglobs (e.g. `*.c`) can
        be given to add all matching files.  Also a
        leading directory name (e.g. `dir` to add `dir/file1`
 -      and `dir/file2`) can be given to add all files in the
 -      directory, recursively.
 +      and `dir/file2`) can be given to update the index to
 +      match the current state of the directory as a whole (e.g.
 +      specifying `dir` will record not just a file `dir/file1`
 +      modified in the working tree, a file `dir/file2` added to
 +      the working tree, but also a file `dir/file3` removed from
 +      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.
  
  -n::
  --dry-run::
@@@ -110,10 -104,10 +110,10 @@@ apply to the index. See EDITING PATCHE
        <pathspec>.  This removes as well as modifies index entries to
        match the working tree, but adds no new files.
  +
 -If no <pathspec> is given, the current version of Git defaults to
 -"."; in other words, update all tracked files in the current directory
 -and its subdirectories. This default will change in a future version
 -of Git, hence the form without <pathspec> should not be used.
 +If no <pathspec> is given when `-u` option is used, all
 +tracked files in the entire working tree are updated (old versions
 +of Git used to limit the update to the current directory and its
 +subdirectories).
  
  -A::
  --all::
        entry.  This adds, modifies, and removes index entries to
        match the working tree.
  +
 -If no <pathspec> is given, the current version of Git defaults to
 -"."; in other words, update all files in the current directory
 -and its subdirectories. This default will change in a future version
 -of Git, hence the form without <pathspec> should not be used.
 +If no <pathspec> is given when `-A` option is used, all
 +files in the entire working tree are updated (old versions
 +of Git used to limit the update to the current directory and its
 +subdirectories).
  
  --no-all::
  --ignore-removal::
        files that have been removed from the working tree.  This
        option is a no-op when no <pathspec> is used.
  +
 -This option is primarily to help the current users of Git, whose
 -"git add <pathspec>..." ignores removed files.  In future versions
 -of Git, "git add <pathspec>..." will be a synonym to "git add -A
 -<pathspec>..." and "git add --ignore-removal <pathspec>..." will behave like
 -today's "git add <pathspec>...", ignoring removed files.
 +This option is primarily to help users who are used to older
 +versions of Git, whose "git add <pathspec>..." was a synonym
 +for "git add --no-all <pathspec>...", i.e. ignored removed files.
  
  -N::
  --intent-to-add::
@@@ -300,9 -296,9 +300,9 @@@ patch:
  
         y - stage this hunk
         n - do not stage this hunk
-        q - quit; do not stage this hunk nor any of the remaining ones
+        q - quit; do not stage this hunk or any of the remaining ones
         a - stage this hunk and all later hunks in the file
-        d - do not stage this hunk nor any of the later hunks in the file
+        d - do not stage this hunk or any of the later hunks in the file
         g - select a hunk to go to
         / - search for a hunk matching the given regex
         j - leave this hunk undecided, see next undecided hunk
index 14862fb203b8c269fc391eee886520b1675e540a,d0b9e2f235e5ec8e71f7d9b03f684db96fa50f30..21cd455508b85f943b45181286adeb2e0066e685
@@@ -83,8 -83,8 +83,8 @@@ the local side, the remote side is upda
  already exists on the remote side.
  
  --all::
 -      Instead of naming each ref to push, specifies that all
 -      refs under `refs/heads/` be pushed.
 +      Push all branches (i.e. refs under `refs/heads/`); cannot be
 +      used with other <refspec>.
  
  --prune::
        Remove remote branches that don't have a local counterpart. For example
@@@ -385,7 -385,7 +385,7 @@@ will now start building on top of B
  The command by default does not allow an update that is not a fast-forward
  to prevent such loss of history.
  
- If you do not want to lose your work (history from X to B) nor the work by
+ If you do not want to lose your work (history from X to B) or the work by
  the other person (history from X to A), you would need to first fetch the
  history from the repository, create a history that contains changes done
  by both parties, and push the result back.
@@@ -442,10 -442,8 +442,10 @@@ Example
        configured for the current branch).
  
  `git push origin`::
 -      Without additional configuration, works like
 -      `git push origin :`.
 +      Without additional configuration, pushes the current branch to
 +      the configured upstream (`remote.origin.merge` configuration
 +      variable) if it has the same name as the current branch, and
 +      errors out without pushing otherwise.
  +
  The default behavior of this command when no <refspec> is given can be
  configured by setting the `push` option of the remote, or the `push.default`
index a077ba0ddc81cf499d38f8b541406ac4583bcd1e,24bf4d55f97b44876e72db355dba301f93c9005c..25432d9257f9c06773edc8ca3d24ddae16bddf99
@@@ -10,7 -10,7 +10,7 @@@ SYNOPSI
  [verse]
  'git reset' [-q] [<tree-ish>] [--] <paths>...
  'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
 -'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]
 +'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
  
  DESCRIPTION
  -----------
@@@ -21,7 -21,7 +21,7 @@@ to HEAD in all forms
  
  'git reset' [-q] [<tree-ish>] [--] <paths>...::
        This form resets the index entries for all <paths> to their
-       state at <tree-ish>.  (It does not affect the working tree, nor
+       state at <tree-ish>.  (It does not affect the working tree or
        the current branch.)
  +
  This means that `git reset <paths>` is the opposite of `git add
@@@ -51,7 -51,7 +51,7 @@@ section of linkgit:git-add[1] to learn 
  +
  --
  --soft::
-       Does not touch the index file nor the working tree at all (but
+       Does not touch the index file or the working tree at all (but
        resets the head to <commit>, just like all modes do). This leaves
        all your changed files "Changes to be committed", as 'git status'
        would put it.
@@@ -60,9 -60,6 +60,9 @@@
        Resets the index but not the working tree (i.e., the changed files
        are preserved but not marked for commit) and reports what has not
        been updated. This is the default action.
 ++
 +If `-N` is specified, removed paths are marked as intent-to-add (see
 +linkgit:git-add[1]).
  
  --hard::
        Resets the index and working tree. Any changes to tracked files in the
@@@ -118,7 -115,7 +118,7 @@@ and changes with these files are distra
  <2> Somebody asks you to pull, and the changes sounds worthy of merging.
  <3> However, you already dirtied the index (i.e. your index does
  not match the HEAD commit).  But you know the pull you are going
- to make does not affect frotz.c nor filfre.c, so you revert the
+ to make does not affect frotz.c or filfre.c, so you revert the
  index changes for these two files.  Your changes in working tree
  remain there.
  <4> Then you can pull and merge, leaving frotz.c and filfre.c
index b8139610b9b22b49fa9427c57154408451b2d333,47c8dcca9d16031ff531118ebf4b8b6fe575e7ce..deb8cca9173ccbaf8c15ade3f8b3312fb6bdcbad
@@@ -237,7 -237,7 +237,7 @@@ list
        reflog entries from the most recent one to older ones.
        When this option is used you cannot specify commits to
        exclude (that is, '{caret}commit', 'commit1..commit2',
-       nor 'commit1\...commit2' notations cannot be used).
+       and 'commit1\...commit2' notations cannot be used).
  +
  With `--pretty` format other than `oneline` (for obvious reasons),
  this causes the output to have two extra lines of information
@@@ -257,14 -257,6 +257,14 @@@ See also linkgit:git-reflog[1]
        Output excluded boundary commits. Boundary commits are
        prefixed with `-`.
  
 +ifdef::git-rev-list[]
 +--use-bitmap-index::
 +
 +      Try to speed up the traversal using the pack bitmap index (if
 +      one is available). Note that when traversing with `--objects`,
 +      trees and blobs will not have their associated path printed.
 +endif::git-rev-list[]
 +
  --
  
  History Simplification
@@@ -758,13 -750,6 +758,13 @@@ This enables parent rewriting, see 'His
  This implies the `--topo-order` option by default, but the
  `--date-order` option may also be specified.
  
 +--show-linear-break[=<barrier>]::
 +      When --graph is not used, all history branches are flattened
 +      which can make it hard to see that the two consecutive commits
 +      do not belong to a linear branch. This option puts a barrier
 +      in between them in that case. If `<barrier>` is specified, it
 +      is the string that will be shown instead of the default one.
 +
  ifdef::git-rev-list[]
  --count::
        Print a number stating how many commits would have been
diff --combined Makefile
index f49f187516e52026388f95df6ec77e2612db7e86,fc02788184a690ecc1862109eeec2c02c0062b2f..2128ce3ea21a4801b9e85e0314a36d4c4dc39b4b
+++ b/Makefile
@@@ -59,9 -59,9 +59,9 @@@ all:
  # FreeBSD can use either, but MinGW and some others need to use
  # libcharset.h's locale_charset() instead.
  #
 -# Define CHARSET_LIB to you need to link with library other than -liconv to
 +# Define CHARSET_LIB to the library you need to link with in order to
  # use locale_charset() function.  On some platforms this needs to set to
 -# -lcharset
 +# -lcharset, on others to -liconv .
  #
  # Define LIBC_CONTAINS_LIBINTL if your gettext implementation doesn't
  # need -lintl when linking.
  #
  # Define NO_MKSTEMPS if you don't have mkstemps in the C library.
  #
 -# Define NO_FNMATCH if you don't have fnmatch in the C library.
 -#
 -# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
 -# FNM_CASEFOLD GNU extension.
 -#
 -# Define NO_WILDMATCH if you do not want to use Git's wildmatch
 -# implementation as fnmatch
 -#
  # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
  # in the C library.
  #
  #
  # Define NEEDS_LIBINTL_BEFORE_LIBICONV if you need libintl before libiconv.
  #
- # Define NO_INTPTR_T if you don't have intptr_t nor uintptr_t.
+ # Define NO_INTPTR_T if you don't have intptr_t or uintptr_t.
  #
  # Define NO_UINTMAX_T if you don't have uintmax_t.
  #
  # Define DEFAULT_HELP_FORMAT to "man", "info" or "html"
  # (defaults to "man") if you want to have a different default when
  # "git help" is called without a parameter specifying the format.
 +#
 +# Define TEST_GIT_INDEX_VERSION to 2, 3 or 4 to run the test suite
 +# with a different indexfile format version.  If it isn't set the index
 +# file format used is index-v[23].
 +#
 +# Define GMTIME_UNRELIABLE_ERRORS if your gmtime() function does not
 +# return NULL when it receives a bogus time_t.
  
  GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@@ -554,7 -555,6 +554,7 @@@ TEST_PROGRAMS_NEED_X += test-dat
  TEST_PROGRAMS_NEED_X += test-delta
  TEST_PROGRAMS_NEED_X += test-dump-cache-tree
  TEST_PROGRAMS_NEED_X += test-genrandom
 +TEST_PROGRAMS_NEED_X += test-hashmap
  TEST_PROGRAMS_NEED_X += test-index-version
  TEST_PROGRAMS_NEED_X += test-line-buffer
  TEST_PROGRAMS_NEED_X += test-match-trees
@@@ -663,8 -663,6 +663,8 @@@ LIB_H += diff.
  LIB_H += diffcore.h
  LIB_H += dir.h
  LIB_H += exec_cmd.h
 +LIB_H += ewah/ewok.h
 +LIB_H += ewah/ewok_rlw.h
  LIB_H += fetch-pack.h
  LIB_H += fmt-merge-msg.h
  LIB_H += fsck.h
@@@ -673,7 -671,7 +673,7 @@@ LIB_H += git-compat-util.
  LIB_H += gpg-interface.h
  LIB_H += graph.h
  LIB_H += grep.h
 -LIB_H += hash.h
 +LIB_H += hashmap.h
  LIB_H += help.h
  LIB_H += http.h
  LIB_H += kwset.h
@@@ -692,10 -690,8 +692,10 @@@ LIB_H += notes-merge.
  LIB_H += notes-utils.h
  LIB_H += notes.h
  LIB_H += object.h
 +LIB_H += pack-objects.h
  LIB_H += pack-revindex.h
  LIB_H += pack.h
 +LIB_H += pack-bitmap.h
  LIB_H += parse-options.h
  LIB_H += patch-ids.h
  LIB_H += pathspec.h
@@@ -799,10 -795,6 +799,10 @@@ LIB_OBJS += dir.
  LIB_OBJS += editor.o
  LIB_OBJS += entry.o
  LIB_OBJS += environment.o
 +LIB_OBJS += ewah/bitmap.o
 +LIB_OBJS += ewah/ewah_bitmap.o
 +LIB_OBJS += ewah/ewah_io.o
 +LIB_OBJS += ewah/ewah_rlw.o
  LIB_OBJS += exec_cmd.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -810,7 -802,7 +810,7 @@@ LIB_OBJS += gettext.
  LIB_OBJS += gpg-interface.o
  LIB_OBJS += graph.o
  LIB_OBJS += grep.o
 -LIB_OBJS += hash.o
 +LIB_OBJS += hashmap.o
  LIB_OBJS += help.o
  LIB_OBJS += hex.o
  LIB_OBJS += ident.o
@@@ -834,10 -826,7 +834,10 @@@ LIB_OBJS += notes-cache.
  LIB_OBJS += notes-merge.o
  LIB_OBJS += notes-utils.o
  LIB_OBJS += object.o
 +LIB_OBJS += pack-bitmap.o
 +LIB_OBJS += pack-bitmap-write.o
  LIB_OBJS += pack-check.o
 +LIB_OBJS += pack-objects.o
  LIB_OBJS += pack-revindex.o
  LIB_OBJS += pack-write.o
  LIB_OBJS += pager.o
@@@ -895,7 -884,6 +895,7 @@@ LIB_OBJS += userdiff.
  LIB_OBJS += utf8.o
  LIB_OBJS += varint.o
  LIB_OBJS += version.o
 +LIB_OBJS += versioncmp.o
  LIB_OBJS += walker.o
  LIB_OBJS += wildmatch.o
  LIB_OBJS += wrapper.o
@@@ -1283,6 -1271,20 +1283,6 @@@ endi
  ifdef NO_STRTOULL
        COMPAT_CFLAGS += -DNO_STRTOULL
  endif
 -ifdef NO_FNMATCH
 -      COMPAT_CFLAGS += -Icompat/fnmatch
 -      COMPAT_CFLAGS += -DNO_FNMATCH
 -      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 -else
 -ifdef NO_FNMATCH_CASEFOLD
 -      COMPAT_CFLAGS += -Icompat/fnmatch
 -      COMPAT_CFLAGS += -DNO_FNMATCH_CASEFOLD
 -      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 -endif
 -endif
 -ifndef NO_WILDMATCH
 -      COMPAT_CFLAGS += -DUSE_WILDMATCH
 -endif
  ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
@@@ -1492,11 -1494,6 +1492,11 @@@ ifneq (,$(XDL_FAST_HASH)
        BASIC_CFLAGS += -DXDL_FAST_HASH
  endif
  
 +ifdef GMTIME_UNRELIABLE_ERRORS
 +      COMPAT_OBJS += compat/gmtime.o
 +      BASIC_CFLAGS += -DGMTIME_UNRELIABLE_ERRORS
 +endif
 +
  ifeq ($(TCLTK_PATH),)
  NO_TCLTK = NoThanks
  endif
@@@ -2225,9 -2222,6 +2225,9 @@@ endi
  ifdef GIT_PERF_MAKE_OPTS
        @echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
  endif
 +ifdef TEST_GIT_INDEX_VERSION
 +      @echo TEST_GIT_INDEX_VERSION=\''$(subst ','\'',$(subst ','\'',$(TEST_GIT_INDEX_VERSION)))'\' >>$@
 +endif
  
  ### Detect Python interpreter path changes
  ifndef NO_PYTHON
@@@ -2485,9 -2479,8 +2485,9 @@@ profile-clean
        $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
  
  clean: profile-clean coverage-clean
 -      $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \
 -              builtin/*.o $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
 +      $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o
 +      $(RM) xdiff/*.o vcs-svn/*.o ewah/*.o builtin/*.o
 +      $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
        $(RM) -r bin-wrappers $(dep_dirs)
diff --combined builtin/apply.c
index 0189523798f31711ad74eaf3dd90ece9c12fa61a,6013e1913c05a57ed935a17504ebe079f46cc8ad..87439fad118a2671989120dd5993a17b4541e2db
@@@ -1943,7 -1943,13 +1943,7 @@@ static int parse_chunk(char *buffer, un
                                       size - offset - hdrsize, patch);
  
        if (!patchsize) {
 -              static const char *binhdr[] = {
 -                      "Binary files ",
 -                      "Files ",
 -                      NULL,
 -              };
                static const char git_binary[] = "GIT binary patch\n";
 -              int i;
                int hd = hdrsize + offset;
                unsigned long llen = linelen(buffer + hd, size - hd);
  
                                patchsize = 0;
                }
                else if (!memcmp(" differ\n", buffer + hd + llen - 8, 8)) {
 +                      static const char *binhdr[] = {
 +                              "Binary files ",
 +                              "Files ",
 +                              NULL,
 +                      };
 +                      int i;
                        for (i = 0; binhdr[i]; i++) {
                                int len = strlen(binhdr[i]);
                                if (len < size - hd &&
@@@ -4061,7 -4061,7 +4061,7 @@@ static int write_out_one_reject(struct 
                return error(_("cannot open %s: %s"), namebuf, strerror(errno));
  
        /* Normal git tools never deal with .rej, so do not pretend
-        * this is a git patch by saying --git nor give extended
+        * this is a git patch by saying --git or giving extended
         * headers.  While at it, maybe please "kompare" that wants
         * the trailing TAB and some garbage at the end of line ;-).
         */
@@@ -4152,7 -4152,7 +4152,7 @@@ static int use_patch(struct patch *p
        /* See if it matches any of exclude/include rule */
        for (i = 0; i < limit_by_name.nr; i++) {
                struct string_list_item *it = &limit_by_name.items[i];
 -              if (!fnmatch(it->string, pathname, 0))
 +              if (!wildmatch(it->string, pathname, 0, NULL))
                        return (it->util != NULL);
        }
  
diff --combined builtin/checkout.c
index 5b07757d4fca1950e293edf4a1183e5f79a72a2f,7f37d1a2453be5b318c9e9a746cddec78bc28fa7..07cf55530918e8de6ae45e1c9b7e16707c32f844
@@@ -53,10 -53,10 +53,10 @@@ struct checkout_opts 
  static int post_checkout_hook(struct commit *old, struct commit *new,
                              int changed)
  {
 -      return run_hook(NULL, "post-checkout",
 -                      sha1_to_hex(old ? old->object.sha1 : null_sha1),
 -                      sha1_to_hex(new ? new->object.sha1 : null_sha1),
 -                      changed ? "1" : "0", NULL);
 +      return run_hook_le(NULL, "post-checkout",
 +                         sha1_to_hex(old ? old->object.sha1 : null_sha1),
 +                         sha1_to_hex(new ? new->object.sha1 : null_sha1),
 +                         changed ? "1" : "0", NULL);
        /* "new" can be NULL when checking out from the index before
           a commit exists. */
  
@@@ -895,7 -895,7 +895,7 @@@ static int parse_branchname_arg(int arg
         *       between A and B, A...B names that merge base.
         *
         *   (b) If <something> is _not_ a commit, either "--" is present
-        *       or <something> is not a path, no -t nor -b was given, and
+        *       or <something> is not a path, no -t or -b was given, and
         *       and there is a tracking branch whose name is <something>
         *       in one and only one remote, then this is a short-hand to
         *       fork local <something> from that remote-tracking branch.
@@@ -1095,7 -1095,7 +1095,7 @@@ int cmd_checkout(int argc, const char *
                OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
                OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
                        BRANCH_TRACK_EXPLICIT),
 -              OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new branch"), N_("new unparented branch")),
 +              OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
                OPT_SET_INT('2', "ours", &opts.writeout_stage, N_("checkout our version for unmerged files"),
                            2),
                OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
diff --combined builtin/clean.c
index cf76b1f412e5423df42528c928c557764f31ad02,977a068f110a5ecfaeb3b680325f11a86be52251..9a9151575d3a8d4eb16d73e432835d3cda4374b8
@@@ -154,7 -154,7 +154,7 @@@ static int remove_dirs(struct strbuf *p
        DIR *dir;
        struct strbuf quoted = STRBUF_INIT;
        struct dirent *e;
 -      int res = 0, ret = 0, gone = 1, original_len = path->len, len, i;
 +      int res = 0, ret = 0, gone = 1, original_len = path->len, len;
        unsigned char submodule_head[20];
        struct string_list dels = STRING_LIST_INIT_DUP;
  
        }
  
        if (!*dir_gone && !quiet) {
 +              int i;
                for (i = 0; i < dels.nr; i++)
                        printf(dry_run ?  _(msg_would_remove) : _(msg_remove), dels.items[i].string);
        }
@@@ -904,11 -903,11 +904,11 @@@ int cmd_clean(int argc, const char **ar
  
        if (!interactive && !dry_run && !force) {
                if (config_set)
-                       die(_("clean.requireForce set to true and neither -i, -n nor -f given; "
+                       die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
                                  "refusing to clean"));
                else
-                       die(_("clean.requireForce defaults to true and neither -i, -n nor -f given; "
-                                 "refusing to clean"));
+                       die(_("clean.requireForce defaults to true and neither -i, -n, nor -f given;"
+                                 " refusing to clean"));
        }
  
        if (force > 1)
diff --combined builtin/commit.c
index 215b5bec192777b36953c76fa8b15c5b14a8a643,5d594a4743b9b6a7ac6bfac0fb41f4ae6025cf13..9cfef6c6cca61973a4982763e4b834bf1b45cb75
@@@ -113,7 -113,6 +113,7 @@@ static char *sign_commit
  static enum {
        CLEANUP_SPACE,
        CLEANUP_NONE,
 +      CLEANUP_SCISSORS,
        CLEANUP_ALL
  } cleanup_mode;
  static const char *cleanup_arg;
@@@ -308,6 -307,7 +308,6 @@@ static char *prepare_index(int argc, co
        int fd;
        struct string_list partial;
        struct pathspec pathspec;
 -      char *old_index_env = NULL;
        int refresh_flags = REFRESH_QUIET;
  
        if (is_status)
                die(_("index file corrupt"));
  
        if (interactive) {
 +              char *old_index_env = NULL;
                fd = hold_locked_index(&index_lock, 1);
  
                refresh_cache_or_die(refresh_flags);
@@@ -601,17 -600,19 +601,17 @@@ static int prepare_to_commit(const cha
  {
        struct stat statbuf;
        struct strbuf committer_ident = STRBUF_INIT;
 -      int commitable, saved_color_setting;
 +      int commitable;
        struct strbuf sb = STRBUF_INIT;
 -      char *buffer;
        const char *hook_arg1 = NULL;
        const char *hook_arg2 = NULL;
 -      int ident_shown = 0;
        int clean_message_contents = (cleanup_mode != CLEANUP_NONE);
        int old_display_comment_prefix;
  
        /* This checks and barfs if author is badly specified */
        determine_author_info(author_ident);
  
 -      if (!no_verify && run_hook(index_file, "pre-commit", NULL))
 +      if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
                return 0;
  
        if (squash_message) {
                                  logfile);
                hook_arg1 = "message";
        } else if (use_message) {
 +              char *buffer;
                buffer = strstr(use_message_buffer, "\n\n");
                if (!use_editor && (!buffer || buffer[2] == '\0'))
                        die(_("commit has empty message"));
        /* This checks if committer ident is explicitly given */
        strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT));
        if (use_editor && include_status) {
 +              int ident_shown = 0;
 +              int saved_color_setting;
                char *ai_tmp, *ci_tmp;
 -              if (whence != FROM_COMMIT)
 +              if (whence != FROM_COMMIT) {
 +                      if (cleanup_mode == CLEANUP_SCISSORS)
 +                              wt_status_add_cut_line(s->fp);
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                            whence == FROM_MERGE
                                ? _("\n"
                                git_path(whence == FROM_MERGE
                                         ? "MERGE_HEAD"
                                         : "CHERRY_PICK_HEAD"));
 +              }
  
                fprintf(s->fp, "\n");
                if (cleanup_mode == CLEANUP_ALL)
                                _("Please enter the commit message for your changes."
                                  " Lines starting\nwith '%c' will be ignored, and an empty"
                                  " message aborts the commit.\n"), comment_line_char);
 +              else if (cleanup_mode == CLEANUP_SCISSORS && whence == FROM_COMMIT)
 +                      wt_status_add_cut_line(s->fp);
                else /* CLEANUP_SPACE, that is. */
                        status_printf(s, GIT_COLOR_NORMAL,
                                _("Please enter the commit message for your changes."
                return 0;
        }
  
 -      if (run_hook(index_file, "prepare-commit-msg",
 -                   git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
 +      if (run_commit_hook(use_editor, index_file, "prepare-commit-msg",
 +                          git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
                return 0;
  
        if (use_editor) {
        }
  
        if (!no_verify &&
 -          run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
 +          run_commit_hook(use_editor, index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
                return 0;
        }
  
@@@ -1074,6 -1067,8 +1074,6 @@@ static int parse_and_validate_options(i
                use_editor = 0;
        if (0 <= edit_flag)
                use_editor = edit_flag;
 -      if (!use_editor)
 -              setenv("GIT_EDITOR", ":", 1);
  
        /* Sanity check options */
        if (amend && !current_head)
        if (argc == 0 && only && amend)
                only_include_assumed = _("Clever... amending the last one with dirty index.");
        if (argc > 0 && !also && !only)
-               only_include_assumed = _("Explicit paths specified without -i nor -o; assuming --only paths...");
+               only_include_assumed = _("Explicit paths specified without -i or -o; assuming --only paths...");
        if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
                cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "verbatim"))
                cleanup_mode = CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "strip"))
                cleanup_mode = CLEANUP_ALL;
 +      else if (!strcmp(cleanup_arg, "scissors"))
 +              cleanup_mode = use_editor ? CLEANUP_SCISSORS : CLEANUP_SPACE;
        else
                die(_("Invalid cleanup mode %s"), cleanup_arg);
  
@@@ -1413,10 -1406,6 +1413,10 @@@ static int git_commit_config(const cha
        }
        if (!strcmp(k, "commit.cleanup"))
                return git_config_string(&cleanup_arg, k, v);
 +      if (!strcmp(k, "commit.gpgsign")) {
 +              sign_commit = git_config_bool(k, v) ? "" : NULL;
 +              return 0;
 +      }
  
        status = git_gpg_config(k, v, NULL);
        if (status)
@@@ -1456,29 -1445,6 +1456,29 @@@ static int run_rewrite_hook(const unsig
        return finish_command(&proc);
  }
  
 +int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...)
 +{
 +      const char *hook_env[3] =  { NULL };
 +      char index[PATH_MAX];
 +      va_list args;
 +      int ret;
 +
 +      snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
 +      hook_env[0] = index;
 +
 +      /*
 +       * Let the hook know that no editor will be launched.
 +       */
 +      if (!editor_is_used)
 +              hook_env[1] = "GIT_EDITOR=:";
 +
 +      va_start(args, name);
 +      ret = run_hook_ve(hook_env, name, args);
 +      va_end(args);
 +
 +      return ret;
 +}
 +
  int cmd_commit(int argc, const char **argv, const char *prefix)
  {
        static struct wt_status s;
                OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
                OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")),
                OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
 -              { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
 +              { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
                  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
                /* end commit message options */
  
        struct ref_lock *ref_lock;
        struct commit_list *parents = NULL, **pptr = &parents;
        struct stat statbuf;
 -      int allow_fast_forward = 1;
        struct commit *current_head = NULL;
        struct commit_extra_header *extra = NULL;
  
        } else if (whence == FROM_MERGE) {
                struct strbuf m = STRBUF_INIT;
                FILE *fp;
 +              int allow_fast_forward = 1;
  
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
                die(_("could not read commit message: %s"), strerror(saved_errno));
        }
  
 -      /* Truncate the message just before the diff, if any. */
 -      if (verbose)
 +      if (verbose || /* Truncate the message just before the diff, if any. */
 +          cleanup_mode == CLEANUP_SCISSORS)
                wt_status_truncate_message_at_cut_line(&sb);
  
        if (cleanup_mode != CLEANUP_NONE)
                     "not exceeded, and then \"git reset HEAD\" to recover."));
  
        rerere(0);
 -      run_hook(get_index_file(), "post-commit", NULL);
 +      run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
        if (amend && !no_post_rewrite) {
                struct notes_rewrite_cfg *cfg;
                cfg = init_copy_notes_for_rewrite("amend");
diff --combined builtin/pack-objects.c
index 7950c4342f81544f719b20add2e1233be36fc718,ef1f20ea94ff9567d23f7cef5203020d9365d5bd..c1f43108710d950d44b783ce838d65e776c17a4d
  #include "diff.h"
  #include "revision.h"
  #include "list-objects.h"
 +#include "pack-objects.h"
  #include "progress.h"
  #include "refs.h"
  #include "streaming.h"
  #include "thread-utils.h"
 +#include "pack-bitmap.h"
  
  static const char *pack_usage[] = {
        N_("git pack-objects --stdout [options...] [< ref-list | < object-list]"),
        NULL
  };
  
 -struct object_entry {
 -      struct pack_idx_entry idx;
 -      unsigned long size;     /* uncompressed size */
 -      struct packed_git *in_pack;     /* already in pack */
 -      off_t in_pack_offset;
 -      struct object_entry *delta;     /* delta base object */
 -      struct object_entry *delta_child; /* deltified objects who bases me */
 -      struct object_entry *delta_sibling; /* other deltified objects who
 -                                           * uses the same base as me
 -                                           */
 -      void *delta_data;       /* cached delta (uncompressed) */
 -      unsigned long delta_size;       /* delta data size (uncompressed) */
 -      unsigned long z_delta_size;     /* delta data size (compressed) */
 -      enum object_type type;
 -      enum object_type in_pack_type;  /* could be delta */
 -      uint32_t hash;                  /* name hint hash */
 -      unsigned char in_pack_header_size;
 -      unsigned preferred_base:1; /*
 -                                  * we do not pack this, but is available
 -                                  * to be used as the base object to delta
 -                                  * objects against.
 -                                  */
 -      unsigned no_try_delta:1;
 -      unsigned tagged:1; /* near the very tip of refs */
 -      unsigned filled:1; /* assigned write-order */
 -};
 -
  /*
 - * Objects we are going to pack are collected in objects array (dynamically
 - * expanded).  nr_objects & nr_alloc controls this array.  They are stored
 - * in the order we see -- typically rev-list --objects order that gives us
 - * nice "minimum seek" order.
 + * Objects we are going to pack are collected in the `to_pack` structure.
 + * It contains an array (dynamically expanded) of the object data, and a map
 + * that can resolve SHA1s to their position in the array.
   */
 -static struct object_entry *objects;
 +static struct packing_data to_pack;
 +
  static struct pack_idx_entry **written_list;
 -static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
 +static uint32_t nr_result, nr_written;
  
  static int non_empty;
  static int reuse_delta = 1, reuse_object = 1;
@@@ -58,43 -83,27 +58,43 @@@ static struct progress *progress_state
  static int pack_compression_level = Z_DEFAULT_COMPRESSION;
  static int pack_compression_seen;
  
 +static struct packed_git *reuse_packfile;
 +static uint32_t reuse_packfile_objects;
 +static off_t reuse_packfile_offset;
 +
 +static int use_bitmap_index = 1;
 +static int write_bitmap_index;
 +static uint16_t write_bitmap_options;
 +
  static unsigned long delta_cache_size = 0;
  static unsigned long max_delta_cache_size = 256 * 1024 * 1024;
  static unsigned long cache_max_small_delta_size = 1000;
  
  static unsigned long window_memory_limit = 0;
  
 -/*
 - * The object names in objects array are hashed with this hashtable,
 - * to help looking up the entry by object name.
 - * This hashtable is built after all the objects are seen.
 - */
 -static int *object_ix;
 -static int object_ix_hashsz;
 -static struct object_entry *locate_object_entry(const unsigned char *sha1);
 -
  /*
   * stats
   */
  static uint32_t written, written_delta;
  static uint32_t reused, reused_delta;
  
 +/*
 + * Indexed commits
 + */
 +static struct commit **indexed_commits;
 +static unsigned int indexed_commits_nr;
 +static unsigned int indexed_commits_alloc;
 +
 +static void index_commit_for_bitmap(struct commit *commit)
 +{
 +      if (indexed_commits_nr >= indexed_commits_alloc) {
 +              indexed_commits_alloc = (indexed_commits_alloc + 32) * 2;
 +              indexed_commits = xrealloc(indexed_commits,
 +                      indexed_commits_alloc * sizeof(struct commit *));
 +      }
 +
 +      indexed_commits[indexed_commits_nr++] = commit;
 +}
  
  static void *get_delta(struct object_entry *entry)
  {
@@@ -544,12 -553,12 +544,12 @@@ static int mark_tagged(const char *path
                       void *cb_data)
  {
        unsigned char peeled[20];
 -      struct object_entry *entry = locate_object_entry(sha1);
 +      struct object_entry *entry = packlist_find(&to_pack, sha1, NULL);
  
        if (entry)
                entry->tagged = 1;
        if (!peel_ref(path, peeled)) {
 -              entry = locate_object_entry(peeled);
 +              entry = packlist_find(&to_pack, peeled, NULL);
                if (entry)
                        entry->tagged = 1;
        }
@@@ -624,10 -633,9 +624,10 @@@ static struct object_entry **compute_wr
  {
        unsigned int i, wo_end, last_untagged;
  
 -      struct object_entry **wo = xmalloc(nr_objects * sizeof(*wo));
 +      struct object_entry **wo = xmalloc(to_pack.nr_objects * sizeof(*wo));
 +      struct object_entry *objects = to_pack.objects;
  
 -      for (i = 0; i < nr_objects; i++) {
 +      for (i = 0; i < to_pack.nr_objects; i++) {
                objects[i].tagged = 0;
                objects[i].filled = 0;
                objects[i].delta_child = NULL;
         * Make sure delta_sibling is sorted in the original
         * recency order.
         */
 -      for (i = nr_objects; i > 0;) {
 +      for (i = to_pack.nr_objects; i > 0;) {
                struct object_entry *e = &objects[--i];
                if (!e->delta)
                        continue;
         * Give the objects in the original recency order until
         * we see a tagged tip.
         */
 -      for (i = wo_end = 0; i < nr_objects; i++) {
 +      for (i = wo_end = 0; i < to_pack.nr_objects; i++) {
                if (objects[i].tagged)
                        break;
                add_to_write_order(wo, &wo_end, &objects[i]);
        /*
         * Then fill all the tagged tips.
         */
 -      for (; i < nr_objects; i++) {
 +      for (; i < to_pack.nr_objects; i++) {
                if (objects[i].tagged)
                        add_to_write_order(wo, &wo_end, &objects[i]);
        }
        /*
         * And then all remaining commits and tags.
         */
 -      for (i = last_untagged; i < nr_objects; i++) {
 +      for (i = last_untagged; i < to_pack.nr_objects; i++) {
                if (objects[i].type != OBJ_COMMIT &&
                    objects[i].type != OBJ_TAG)
                        continue;
        /*
         * And then all the trees.
         */
 -      for (i = last_untagged; i < nr_objects; i++) {
 +      for (i = last_untagged; i < to_pack.nr_objects; i++) {
                if (objects[i].type != OBJ_TREE)
                        continue;
                add_to_write_order(wo, &wo_end, &objects[i]);
        /*
         * Finally all the rest in really tight order
         */
 -      for (i = last_untagged; i < nr_objects; i++) {
 +      for (i = last_untagged; i < to_pack.nr_objects; i++) {
                if (!objects[i].filled)
                        add_family_to_write_order(wo, &wo_end, &objects[i]);
        }
  
 -      if (wo_end != nr_objects)
 -              die("ordered %u objects, expected %"PRIu32, wo_end, nr_objects);
 +      if (wo_end != to_pack.nr_objects)
 +              die("ordered %u objects, expected %"PRIu32, wo_end, to_pack.nr_objects);
  
        return wo;
  }
  
 +static off_t write_reused_pack(struct sha1file *f)
 +{
 +      unsigned char buffer[8192];
 +      off_t to_write, total;
 +      int fd;
 +
 +      if (!is_pack_valid(reuse_packfile))
 +              die("packfile is invalid: %s", reuse_packfile->pack_name);
 +
 +      fd = git_open_noatime(reuse_packfile->pack_name);
 +      if (fd < 0)
 +              die_errno("unable to open packfile for reuse: %s",
 +                        reuse_packfile->pack_name);
 +
 +      if (lseek(fd, sizeof(struct pack_header), SEEK_SET) == -1)
 +              die_errno("unable to seek in reused packfile");
 +
 +      if (reuse_packfile_offset < 0)
 +              reuse_packfile_offset = reuse_packfile->pack_size - 20;
 +
 +      total = to_write = reuse_packfile_offset - sizeof(struct pack_header);
 +
 +      while (to_write) {
 +              int read_pack = xread(fd, buffer, sizeof(buffer));
 +
 +              if (read_pack <= 0)
 +                      die_errno("unable to read from reused packfile");
 +
 +              if (read_pack > to_write)
 +                      read_pack = to_write;
 +
 +              sha1write(f, buffer, read_pack);
 +              to_write -= read_pack;
 +
 +              /*
 +               * We don't know the actual number of objects written,
 +               * only how many bytes written, how many bytes total, and
 +               * how many objects total. So we can fake it by pretending all
 +               * objects we are writing are the same size. This gives us a
 +               * smooth progress meter, and at the end it matches the true
 +               * answer.
 +               */
 +              written = reuse_packfile_objects *
 +                              (((double)(total - to_write)) / total);
 +              display_progress(progress_state, written);
 +      }
 +
 +      close(fd);
 +      written = reuse_packfile_objects;
 +      display_progress(progress_state, written);
 +      return reuse_packfile_offset - sizeof(struct pack_header);
 +}
 +
  static void write_pack_file(void)
  {
        uint32_t i = 0, j;
        struct object_entry **write_order;
  
        if (progress > pack_to_stdout)
 -              progress_state = start_progress("Writing objects", nr_result);
 -      written_list = xmalloc(nr_objects * sizeof(*written_list));
 +              progress_state = start_progress(_("Writing objects"), nr_result);
 +      written_list = xmalloc(to_pack.nr_objects * sizeof(*written_list));
        write_order = compute_write_order();
  
        do {
                        f = create_tmp_packfile(&pack_tmp_name);
  
                offset = write_pack_header(f, nr_remaining);
 +
 +              if (reuse_packfile) {
 +                      off_t packfile_size;
 +                      assert(pack_to_stdout);
 +
 +                      packfile_size = write_reused_pack(f);
 +                      offset += packfile_size;
 +              }
 +
                nr_written = 0;
 -              for (; i < nr_objects; i++) {
 +              for (; i < to_pack.nr_objects; i++) {
                        struct object_entry *e = write_order[i];
                        if (write_one(f, e, &offset) == WRITE_ONE_BREAK)
                                break;
  
                if (!pack_to_stdout) {
                        struct stat st;
 -                      char tmpname[PATH_MAX];
 +                      struct strbuf tmpname = STRBUF_INIT;
  
                        /*
                         * Packs are runtime accessed in their mtime
                                utb.modtime = --last_mtime;
                                if (utime(pack_tmp_name, &utb) < 0)
                                        warning("failed utime() on %s: %s",
 -                                              tmpname, strerror(errno));
 +                                              pack_tmp_name, strerror(errno));
                        }
  
 -                      /* Enough space for "-<sha-1>.pack"? */
 -                      if (sizeof(tmpname) <= strlen(base_name) + 50)
 -                              die("pack base name '%s' too long", base_name);
 -                      snprintf(tmpname, sizeof(tmpname), "%s-", base_name);
 -                      finish_tmp_packfile(tmpname, pack_tmp_name,
 +                      strbuf_addf(&tmpname, "%s-", base_name);
 +
 +                      if (write_bitmap_index) {
 +                              bitmap_writer_set_checksum(sha1);
 +                              bitmap_writer_build_type_index(written_list, nr_written);
 +                      }
 +
 +                      finish_tmp_packfile(&tmpname, pack_tmp_name,
                                            written_list, nr_written,
                                            &pack_idx_opts, sha1);
 +
 +                      if (write_bitmap_index) {
 +                              strbuf_addf(&tmpname, "%s.bitmap", sha1_to_hex(sha1));
 +
 +                              stop_progress(&progress_state);
 +
 +                              bitmap_writer_show_progress(progress);
 +                              bitmap_writer_reuse_bitmaps(&to_pack);
 +                              bitmap_writer_select_commits(indexed_commits, indexed_commits_nr, -1);
 +                              bitmap_writer_build(&to_pack);
 +                              bitmap_writer_finish(written_list, nr_written,
 +                                                   tmpname.buf, write_bitmap_options);
 +                              write_bitmap_index = 0;
 +                      }
 +
 +                      strbuf_release(&tmpname);
                        free(pack_tmp_name);
                        puts(sha1_to_hex(sha1));
                }
                        written_list[j]->offset = (off_t)-1;
                }
                nr_remaining -= nr_written;
 -      } while (nr_remaining && i < nr_objects);
 +      } while (nr_remaining && i < to_pack.nr_objects);
  
        free(written_list);
        free(write_order);
                        written, nr_result);
  }
  
 -static int locate_object_entry_hash(const unsigned char *sha1)
 -{
 -      int i;
 -      unsigned int ui;
 -      memcpy(&ui, sha1, sizeof(unsigned int));
 -      i = ui % object_ix_hashsz;
 -      while (0 < object_ix[i]) {
 -              if (!hashcmp(sha1, objects[object_ix[i] - 1].idx.sha1))
 -                      return i;
 -              if (++i == object_ix_hashsz)
 -                      i = 0;
 -      }
 -      return -1 - i;
 -}
 -
 -static struct object_entry *locate_object_entry(const unsigned char *sha1)
 -{
 -      int i;
 -
 -      if (!object_ix_hashsz)
 -              return NULL;
 -
 -      i = locate_object_entry_hash(sha1);
 -      if (0 <= i)
 -              return &objects[object_ix[i]-1];
 -      return NULL;
 -}
 -
 -static void rehash_objects(void)
 -{
 -      uint32_t i;
 -      struct object_entry *oe;
 -
 -      object_ix_hashsz = nr_objects * 3;
 -      if (object_ix_hashsz < 1024)
 -              object_ix_hashsz = 1024;
 -      object_ix = xrealloc(object_ix, sizeof(int) * object_ix_hashsz);
 -      memset(object_ix, 0, sizeof(int) * object_ix_hashsz);
 -      for (i = 0, oe = objects; i < nr_objects; i++, oe++) {
 -              int ix = locate_object_entry_hash(oe->idx.sha1);
 -              if (0 <= ix)
 -                      continue;
 -              ix = -1 - ix;
 -              object_ix[ix] = i + 1;
 -      }
 -}
 -
 -static uint32_t name_hash(const char *name)
 -{
 -      uint32_t c, hash = 0;
 -
 -      if (!name)
 -              return 0;
 -
 -      /*
 -       * This effectively just creates a sortable number from the
 -       * last sixteen non-whitespace characters. Last characters
 -       * count "most", so things that end in ".c" sort together.
 -       */
 -      while ((c = *name++) != 0) {
 -              if (isspace(c))
 -                      continue;
 -              hash = (hash >> 2) + (c << 24);
 -      }
 -      return hash;
 -}
 -
  static void setup_delta_attr_check(struct git_attr_check *check)
  {
        static struct git_attr *attr_delta;
@@@ -906,69 -900,42 +906,69 @@@ static int no_try_delta(const char *pat
        return 0;
  }
  
 -static int add_object_entry(const unsigned char *sha1, enum object_type type,
 -                          const char *name, int exclude)
 +/*
 + * When adding an object, check whether we have already added it
 + * to our packing list. If so, we can skip. However, if we are
 + * being asked to excludei t, but the previous mention was to include
 + * it, make sure to adjust its flags and tweak our numbers accordingly.
 + *
 + * As an optimization, we pass out the index position where we would have
 + * found the item, since that saves us from having to look it up again a
 + * few lines later when we want to add the new entry.
 + */
 +static int have_duplicate_entry(const unsigned char *sha1,
 +                              int exclude,
 +                              uint32_t *index_pos)
  {
        struct object_entry *entry;
 -      struct packed_git *p, *found_pack = NULL;
 -      off_t found_offset = 0;
 -      int ix;
 -      uint32_t hash = name_hash(name);
 -
 -      ix = nr_objects ? locate_object_entry_hash(sha1) : -1;
 -      if (ix >= 0) {
 -              if (exclude) {
 -                      entry = objects + object_ix[ix] - 1;
 -                      if (!entry->preferred_base)
 -                              nr_result--;
 -                      entry->preferred_base = 1;
 -              }
 +
 +      entry = packlist_find(&to_pack, sha1, index_pos);
 +      if (!entry)
                return 0;
 +
 +      if (exclude) {
 +              if (!entry->preferred_base)
 +                      nr_result--;
 +              entry->preferred_base = 1;
        }
  
 +      return 1;
 +}
 +
 +/*
 + * Check whether we want the object in the pack (e.g., we do not want
 + * objects found in non-local stores if the "--local" option was used).
 + *
 + * As a side effect of this check, we will find the packed version of this
 + * object, if any. We therefore pass out the pack information to avoid having
 + * to look it up again later.
 + */
 +static int want_object_in_pack(const unsigned char *sha1,
 +                             int exclude,
 +                             struct packed_git **found_pack,
 +                             off_t *found_offset)
 +{
 +      struct packed_git *p;
 +
        if (!exclude && local && has_loose_object_nonlocal(sha1))
                return 0;
  
 +      *found_pack = NULL;
 +      *found_offset = 0;
 +
        for (p = packed_git; p; p = p->next) {
                off_t offset = find_pack_entry_one(sha1, p);
                if (offset) {
 -                      if (!found_pack) {
 +                      if (!*found_pack) {
                                if (!is_pack_valid(p)) {
                                        warning("packfile %s cannot be accessed", p->pack_name);
                                        continue;
                                }
 -                              found_offset = offset;
 -                              found_pack = p;
 +                              *found_offset = offset;
 +                              *found_pack = p;
                        }
                        if (exclude)
 -                              break;
 +                              return 1;
                        if (incremental)
                                return 0;
                        if (local && !p->pack_local)
                }
        }
  
 -      if (nr_objects >= nr_alloc) {
 -              nr_alloc = (nr_alloc  + 1024) * 3 / 2;
 -              objects = xrealloc(objects, nr_alloc * sizeof(*entry));
 -      }
 +      return 1;
 +}
 +
 +static void create_object_entry(const unsigned char *sha1,
 +                              enum object_type type,
 +                              uint32_t hash,
 +                              int exclude,
 +                              int no_try_delta,
 +                              uint32_t index_pos,
 +                              struct packed_git *found_pack,
 +                              off_t found_offset)
 +{
 +      struct object_entry *entry;
  
 -      entry = objects + nr_objects++;
 -      memset(entry, 0, sizeof(*entry));
 -      hashcpy(entry->idx.sha1, sha1);
 +      entry = packlist_alloc(&to_pack, sha1, index_pos);
        entry->hash = hash;
        if (type)
                entry->type = type;
                entry->in_pack_offset = found_offset;
        }
  
 -      if (object_ix_hashsz * 3 <= nr_objects * 4)
 -              rehash_objects();
 -      else
 -              object_ix[-1 - ix] = nr_objects;
 +      entry->no_try_delta = no_try_delta;
 +}
 +
 +static const char no_closure_warning[] = N_(
 +"disabling bitmap writing, as some objects are not being packed"
 +);
 +
 +static int add_object_entry(const unsigned char *sha1, enum object_type type,
 +                          const char *name, int exclude)
 +{
 +      struct packed_git *found_pack;
 +      off_t found_offset;
 +      uint32_t index_pos;
 +
 +      if (have_duplicate_entry(sha1, exclude, &index_pos))
 +              return 0;
 +
 +      if (!want_object_in_pack(sha1, exclude, &found_pack, &found_offset)) {
 +              /* The pack is missing an object, so it will not have closure */
 +              if (write_bitmap_index) {
 +                      warning(_(no_closure_warning));
 +                      write_bitmap_index = 0;
 +              }
 +              return 0;
 +      }
 +
 +      create_object_entry(sha1, type, pack_name_hash(name),
 +                          exclude, name && no_try_delta(name),
 +                          index_pos, found_pack, found_offset);
 +
 +      display_progress(progress_state, nr_result);
 +      return 1;
 +}
  
 -      display_progress(progress_state, nr_objects);
 +static int add_object_entry_from_bitmap(const unsigned char *sha1,
 +                                      enum object_type type,
 +                                      int flags, uint32_t name_hash,
 +                                      struct packed_git *pack, off_t offset)
 +{
 +      uint32_t index_pos;
 +
 +      if (have_duplicate_entry(sha1, 0, &index_pos))
 +              return 0;
  
 -      if (name && no_try_delta(name))
 -              entry->no_try_delta = 1;
 +      create_object_entry(sha1, type, name_hash, 0, 0, index_pos, pack, offset);
  
 +      display_progress(progress_state, nr_result);
        return 1;
  }
  
@@@ -1076,7 -999,7 +1076,7 @@@ static int pbase_tree_cache_ix_incr(in
  static struct pbase_tree {
        struct pbase_tree *next;
        /* This is a phony "cache" entry; we are not
-        * going to evict it nor find it through _get()
+        * going to evict it or find it through _get()
         * mechanism -- this is for the toplevel node that
         * would almost always change with any commit.
         */
@@@ -1233,9 -1156,12 +1233,9 @@@ static int check_pbase_path(unsigned ha
        if (0 <= pos)
                return 1;
        pos = -pos - 1;
 -      if (done_pbase_paths_alloc <= done_pbase_paths_num) {
 -              done_pbase_paths_alloc = alloc_nr(done_pbase_paths_alloc);
 -              done_pbase_paths = xrealloc(done_pbase_paths,
 -                                          done_pbase_paths_alloc *
 -                                          sizeof(unsigned));
 -      }
 +      ALLOC_GROW(done_pbase_paths,
 +                 done_pbase_paths_num + 1,
 +                 done_pbase_paths_alloc);
        done_pbase_paths_num++;
        if (pos < done_pbase_paths_num)
                memmove(done_pbase_paths + pos + 1,
@@@ -1249,7 -1175,7 +1249,7 @@@ static void add_preferred_base_object(c
  {
        struct pbase_tree *it;
        int cmplen;
 -      unsigned hash = name_hash(name);
 +      unsigned hash = pack_name_hash(name);
  
        if (!num_preferred_base || check_pbase_path(hash))
                return;
@@@ -1401,7 -1327,7 +1401,7 @@@ static void check_object(struct object_
                        break;
                }
  
 -              if (base_ref && (base_entry = locate_object_entry(base_ref))) {
 +              if (base_ref && (base_entry = packlist_find(&to_pack, base_ref, NULL))) {
                        /*
                         * If base_ref was set above that means we wish to
                         * reuse delta data, and we even found that base
@@@ -1475,12 -1401,12 +1475,12 @@@ static void get_object_details(void
        uint32_t i;
        struct object_entry **sorted_by_offset;
  
 -      sorted_by_offset = xcalloc(nr_objects, sizeof(struct object_entry *));
 -      for (i = 0; i < nr_objects; i++)
 -              sorted_by_offset[i] = objects + i;
 -      qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
 +      sorted_by_offset = xcalloc(to_pack.nr_objects, sizeof(struct object_entry *));
 +      for (i = 0; i < to_pack.nr_objects; i++)
 +              sorted_by_offset[i] = to_pack.objects + i;
 +      qsort(sorted_by_offset, to_pack.nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
  
 -      for (i = 0; i < nr_objects; i++) {
 +      for (i = 0; i < to_pack.nr_objects; i++) {
                struct object_entry *entry = sorted_by_offset[i];
                check_object(entry);
                if (big_file_threshold < entry->size)
@@@ -2106,7 -2032,7 +2106,7 @@@ static int add_ref_tag(const char *path
  
        if (starts_with(path, "refs/tags/") && /* is a tag? */
            !peel_ref(path, peeled)        && /* peelable? */
 -          locate_object_entry(peeled))      /* object packed? */
 +          packlist_find(&to_pack, peeled, NULL))      /* object packed? */
                add_object_entry(sha1, OBJ_TAG, NULL, 0);
        return 0;
  }
@@@ -2129,14 -2055,14 +2129,14 @@@ static void prepare_pack(int window, in
        if (!pack_to_stdout)
                do_check_packed_object_crc = 1;
  
 -      if (!nr_objects || !window || !depth)
 +      if (!to_pack.nr_objects || !window || !depth)
                return;
  
 -      delta_list = xmalloc(nr_objects * sizeof(*delta_list));
 +      delta_list = xmalloc(to_pack.nr_objects * sizeof(*delta_list));
        nr_deltas = n = 0;
  
 -      for (i = 0; i < nr_objects; i++) {
 -              struct object_entry *entry = objects + i;
 +      for (i = 0; i < to_pack.nr_objects; i++) {
 +              struct object_entry *entry = to_pack.objects + i;
  
                if (entry->delta)
                        /* This happens if we decided to reuse existing
        if (nr_deltas && n > 1) {
                unsigned nr_done = 0;
                if (progress)
 -                      progress_state = start_progress("Compressing objects",
 +                      progress_state = start_progress(_("Compressing objects"),
                                                        nr_deltas);
                qsort(delta_list, n, sizeof(*delta_list), type_size_sort);
                ll_find_deltas(delta_list, n, window+1, depth, &nr_done);
@@@ -2214,20 -2140,6 +2214,20 @@@ static int git_pack_config(const char *
                cache_max_small_delta_size = git_config_int(k, v);
                return 0;
        }
 +      if (!strcmp(k, "pack.writebitmaps")) {
 +              write_bitmap_index = git_config_bool(k, v);
 +              return 0;
 +      }
 +      if (!strcmp(k, "pack.writebitmaphashcache")) {
 +              if (git_config_bool(k, v))
 +                      write_bitmap_options |= BITMAP_OPT_HASH_CACHE;
 +              else
 +                      write_bitmap_options &= ~BITMAP_OPT_HASH_CACHE;
 +      }
 +      if (!strcmp(k, "pack.usebitmaps")) {
 +              use_bitmap_index = git_config_bool(k, v);
 +              return 0;
 +      }
        if (!strcmp(k, "pack.threads")) {
                delta_search_threads = git_config_int(k, v);
                if (delta_search_threads < 0)
@@@ -2286,9 -2198,6 +2286,9 @@@ static void show_commit(struct commit *
  {
        add_object_entry(commit->object.sha1, OBJ_COMMIT, NULL, 0);
        commit->object.flags |= OBJECT_ADDED;
 +
 +      if (write_bitmap_index)
 +              index_commit_for_bitmap(commit);
  }
  
  static void show_object(struct object *obj,
@@@ -2431,7 -2340,7 +2431,7 @@@ static void loosen_unused_packed_object
  
                for (i = 0; i < p->num_objects; i++) {
                        sha1 = nth_packed_object_sha1(p, i);
 -                      if (!locate_object_entry(sha1) &&
 +                      if (!packlist_find(&to_pack, sha1, NULL) &&
                                !has_sha1_pack_kept_or_nonlocal(sha1))
                                if (force_object_loose(sha1, p->mtime))
                                        die("unable to force loose object");
        }
  }
  
 +static int get_object_list_from_bitmap(struct rev_info *revs)
 +{
 +      if (prepare_bitmap_walk(revs) < 0)
 +              return -1;
 +
 +      if (!reuse_partial_packfile_from_bitmap(
 +                      &reuse_packfile,
 +                      &reuse_packfile_objects,
 +                      &reuse_packfile_offset)) {
 +              assert(reuse_packfile_objects);
 +              nr_result += reuse_packfile_objects;
 +              display_progress(progress_state, nr_result);
 +      }
 +
 +      traverse_bitmap_commit_list(&add_object_entry_from_bitmap);
 +      return 0;
 +}
 +
  static void get_object_list(int ac, const char **av)
  {
        struct rev_info revs;
        save_commit_buffer = 0;
        setup_revisions(ac, av, &revs, NULL);
  
 +      /* make sure shallows are read */
 +      is_repository_shallow();
 +
        while (fgets(line, sizeof(line), stdin) != NULL) {
                int len = strlen(line);
                if (len && line[len - 1] == '\n')
                if (*line == '-') {
                        if (!strcmp(line, "--not")) {
                                flags ^= UNINTERESTING;
 +                              write_bitmap_index = 0;
 +                              continue;
 +                      }
 +                      if (starts_with(line, "--shallow ")) {
 +                              unsigned char sha1[20];
 +                              if (get_sha1_hex(line + 10, sha1))
 +                                      die("not an SHA-1 '%s'", line + 10);
 +                              register_shallow(sha1);
                                continue;
                        }
                        die("not a rev '%s'", line);
                        die("bad revision '%s'", line);
        }
  
 +      if (use_bitmap_index && !get_object_list_from_bitmap(&revs))
 +              return;
 +
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
        mark_edges_uninteresting(&revs, show_edge);
@@@ -2627,14 -2504,10 +2627,14 @@@ int cmd_pack_objects(int argc, const ch
                            N_("pack compression level")),
                OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents,
                            N_("do not hide commits by grafts"), 0),
 +              OPT_BOOL(0, "use-bitmap-index", &use_bitmap_index,
 +                       N_("use a bitmap index if available to speed up counting objects")),
 +              OPT_BOOL(0, "write-bitmap-index", &write_bitmap_index,
 +                       N_("write a bitmap index together with the pack index")),
                OPT_END(),
        };
  
 -      read_replace_refs = 0;
 +      check_replace_refs = 0;
  
        reset_pack_idx_option(&pack_idx_opts);
        git_config(git_pack_config, NULL);
        if (keep_unreachable && unpack_unreachable)
                die("--keep-unreachable and --unpack-unreachable are incompatible.");
  
 +      if (!use_internal_rev_list || !pack_to_stdout || is_repository_shallow())
 +              use_bitmap_index = 0;
 +
 +      if (pack_to_stdout || !rev_list_all)
 +              write_bitmap_index = 0;
 +
        if (progress && all_progress_implied)
                progress = 2;
  
        prepare_packed_git();
  
        if (progress)
 -              progress_state = start_progress("Counting objects", 0);
 +              progress_state = start_progress(_("Counting objects"), 0);
        if (!use_internal_rev_list)
                read_object_list_from_stdin();
        else {
diff --combined diff.c
index e343191bdaba0dbf63a841a79287cbb5f56fc18a,635dee244d767bffc689550fd3e32d0ac1a37fea..539997fc6a679b2d85479a4d8f12f864d92b6c7c
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -1361,7 -1361,11 +1361,7 @@@ static struct diffstat_file *diffstat_a
  {
        struct diffstat_file *x;
        x = xcalloc(sizeof (*x), 1);
 -      if (diffstat->nr == diffstat->alloc) {
 -              diffstat->alloc = alloc_nr(diffstat->alloc);
 -              diffstat->files = xrealloc(diffstat->files,
 -                              diffstat->alloc * sizeof(x));
 -      }
 +      ALLOC_GROW(diffstat->files, diffstat->nr + 1, diffstat->alloc);
        diffstat->files[diffstat->nr++] = x;
        if (name_b) {
                x->from_name = xstrdup(name_a);
@@@ -3362,11 -3366,14 +3362,11 @@@ static int opt_arg(const char *arg, in
        if (c != '-')
                return 0;
        arg++;
 -      eq = strchr(arg, '=');
 -      if (eq)
 -              len = eq - arg;
 -      else
 -              len = strlen(arg);
 +      eq = strchrnul(arg, '=');
 +      len = eq - arg;
        if (!len || strncmp(arg, arg_long, len))
                return 0;
 -      if (eq) {
 +      if (*eq) {
                int n;
                char *end;
                if (!isdigit(*++eq))
@@@ -3593,6 -3600,14 +3593,6 @@@ static int parse_diff_filter_opt(const 
        return 0;
  }
  
 -/* Used only by "diff-files" and "diff --no-index" */
 -void handle_deprecated_show_diff_q(struct diff_options *opt)
 -{
 -      warning("'diff -q' and 'diff-files -q' are deprecated.");
 -      warning("Use 'diff --diff-filter=d' instead to ignore deleted filepairs.");
 -      parse_diff_filter_opt("d", opt);
 -}
 -
  static void enable_patch_output(int *fmt) {
        *fmt &= ~DIFF_FORMAT_NO_OUTPUT;
        *fmt |= DIFF_FORMAT_PATCH;
@@@ -3927,7 -3942,7 +3927,7 @@@ static int diff_scoreopt_parse(const ch
                }
        }
        if (cmd != 'M' && cmd != 'C' && cmd != 'B')
-               return -1; /* that is not a -M, -C nor -B option */
+               return -1; /* that is not a -M, -Cor -B option */
  
        opt1 = parse_rename_score(&opt);
        if (cmd != 'B')
@@@ -3951,7 -3966,11 +3951,7 @@@ struct diff_queue_struct diff_queued_di
  
  void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
  {
 -      if (queue->alloc <= queue->nr) {
 -              queue->alloc = alloc_nr(queue->alloc);
 -              queue->queue = xrealloc(queue->queue,
 -                                      sizeof(dp) * queue->alloc);
 -      }
 +      ALLOC_GROW(queue->queue, queue->nr + 1, queue->alloc);
        queue->queue[queue->nr++] = dp;
  }
  
index d3bca1261110014b2b969f6d2fc1d73dca424204,32c2f9cf88201b2dc2b94b9c97633c8c67d8c6c5..1fadd69f8809f91337a27b98f244a3cf7183b23f
@@@ -58,9 -58,6 +58,9 @@@ if ($repo->config_bool("interactive.sin
                Term::ReadKey->import;
                $use_readkey = 1;
        };
 +      if (!$use_readkey) {
 +              print STDERR "missing Term::ReadKey, disabling interactive.singlekey\n";
 +      }
        eval {
                require Term::Cap;
                my $termcap = Term::Cap->Tgetent;
@@@ -1159,9 -1156,9 +1159,9 @@@ sub help_patch_cmd 
        print colored $help_color, <<EOF ;
  y - $verb this hunk$target
  n - do not $verb this hunk$target
- q - quit; do not $verb this hunk nor any of the remaining ones
+ q - quit; do not $verb this hunk or any of the remaining ones
  a - $verb this hunk and all later hunks in the file
- d - do not $verb this hunk nor any of the later hunks in the file
+ d - do not $verb this hunk or any of the later hunks in the file
  g - select a hunk to go to
  / - search for a hunk matching the given regex
  j - leave this hunk undecided, see next undecided hunk
diff --combined git-am.sh
index 1b638e83b13bf4a2802cb035b437433177b3d34f,e92e5bb121d50d21f104c3f66e90a7c1db5f34a6..ee61a77d717a7210a1cf614914ab62788fd5e4fc
+++ b/git-am.sh
@@@ -4,7 -4,6 +4,7 @@@
  
  SUBDIRECTORY_OK=Yes
  OPTIONS_KEEPDASHDASH=
 +OPTIONS_STUCKLONG=t
  OPTIONS_SPEC="\
  git am [options] [(<mbox>|<Maildir>)...]
  git am [options] (--continue | --skip | --abort)
@@@ -38,7 -37,6 +38,7 @@@ abort           restore the original br
  committer-date-is-author-date    lie about committer date
  ignore-date     use current timestamp for author date
  rerere-autoupdate update the index with reused conflict resolution if possible
 +S,gpg-sign?     GPG-sign commits
  rebasing*       (internal use for git-rebase)"
  
  . git-sh-setup
@@@ -125,7 -123,7 +125,7 @@@ cannot_fallback () 
  }
  
  fall_back_3way () {
 -    O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
 +    O_OBJECT=$(cd "$GIT_OBJECT_DIRECTORY" && pwd)
  
      rm -fr "$dotest"/patch-merge-*
      mkdir "$dotest/patch-merge-tmp-dir"
@@@ -275,7 -273,7 +275,7 @@@ split_patches () 
                then
                        clean_abort "$(gettext "Only one StGIT patch series can be applied at once")"
                fi
 -              series_dir=`dirname "$1"`
 +              series_dir=$(dirname "$1")
                series_file="$1"
                shift
                {
                this=0
                for stgit in "$@"
                do
 -                      this=`expr "$this" + 1`
 -                      msgnum=`printf "%0${prec}d" $this`
 +                      this=$(expr "$this" + 1)
 +                      msgnum=$(printf "%0${prec}d" $this)
                        # Perl version of StGIT parse_patch. The first nonemptyline
                        # not starting with Author, From or Date is the
                        # subject, and the body starts with the next nonempty
@@@ -376,7 -374,6 +376,7 @@@ git_apply_opt
  committer_date_is_author_date=
  ignore_date=
  allow_rerere_autoupdate=
 +gpg_sign_opt=
  
  if test "$(git config --bool --get am.keepcr)" = true
  then
@@@ -416,14 -413,14 +416,14 @@@ it will be removed. Please do not use i
                abort=t ;;
        --rebasing)
                rebasing=t threeway=t ;;
 -      --resolvemsg)
 -              shift; resolvemsg=$1 ;;
 -      --whitespace|--directory|--exclude|--include)
 -              git_apply_opt="$git_apply_opt $(sq "$1=$2")"; shift ;;
 -      -C|-p)
 -              git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;;
 -      --patch-format)
 -              shift ; patch_format="$1" ;;
 +      --resolvemsg=*)
 +              resolvemsg="${1#--resolvemsg=}" ;;
 +      --whitespace=*|--directory=*|--exclude=*|--include=*)
 +              git_apply_opt="$git_apply_opt $(sq "$1")" ;;
 +      -C*|-p*)
 +              git_apply_opt="$git_apply_opt $(sq "$1")" ;;
 +      --patch-format=*)
 +              patch_format="${1#--patch-format=}" ;;
        --reject|--ignore-whitespace|--ignore-space-change)
                git_apply_opt="$git_apply_opt $1" ;;
        --committer-date-is-author-date)
                keepcr=t ;;
        --no-keep-cr)
                keepcr=f ;;
 +      --gpg-sign)
 +              gpg_sign_opt=-S ;;
 +      --gpg-sign=*)
 +              gpg_sign_opt="-S${1#--gpg-sign=}" ;;
        --)
                shift; break ;;
        *)
@@@ -530,7 -523,7 +530,7 @@@ Use \"git am --abort\" to remove it.")
                esac
        fi
  
-       # Make sure we are not given --skip, --continue, nor --abort
+       # Make sure we are not given --skip, --continue, or --abort
        test "$skip$resolved$abort" = "" ||
                die "$(gettext "Resolve operation not in progress, we are not resuming.")"
  
  git_apply_opt=$(cat "$dotest/apply-opt")
  if test "$(cat "$dotest/sign")" = t
  then
 -      SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e '
 +      SIGNOFF=$(git var GIT_COMMITTER_IDENT | sed -e '
                        s/>.*/>/
                        s/^/Signed-off-by: /'
 -              `
 +              )
  else
        SIGNOFF=
  fi
  
 -last=`cat "$dotest/last"`
 -this=`cat "$dotest/next"`
 +last=$(cat "$dotest/last")
 +this=$(cat "$dotest/next")
  if test "$skip" = t
  then
 -      this=`expr "$this" + 1`
 +      this=$(expr "$this" + 1)
        resume=
  fi
  
  while test "$this" -le "$last"
  do
 -      msgnum=`printf "%0${prec}d" $this`
 -      next=`expr "$this" + 1`
 +      msgnum=$(printf "%0${prec}d" $this)
 +      next=$(expr "$this" + 1)
        test -f "$dotest/$msgnum" || {
                resume=
                go_next
@@@ -739,16 -732,16 +739,16 @@@ To restore the original branch and sto
        '')
            if test '' != "$SIGNOFF"
            then
 -              LAST_SIGNED_OFF_BY=`
 +              LAST_SIGNED_OFF_BY=$(
                    sed -ne '/^Signed-off-by: /p' \
                    "$dotest/msg-clean" |
                    sed -ne '$p'
 -              `
 -              ADD_SIGNOFF=`
 +              )
 +              ADD_SIGNOFF=$(
                    test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
                    test '' = "$LAST_SIGNED_OFF_BY" && echo
                    echo "$SIGNOFF"
 -              }`
 +              })
            else
                ADD_SIGNOFF=
            fi
@@@ -906,8 -899,7 +906,8 @@@ did you forget to use 'git add'?
                        GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
                        export GIT_COMMITTER_DATE
                fi &&
 -              git commit-tree $tree ${parent:+-p} $parent <"$dotest/final-commit"
 +              git commit-tree ${parent:+-p} $parent ${gpg_sign_opt:+"$gpg_sign_opt"} $tree  \
 +                      <"$dotest/final-commit"
        ) &&
        git update-ref -m "$GIT_REFLOG_ACTION: $FIRSTLINE" HEAD $commit $parent ||
        stop_here $this
diff --combined gitweb/gitweb.perl
index 79057b7d0e4f6c76a9d9853be14bbef60fa9c1c0,52108b925526764f78be017afc47003036469346..a9f57d6f9024b2c23d6a2a67d33d84638e3bfb07
@@@ -1490,7 -1490,7 +1490,7 @@@ sub is_valid_pathname 
        my $input = shift;
  
        return undef unless defined $input;
-       # no '.' or '..' as elements of path, i.e. no '.' nor '..'
+       # no '.' or '..' as elements of path, i.e. no '.' or '..'
        # at the beginning, at the end, and between slashes.
        # also this catches doubled slashes
        if ($input =~ m!(^|/)(|\.|\.\.)(/|$)!) {
@@@ -7094,7 -7094,7 +7094,7 @@@ sub git_blob 
        git_print_page_path($file_name, "blob", $hash_base);
        print "<div class=\"page_body\">\n";
        if ($mimetype =~ m!^image/!) {
 -              print qq!<img type="!.esc_attr($mimetype).qq!"!;
 +              print qq!<img class="blob" type="!.esc_attr($mimetype).qq!"!;
                if ($file_name) {
                        print qq! alt="!.esc_attr($file_name).qq!" title="!.esc_attr($file_name).qq!"!;
                }
diff --combined http.h
index a82888445e9f04acfe27e36b1f274ffb9659cddf,a766066dfde652d13bbd30f1bb83928b1e727f22..e64084fe6d455652bde1b02012b52879327e2c0a
--- 1/http.h
--- 2/http.h
+++ b/http.h
@@@ -13,8 -13,7 +13,7 @@@
  /*
   * We detect based on the cURL version if multi-transfer is
   * usable in this implementation and define this symbol accordingly.
-  * This is not something Makefile should set nor users should pass
-  * via CFLAGS.
+  * This shouldn't be set by the Makefile or by the user (e.g. via CFLAGS).
   */
  #undef USE_CURL_MULTI
  
@@@ -90,15 -89,6 +89,15 @@@ extern void finish_active_slot(struct a
  extern void finish_all_active_slots(void);
  extern int handle_curl_result(struct slot_results *results);
  
 +/*
 + * This will run one slot to completion in a blocking manner, similar to how
 + * curl_easy_perform would work (but we don't want to use that, because
 + * we do not want to intermingle calls to curl_multi and curl_easy).
 + *
 + */
 +int run_one_slot(struct active_request_slot *slot,
 +               struct slot_results *results);
 +
  #ifdef USE_CURL_MULTI
  extern void fill_active_slots(void);
  extern void add_fill_function(void *data, int (*fill)(void *));
diff --combined remote.c
index 6d424680c2987575d3958d42d540393586128ae9,f43c7a9d531db7a36634e6103bfdf60ee3ca22e1..eea2c8de45052e3e3a59fb150eef3f54c6086800
+++ b/remote.c
@@@ -857,32 -857,6 +857,32 @@@ static int match_name_with_pattern(cons
        return ret;
  }
  
 +static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct refspec *query, struct string_list *results)
 +{
 +      int i;
 +      int find_src = !query->src;
 +
 +      if (find_src && !query->dst)
 +              error("query_refspecs_multiple: need either src or dst");
 +
 +      for (i = 0; i < ref_count; i++) {
 +              struct refspec *refspec = &refs[i];
 +              const char *key = find_src ? refspec->dst : refspec->src;
 +              const char *value = find_src ? refspec->src : refspec->dst;
 +              const char *needle = find_src ? query->dst : query->src;
 +              char **result = find_src ? &query->src : &query->dst;
 +
 +              if (!refspec->dst)
 +                      continue;
 +              if (refspec->pattern) {
 +                      if (match_name_with_pattern(key, needle, value, result))
 +                              string_list_append_nodup(results, *result);
 +              } else if (!strcmp(needle, key)) {
 +                      string_list_append(results, value);
 +              }
 +      }
 +}
 +
  int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
  {
        int i;
@@@ -1062,13 -1036,11 +1062,13 @@@ int count_refspec_match(const char *pat
                }
        }
        if (!matched) {
 -              *matched_ref = matched_weak;
 +              if (matched_ref)
 +                      *matched_ref = matched_weak;
                return weak_match;
        }
        else {
 -              *matched_ref = matched;
 +              if (matched_ref)
 +                      *matched_ref = matched;
                return match;
        }
  }
@@@ -1088,25 -1060,18 +1088,25 @@@ static struct ref *alloc_delete_ref(voi
        return ref;
  }
  
 -static struct ref *try_explicit_object_name(const char *name)
 +static int try_explicit_object_name(const char *name,
 +                                  struct ref **match)
  {
        unsigned char sha1[20];
 -      struct ref *ref;
  
 -      if (!*name)
 -              return alloc_delete_ref();
 +      if (!*name) {
 +              if (match)
 +                      *match = alloc_delete_ref();
 +              return 0;
 +      }
 +
        if (get_sha1(name, sha1))
 -              return NULL;
 -      ref = alloc_ref(name);
 -      hashcpy(ref->new_sha1, sha1);
 -      return ref;
 +              return -1;
 +
 +      if (match) {
 +              *match = alloc_ref(name);
 +              hashcpy((*match)->new_sha1, sha1);
 +      }
 +      return 0;
  }
  
  static struct ref *make_linked_ref(const char *name, struct ref ***tail)
@@@ -1136,37 -1101,12 +1136,37 @@@ static char *guess_ref(const char *name
        return strbuf_detach(&buf, NULL);
  }
  
 +static int match_explicit_lhs(struct ref *src,
 +                            struct refspec *rs,
 +                            struct ref **match,
 +                            int *allocated_match)
 +{
 +      switch (count_refspec_match(rs->src, src, match)) {
 +      case 1:
 +              if (allocated_match)
 +                      *allocated_match = 0;
 +              return 0;
 +      case 0:
 +              /* The source could be in the get_sha1() format
 +               * not a reference name.  :refs/other is a
 +               * way to delete 'other' ref at the remote end.
 +               */
 +              if (try_explicit_object_name(rs->src, match) < 0)
 +                      return error("src refspec %s does not match any.", rs->src);
 +              if (allocated_match)
 +                      *allocated_match = 1;
 +              return 0;
 +      default:
 +              return error("src refspec %s matches more than one.", rs->src);
 +      }
 +}
 +
  static int match_explicit(struct ref *src, struct ref *dst,
                          struct ref ***dst_tail,
                          struct refspec *rs)
  {
        struct ref *matched_src, *matched_dst;
 -      int copy_src;
 +      int allocated_src;
  
        const char *dst_value = rs->dst;
        char *dst_guess;
                return 0;
  
        matched_src = matched_dst = NULL;
 -      switch (count_refspec_match(rs->src, src, &matched_src)) {
 -      case 1:
 -              copy_src = 1;
 -              break;
 -      case 0:
 -              /* The source could be in the get_sha1() format
 -               * not a reference name.  :refs/other is a
 -               * way to delete 'other' ref at the remote end.
 -               */
 -              matched_src = try_explicit_object_name(rs->src);
 -              if (!matched_src)
 -                      return error("src refspec %s does not match any.", rs->src);
 -              copy_src = 0;
 -              break;
 -      default:
 -              return error("src refspec %s matches more than one.", rs->src);
 -      }
 +      if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0)
 +              return -1;
  
        if (!dst_value) {
                unsigned char sha1[20];
                return error("dst ref %s receives from more than one src.",
                      matched_dst->name);
        else {
 -              matched_dst->peer_ref = copy_src ? copy_ref(matched_src) : matched_src;
 +              matched_dst->peer_ref = allocated_src ?
 +                                      matched_src :
 +                                      copy_ref(matched_src);
                matched_dst->force = rs->force;
        }
        return 0;
@@@ -1404,31 -1357,6 +1404,31 @@@ static void prepare_ref_index(struct st
        sort_string_list(ref_index);
  }
  
 +/*
 + * Given only the set of local refs, sanity-check the set of push
 + * refspecs. We can't catch all errors that match_push_refs would,
 + * but we can catch some errors early before even talking to the
 + * remote side.
 + */
 +int check_push_refs(struct ref *src, int nr_refspec, const char **refspec_names)
 +{
 +      struct refspec *refspec = parse_push_refspec(nr_refspec, refspec_names);
 +      int ret = 0;
 +      int i;
 +
 +      for (i = 0; i < nr_refspec; i++) {
 +              struct refspec *rs = refspec + i;
 +
 +              if (rs->pattern || rs->matching)
 +                      continue;
 +
 +              ret |= match_explicit_lhs(src, rs, NULL, NULL);
 +      }
 +
 +      free_refspec(nr_refspec, refspec);
 +      return ret;
 +}
 +
  /*
   * Given the set of refs the local repository has, the set of refs the
   * remote repository has, and the refspec used for push, determine
@@@ -1481,7 -1409,7 +1481,7 @@@ int match_push_refs(struct ref *src, st
                                /*
                                 * Remote doesn't have it, and we have no
                                 * explicit pattern, and we don't have
-                                * --all nor --mirror.
+                                * --all or --mirror.
                                 */
                                goto free_name;
  
@@@ -2069,37 -1997,25 +2069,37 @@@ static int get_stale_heads_cb(const cha
        const unsigned char *sha1, int flags, void *cb_data)
  {
        struct stale_heads_info *info = cb_data;
 +      struct string_list matches = STRING_LIST_INIT_DUP;
        struct refspec query;
 +      int i, stale = 1;
        memset(&query, 0, sizeof(struct refspec));
        query.dst = (char *)refname;
  
 -      if (query_refspecs(info->refs, info->ref_count, &query))
 -              return 0; /* No matches */
 +      query_refspecs_multiple(info->refs, info->ref_count, &query, &matches);
 +      if (matches.nr == 0)
 +              goto clean_exit; /* No matches */
  
        /*
         * If we did find a suitable refspec and it's not a symref and
         * it's not in the list of refs that currently exist in that
 -       * remote we consider it to be stale.
 +       * remote, we consider it to be stale. In order to deal with
 +       * overlapping refspecs, we need to go over all of the
 +       * matching refs.
         */
 -      if (!((flags & REF_ISSYMREF) ||
 -            string_list_has_string(info->ref_names, query.src))) {
 +      if (flags & REF_ISSYMREF)
 +              goto clean_exit;
 +
 +      for (i = 0; stale && i < matches.nr; i++)
 +              if (string_list_has_string(info->ref_names, matches.items[i].string))
 +                      stale = 0;
 +
 +      if (stale) {
                struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
                hashcpy(ref->new_sha1, sha1);
        }
  
 -      free(query.src);
 +clean_exit:
 +      string_list_clear(&matches, 0);
        return 0;
  }
  
diff --combined sha1_file.c
index 400aa463a47c504feec3ca508e7340c6d5dc8268,77dbb56946771d631ec544dc1958fcff9215c117..3e9f55f1bb19a33908be174b2fa463f8142d4cae
@@@ -60,12 -60,6 +60,12 @@@ static struct cached_object empty_tree 
        0
  };
  
 +/*
 + * A pointer to the last packed_git in which an object was found.
 + * When an object is sought, we look in this packfile first, because
 + * objects that are looked up at similar times are often in the same
 + * packfile as one another.
 + */
  static struct packed_git *last_found_pack;
  
  static struct cached_object *find_cached_object(const unsigned char *sha1)
@@@ -184,7 -178,17 +184,7 @@@ static void fill_sha1_path(char *pathbu
        }
  }
  
 -/*
 - * NOTE! This returns a statically allocated buffer, so you have to be
 - * careful about using it. Do an "xstrdup()" if you need to save the
 - * filename.
 - *
 - * Also note that this returns the location for creating.  Reading
 - * SHA1 file can happen from any alternate directory listed in the
 - * DB_ENVIRONMENT environment variable if it is not found in
 - * the primary object database.
 - */
 -char *sha1_file_name(const unsigned char *sha1)
 +const char *sha1_file_name(const unsigned char *sha1)
  {
        static char buf[PATH_MAX];
        const char *objdir;
        return buf;
  }
  
 +/*
 + * Return the name of the pack or index file with the specified sha1
 + * in its filename.  *base and *name are scratch space that must be
 + * provided by the caller.  which should be "pack" or "idx".
 + */
  static char *sha1_get_pack_name(const unsigned char *sha1,
                                char **name, char **base, const char *which)
  {
@@@ -253,6 -252,8 +253,6 @@@ char *sha1_pack_index_name(const unsign
  struct alternate_object_database *alt_odb_list;
  static struct alternate_object_database **alt_odb_tail;
  
 -static int git_open_noatime(const char *name);
 -
  /*
   * Prepare alternate object database registry.
   *
@@@ -437,7 -438,8 +437,7 @@@ void prepare_alt_odb(void
  
  static int has_loose_object_local(const unsigned char *sha1)
  {
 -      char *name = sha1_file_name(sha1);
 -      return !access(name, F_OK);
 +      return !access(sha1_file_name(sha1), F_OK);
  }
  
  int has_loose_object_nonlocal(const unsigned char *sha1)
@@@ -489,12 -491,7 +489,12 @@@ void pack_report(void
                sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
  }
  
 -static int check_packed_git_idx(const char *path,  struct packed_git *p)
 +/*
 + * Open and mmap the index file at path, perform a couple of
 + * consistency checks, then record its information to p.  Return 0 on
 + * success.
 + */
 +static int check_packed_git_idx(const char *path, struct packed_git *p)
  {
        void *idx_map;
        struct pack_idx_header *hdr;
@@@ -790,7 -787,7 +790,7 @@@ void close_pack_index(struct packed_gi
   * contain the same set of objects as an existing one.  In that case
   * the resulting file might be different even if its name would be the
   * same.  It is best to close any reference to the old pack before it is
-  * replaced on disk.  Of course no index pointers nor windows for given pack
+  * replaced on disk.  Of course no index pointers or windows for given pack
   * must subsist at this point.  If ever objects from this pack are requested
   * again, the new version of the pack will be reinitialized through
   * reprepare_packed_git().
@@@ -1126,7 -1123,7 +1126,7 @@@ static void report_helper(const struct 
        const char *msg;
        switch (seen_bits) {
        case 0:
-               msg = "no corresponding .idx nor .pack";
+               msg = "no corresponding .idx or .pack";
                break;
        case 1:
                msg = "no corresponding .idx";
@@@ -1235,7 -1232,6 +1235,7 @@@ static void prepare_packed_git_one(cha
  
                if (has_extension(de->d_name, ".idx") ||
                    has_extension(de->d_name, ".pack") ||
 +                  has_extension(de->d_name, ".bitmap") ||
                    has_extension(de->d_name, ".keep"))
                        string_list_append(&garbage, path);
                else
@@@ -1320,6 -1316,7 +1320,6 @@@ void prepare_packed_git(void
  
  void reprepare_packed_git(void)
  {
 -      discard_revindex();
        prepare_packed_git_run_once = 0;
        prepare_packed_git();
  }
@@@ -1396,7 -1393,7 +1396,7 @@@ int check_sha1_signature(const unsigne
        return hashcmp(sha1, real_sha1) ? -1 : 0;
  }
  
 -static int git_open_noatime(const char *name)
 +int git_open_noatime(const char *name)
  {
        static int sha1_file_open_flag = O_NOATIME;
  
  
  static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
  {
 -      char *name = sha1_file_name(sha1);
        struct alternate_object_database *alt;
  
 -      if (!lstat(name, st))
 +      if (!lstat(sha1_file_name(sha1), st))
                return 0;
  
        prepare_alt_odb();
        errno = ENOENT;
        for (alt = alt_odb_list; alt; alt = alt->next) {
 -              name = alt->name;
 -              fill_sha1_path(name, sha1);
 +              fill_sha1_path(alt->name, sha1);
                if (!lstat(alt->base, st))
                        return 0;
        }
  static int open_sha1_file(const unsigned char *sha1)
  {
        int fd;
 -      char *name = sha1_file_name(sha1);
        struct alternate_object_database *alt;
  
 -      fd = git_open_noatime(name);
 +      fd = git_open_noatime(sha1_file_name(sha1));
        if (fd >= 0)
                return fd;
  
        prepare_alt_odb();
        errno = ENOENT;
        for (alt = alt_odb_list; alt; alt = alt->next) {
 -              name = alt->name;
 -              fill_sha1_path(name, sha1);
 +              fill_sha1_path(alt->name, sha1);
                fd = git_open_noatime(alt->base);
                if (fd >= 0)
                        return fd;
@@@ -2288,10 -2289,6 +2288,10 @@@ void *unpack_entry(struct packed_git *p
        *final_size = size;
  
        unuse_pack(&w_curs);
 +
 +      if (delta_stack != small_delta_stack)
 +              free(delta_stack);
 +
        return data;
  }
  
@@@ -2451,10 -2448,6 +2451,10 @@@ static int fill_pack_entry(const unsign
        return 1;
  }
  
 +/*
 + * Iff a pack file contains the object named by sha1, return true and
 + * store its location to e.
 + */
  static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
  {
        struct packed_git *p;
                return 1;
  
        for (p = packed_git; p; p = p->next) {
 -              if (p == last_found_pack || !fill_pack_entry(sha1, e, p))
 -                      continue;
 +              if (p == last_found_pack)
 +                      continue; /* we already checked this one */
  
 -              last_found_pack = p;
 -              return 1;
 +              if (fill_pack_entry(sha1, e, p)) {
 +                      last_found_pack = p;
 +                      return 1;
 +              }
        }
        return 0;
  }
@@@ -2635,7 -2626,12 +2635,7 @@@ int pretend_sha1_file(void *buf, unsign
        hash_sha1_file(buf, len, typename(type), sha1);
        if (has_sha1_file(sha1) || find_cached_object(sha1))
                return 0;
 -      if (cached_object_alloc <= cached_object_nr) {
 -              cached_object_alloc = alloc_nr(cached_object_alloc);
 -              cached_objects = xrealloc(cached_objects,
 -                                        sizeof(*cached_objects) *
 -                                        cached_object_alloc);
 -      }
 +      ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
        co = &cached_objects[cached_object_nr++];
        co->size = len;
        co->type = type;
@@@ -2683,6 -2679,7 +2683,6 @@@ void *read_sha1_file_extended(const uns
                              unsigned flag)
  {
        void *data;
 -      char *path;
        const struct packed_git *p;
        const unsigned char *repl = lookup_replace_object_extended(sha1, flag);
  
                    sha1_to_hex(repl), sha1_to_hex(sha1));
  
        if (has_loose_object(repl)) {
 -              path = sha1_file_name(sha1);
 +              const char *path = sha1_file_name(sha1);
 +
                die("loose object %s (stored in %s) is corrupt",
                    sha1_to_hex(repl), path);
        }
@@@ -2899,9 -2895,10 +2899,9 @@@ static int write_loose_object(const uns
        git_zstream stream;
        git_SHA_CTX c;
        unsigned char parano_sha1[20];
 -      char *filename;
        static char tmp_file[PATH_MAX];
 +      const char *filename = sha1_file_name(sha1);
  
 -      filename = sha1_file_name(sha1);
        fd = create_tmpfile(tmp_file, sizeof(tmp_file), filename);
        if (fd < 0) {
                if (errno == EACCES)
diff --combined t/t7104-reset-hard.sh
index f136ee7bb5300966c0c3c9d2250dc81763db9feb,0000000000000000000000000000000000000000..16faa0781373bb3769ce9f0fa0a09be8c2b2ed81
mode 100755,000000..100755
--- /dev/null
@@@ -1,46 -1,0 +1,46 @@@
- test_expect_success 'reset --hard did not corrupt index nor cached-tree' '
 +#!/bin/sh
 +
 +test_description='reset --hard unmerged'
 +
 +. ./test-lib.sh
 +
 +test_expect_success setup '
 +
 +      mkdir before later &&
 +      >before/1 &&
 +      >before/2 &&
 +      >hello &&
 +      >later/3 &&
 +      git add before hello later &&
 +      git commit -m world &&
 +
 +      H=$(git rev-parse :hello) &&
 +      git rm --cached hello &&
 +      echo "100644 $H 2       hello" | git update-index --index-info &&
 +
 +      rm -f hello &&
 +      mkdir -p hello &&
 +      >hello/world &&
 +      test "$(git ls-files -o)" = hello/world
 +
 +'
 +
 +test_expect_success 'reset --hard should restore unmerged ones' '
 +
 +      git reset --hard &&
 +      git ls-files --error-unmatch before/1 before/2 hello later/3 &&
 +      test -f hello
 +
 +'
 +
++test_expect_success 'reset --hard did not corrupt index or cached-tree' '
 +
 +      T=$(git write-tree) &&
 +      rm -f .git/index &&
 +      git add before hello later &&
 +      U=$(git write-tree) &&
 +      test "$T" = "$U"
 +
 +'
 +
 +test_done
index ed98e64477905123164365b8fb15bdb1435d0646,1f06e25db6451150ff0a066e0d342414301433a3..6146c3fec293915b4599748e7a787539a7715e1a
@@@ -25,6 -25,7 +25,6 @@@ perl -e 'use DBI; use DBD::SQLite' >/de
      test_done
  }
  
 -unset GIT_DIR GIT_CONFIG
  WORKDIR=$(pwd)
  SERVERDIR=$(pwd)/gitcvs.git
  git_config="$SERVERDIR/config"
@@@ -511,7 -512,7 +511,7 @@@ test_expect_success 'cvs co -c (shows m
  # Known issues with git-cvsserver current log output:
  #  - Hard coded "lines: +2 -3" placeholder, instead of real numbers.
  #  - CVS normally does not internally add a blank first line
- #    nor a last line with nothing but a space to log messages.
+ #    or a last line with nothing but a space to log messages.
  #  - The latest cvs 1.12.x server sends +0000 timezone (with some hidden "MT"
  #    tagging in the protocol), and if cvs 1.12.x client sees the MT tags,
  #    it converts to local time zone.  git-cvsserver doesn't do the +0000