Jeff King a10a17877b for_each_alternate_ref: replace transport code with for-each-ref
The current method for getting the refs from an alternate is
to run upload-pack in the alternate and parse its output
using the normal transport code.  This works and is
reasonably short, but it has a very bad memory footprint
when there are a lot of refs in the alternate. There are two
problems:

  1. It reads in all of the refs before passing any back to
     us. Which means that our peak memory usage has to store
     every ref (including duplicates for peeled variants),
     even if our callback could determine that some are not
     interesting (e.g., because they point to the same sha1
     as another ref).

  2. It allocates a "struct ref" for each one. Among other
     things, this contains 3 separate 20-byte oids, along
     with the name and various pointers.  That can add up,
     especially if the callback is only interested in the
     sha1 (which it can store in a sha1_array as just 20
     bytes).

On a particularly pathological case, where the alternate had
over 80 million refs pointing to only around 60,000 unique
objects, the peak heap usage of "git clone --reference" grew
to over 25GB.

This patch instead calls git-for-each-ref in the alternate
repository, and passes each line to the callback as we read
it. That drops the peak heap of the same command to 50MB.

I considered and rejected a few alternatives.

We could read all of the refs in the alternate using our own
ref code, just as we do with submodules.  However, as memory
footprint is one of the concerns here, we want to avoid
loading those refs into our own memory as a whole.

It's possible that this will be a better technique in the
future when the ref code can more easily iterate without
loading all of packed-refs into memory.

Another option is to keep calling upload-pack, and just
parse its output ourselves in a streaming fashion. Besides
for-each-ref being simpler (we get to define the format
ourselves, and don't have to deal with speaking the git
protocol), it's more flexible for possible future changes.

For instance, it might be useful for the caller to be able
to limit the set of "interesting" alternate refs.  The
motivating example is one where many "forks" of a particular
repository share object storage, and the shared storage has
refs for each fork (which is why so many of the refs are
duplicates; each fork has the same tags).  A plausible
future optimization would be to ask for the alternate refs
for just _one_ fork (if you had some out-of-band way of
knowing which was the most interesting or important for the
current operation).

Similarly, no callbacks actually care about the symref value
of alternate refs, and as before, this patch ignores them
entirely.  However, if we wanted to add them, for-each-ref's
"%(symref)" is going to be more flexible than upload-pack,
because the latter only handles the HEAD symref due to
historical constraints.

There is one potential downside, though: unlike upload-pack,
our for-each-ref command doesn't report the peeled value of
refs. The existing code calls the alternate_ref_fn callback
twice for tags: once for the tag, and once for the peeled
value with the refname set to "ref^{}".

For the callers in fetch-pack, this doesn't matter at all.
We immediately peel each tag down to a commit either way (so
there's a slight improvement, as do not bother passing the
redundant data over the pipe). For the caller in
receive-pack, it means we will not advertise the peeled
values of tags in our alternate. However, we also don't
advertise peeled values for our _own_ tags, so this is
actually making things more consistent.

It's unclear whether receive-pack advertising peeled values
is a win or not. On one hand, giving more information to the
other side may let it omit some objects from the push. On
the other hand, for tags which both sides have, they simply
bloat the advertisement. The upload-pack advertisement of
git.git is about 30% larger than the receive-pack
advertisement due to its peeled information.

This patch omits the peeled information from
for_each_alternate_ref entirely, and leaves it up to the
caller whether they want to dig up the information.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-08 15:39:55 -08:00
2016-05-10 11:19:07 -07:00
2017-02-03 11:29:52 -08:00
2016-02-22 14:51:09 -08:00
2016-12-27 00:11:40 -08:00
2017-01-25 14:42:37 -08:00
2017-02-02 13:36:57 -08:00
2017-02-02 13:36:55 -08:00
2016-02-22 14:51:09 -08:00
2016-11-22 13:55:20 -08:00
2016-11-22 13:55:20 -08:00
2016-02-22 14:50:32 -08:00
2016-02-22 14:50:32 -08:00
2016-05-09 12:29:08 -07:00
2016-02-22 14:51:09 -08:00
2017-01-25 14:42:37 -08:00
2016-08-12 09:47:37 -07:00
2016-12-06 13:27:11 -08:00
2016-10-31 13:15:21 -07:00
2016-05-09 12:29:08 -07:00
2016-07-27 14:15:51 -07:00
2015-11-20 08:02:05 -05:00
2016-10-27 14:58:50 -07:00
2016-09-29 15:42:18 -07:00
2017-01-18 15:12:16 -08:00
2016-12-12 15:15:07 -08:00
2016-05-09 12:29:08 -07:00
2016-07-01 12:44:57 -07:00
2016-07-01 12:44:57 -07:00
2017-01-23 11:02:36 -08:00
2017-02-02 13:36:55 -08:00
2016-12-19 14:45:35 -08:00
2016-10-14 01:36:12 +00:00
2017-02-03 11:29:52 -08:00
2016-02-22 14:51:09 -08:00
2016-09-29 15:42:18 -07:00
2016-05-17 14:38:32 -07:00
2016-12-07 11:31:59 -08:00
2017-02-02 13:36:57 -08:00
2016-12-07 11:31:59 -08:00
2016-07-29 11:05:07 -07:00
2016-07-29 11:05:07 -07:00
2016-09-26 16:09:18 -07:00
2015-11-20 08:02:05 -05:00
2016-06-13 14:38:16 -07:00
2016-09-29 15:42:18 -07:00
2016-09-25 16:44:13 -07:00
2016-09-29 15:42:18 -07:00
2016-10-17 13:25:21 -07:00
2016-07-28 11:26:03 -07:00
2016-07-28 11:26:03 -07:00
2016-05-09 12:29:08 -07:00
2017-01-31 13:15:00 -08:00
2017-01-31 13:14:58 -08:00
2017-01-17 15:19:11 -08:00
2016-04-25 15:17:15 -07:00
2016-07-14 15:50:41 -07:00
2016-09-29 15:42:18 -07:00
2016-10-10 14:03:46 -07:00
2016-07-01 15:09:10 -07:00
2016-08-05 09:28:17 -07:00
2016-09-29 15:42:18 -07:00
2017-01-31 13:14:56 -08:00
2016-02-22 10:40:35 -08:00
2016-09-26 18:16:23 -07:00
2017-02-02 13:36:55 -08:00
2017-02-03 11:25:19 -08:00

Git - fast, scalable, distributed revision control system

Git is a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals.

Git is an Open Source project covered by the GNU General Public License version 2 (some parts of it are under different licenses, compatible with the GPLv2). It was originally written by Linus Torvalds with help of a group of hackers around the net.

Please read the file INSTALL for installation instructions.

Many Git online resources are accessible from http://git-scm.com/ including full documentation and Git related tools.

See Documentation/gittutorial.txt to get started, then see Documentation/giteveryday.txt for a useful minimum set of commands, and Documentation/git-.txt for documentation of each command. If git has been correctly installed, then the tutorial can also be read with man gittutorial or git help tutorial, and the documentation of each command with man git-<commandname> or git help <commandname>.

CVS users may also want to read Documentation/gitcvs-migration.txt (man gitcvs-migration or git help cvs-migration if git is installed).

The user discussion and development of Git take place on the Git mailing list -- everyone is welcome to post bug reports, feature requests, comments and patches to git@vger.kernel.org (read Documentation/SubmittingPatches for instructions on patch submission). To subscribe to the list, send an email with just "subscribe git" in the body to majordomo@vger.kernel.org. The mailing list archives are available at https://public-inbox.org/git, http://marc.info/?l=git and other archival sites.

The maintainer frequently sends the "What's cooking" reports that list the current status of various development topics to the mailing list. The discussion following them give a good reference for project status, development direction and remaining tasks.

The name "git" was given by Linus Torvalds when he wrote the very first version. He described the tool as "the stupid content tracker" and the name as (depending on your mood):

  • random three-letter combination that is pronounceable, and not actually used by any common UNIX command. The fact that it is a mispronunciation of "get" may or may not be relevant.
  • stupid. contemptible and despicable. simple. Take your pick from the dictionary of slang.
  • "global information tracker": you're in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room.
  • "goddamn idiotic truckload of sh*t": when it breaks
Description
No description provided
Readme 279 MiB
Languages
C 50.5%
Shell 38.7%
Perl 4.5%
Tcl 3.2%
Python 0.8%
Other 2.1%