#700839 git: reduce installation size by linking the copies /usr/bin/git and /usr/lib/git-core/git

Package:
git
Source:
git
Description:
fast, scalable, distributed revision control system
Submitter:
Helmut Grohne
Date:
2015-09-25 22:06:04 UTC
Severity:
wishlist
#700839#5
Date:
2013-02-18 09:19:14 UTC
From:
To:
I noticed that git ships its binary twice.

$ ls -lai /usr/lib/git-core/git /usr/bin/git
688632 -rwxr-xr-x 1 root root 1355584 Nov  1 16:36 /usr/bin/git
 20941 -rwxr-xr-x 1 root root 1355584 Nov  1 16:36 /usr/lib/git-core/git
$ cmp /usr/lib/git-core/git /usr/bin/git && echo same
same
$

This binary makes up 10% of the installation size. Please consider
replacing one of those locations with a link to the other.

Helmut

#700839#10
Date:
2013-02-18 09:25:52 UTC
From:
To:
I just noticed that there are another 10% to be obtained:

$ ls -lai /usr/lib/git-core/git-shell /usr/bin/git-shell
688732 -rwxr-xr-x 1 root root 568360 Nov  1 16:36 /usr/bin/git-shell
 21360 -rwxr-xr-x 1 root root 568360 Nov  1 16:36 /usr/lib/git-core/git-shell
$ ls -lai /usr/lib/git-core/git-upload-pack /usr/bin/git-upload-pack
688734 -rwxr-xr-x 1 root root 588936 Nov  1 16:36 /usr/bin/git-upload-pack
 21368 -rwxr-xr-x 1 root root 588936 Nov  1 16:36 /usr/lib/git-core/git-upload-pack
$

Those are indeed identical as well.

Helmut

#700839#15
Date:
2013-02-18 10:03:13 UTC
From:
To:
Hi Helmut,

Helmut Grohne wrote:

Ideally these should be hard links to the same inode (as in the
default configuration upstream).  We can't ship them that way because
there is no guarantee the two paths are even on the same filesystem,
but postinst could replace one copy with a hardlink to the other when
the system configuration allows.

What do you think?

Thanks,
Jonathan

#700839#20
Date:
2013-02-19 07:34:32 UTC
From:
To:
Hi Jonathan,

Thanks for considering my request.
binary packages. I have not yet encoutered a case where /usr/bin and
/usr/lib are on separate filesystems. Considering this as a valid case
will break the hard link case. dpkg uses tar to extract packages.  A
quick example shows how this breaks:

tar: ./linktest: Cannot hard link to `./usr/linktest': Invalid cross-device link
tar: Exiting with failure status due to previous errors

On the bright side I believe that symbolic links would work as well
here. The git package already employs them for a number of other
binaries even though at present none of them cross directories.

Many other packages use this technique as well:
find /usr/bin -type l | xargs ls -l | grep ' -> \.\./lib/'

(Hint if your system lacks example packages: ghc, iceweasel, llvm-3.1,
pypy, swi-prolog-nox)

We can conclude that the soft links are proven to work.
download bandwidth and mirror space. Getting it right seems hard as
well. I'd rather tag this issue wontfix than resort to such a trick.

Summary: From my point of view symbolic links are a clear winner here.

Helmut

#700839#25
Date:
2015-09-25 22:02:27 UTC
From:
To:
TL;DR shorter version:
    Included patch _packs_ the now bloated(*bloat) git packages in
    Debian with xz and symlinks. Cut by 34% or 2.4x depending on what
    you count. And 2.67x above that -- could be B-> possible.


Hi, everyboby!

Great I found this bug. Again. That is now that I've made a patch for
it. Every time I've seen it before I've been looking for a patch
myself and to no avail. This time it is different -- I've done it
myself and gotta share it with you.

I've done that for my local Debian "wheezy" 7.x backport of git 2.4.8
sources with 2.5.0-1 packaging. Disregard the versions. The packaging
didn't change thru to current 2.5.3-1 in unstable.

The patch makes symlinks for
  * all the matching exactly binaries in /usr/lib/git-core + /usr/bin
  * the repeated in every package changelogs in /usr/share/docs/
including between adjacent binary packages where their dependencies
allow that.

My attempts to use upstream Makefile NO_INSTALL_HARDLINKS flag and
friends did not succeed.  Dunno if there was some kind of mistake on
my part or those hardlinks just did not survive .deb packaging and
installation (in wheezy, yes).  So I resorted to symlinking.  That is
worked AFAICS.

I also used xz compression for my binary packages.  Don't know if xz
-9e compression is allowed or desired in main Debian archive.  That
part is very small (just 2 dpkg-deb lines) feel free to drop it as you
wish as it only affects resulting packages size, not installed size.

Executables are linked like this:

$ ls -Ggh  /usr/{lib/git-core,bin}/git{,-shell,-upload-pack}
lrwxrwxrwx 1   19 Aug 13 01:02 /usr/bin/git -> ../lib/git-core/git
lrwxrwxrwx 1   25 Aug 13 01:02 /usr/bin/git-shell -> ../lib/git-core/git-shell
lrwxrwxrwx 1   31 Aug 13 01:02 /usr/bin/git-upload-pack -> ../lib/git-core/git-upload-pack
-rwxr-xr-x 1 1.7M Aug 13 01:02 /usr/lib/git-core/git
-rwxr-xr-x 1 790K Aug 13 01:02 /usr/lib/git-core/git-shell
-rwxr-xr-x 1 810K Aug 13 01:02 /usr/lib/git-core/git-upload-pack

More matching blobs are also raplaced by symlinks in those 2 dirs:

$ find /usr/lib/git-core/ -type l |wc -l
112
$ find /usr/bin -type l -name git\* |wc -l
5


Changelogs symlinked:

$ ls -Ggh  /usr/share/doc/git{,-man}/c{han,op}*
-rw-r--r-- 1  35K Aug 13 01:02 /usr/share/doc/git-man/changelog.Debian.gz
-rw-r--r-- 1 554K Aug 13 01:02 /usr/share/doc/git-man/changelog.gz
-rw-r--r-- 1  18K Aug 13 01:02 /usr/share/doc/git-man/copyright
lrwxrwxrwx 1   30 Aug 13 01:02 /usr/share/doc/git/changelog.Debian.gz -> ../git-man/changelog.Debian.gz
lrwxrwxrwx 1   23 Aug 13 01:02 /usr/share/doc/git/changelog.gz -> ../git-man/changelog.gz
lrwxrwxrwx 1   20 Aug 13 01:02 /usr/share/doc/git/copyright -> ../git-man/copyright

As all the packages depend on git-man (thru git mostly) those are
symlinked to actual files in that package. 600k~ cutoff from each of
15 of 16 .deb-s, ditto installed size.


Hope that helps. Happy packaging!


PS: 15+ more blobs are mostly a repeatition if you judge by nearly
matching sizes:

$ ls -Gg `find /usr/lib/git-core/ -type f -size +100k` |cat -n
     1  -rwxr-xr-x 1 1707600 Aug 13 01:02 /usr/lib/git-core/git
     2  -rwxr-xr-x 1  804076 Aug 13 01:02 /usr/lib/git-core/git-credential-cache
     3  -rwxr-xr-x 1  816428 Aug 13 01:02 /usr/lib/git-core/git-credential-cache--daemon
     4  -rwxr-xr-x 1  812300 Aug 13 01:02 /usr/lib/git-core/git-credential-store
     5  -rwxr-xr-x 1  833068 Aug 13 01:02 /usr/lib/git-core/git-daemon
     6  -rwxr-xr-x 1  845260 Aug 13 01:02 /usr/lib/git-core/git-fast-import
     7  -rwxr-xr-x 1  816556 Aug 13 01:02 /usr/lib/git-core/git-http-backend
     8  -rwxr-xr-x 1  845324 Aug 13 01:02 /usr/lib/git-core/git-http-fetch
     9  -rwxr-xr-x 1  857676 Aug 13 01:02 /usr/lib/git-core/git-http-push
    10  -rwxr-xr-x 1  824820 Aug 13 01:02 /usr/lib/git-core/git-imap-send
    11  -rwxr-xr-x 1  870092 Aug 13 01:02 /usr/lib/git-core/git-remote-http
    12  -rwxr-xr-x 1  828736 Aug 13 01:02 /usr/lib/git-core/git-remote-testsvn
    13  -rwxr-xr-x 1  804044 Aug 13 01:02 /usr/lib/git-core/git-sh-i18n--envsubst
    14  -rwxr-xr-x 1  808236 Aug 13 01:02 /usr/lib/git-core/git-shell
    15  -rwxr-xr-x 1  804044 Aug 13 01:02 /usr/lib/git-core/git-show-index
    16  -rwxr-xr-x 1  828908 Aug 13 01:02 /usr/lib/git-core/git-upload-pack

12.4M out of 18.5M "my" installed size are 15x 800k~ exes. Possible
2.67x bloat squeeze (if I estimated it right, 12.4=>0.8 inside 18.5).
Didn't pursue that myself. Maybe some upstream developer will take
that greater chalenge of reworking the NO_INSTALL_HARDLINKS and around
mess? Looking forward :) for that.


PPS: One more idea in packaging/distibution slim down: merge all minor
release notes to every major release notes and gzip that. Make this a
plesant little (1.3M of text gziped) Makefile present to upstream*?
;) Anyone?

$ find /usr/share/doc/git/RelNotes/ -type f |wc -l
253
$ find /usr/share/doc/git/RelNotes/ -type f |grep -c \\.0\\.txt
10
$ ls -Gg /usr/share/doc/git/RelNotes/2.3* |head -5
-rw-r--r-- 1 12859 Aug 13 01:02 /usr/share/doc/git/RelNotes/2.3.0.txt
-rw-r--r-- 1  1998 Aug 13 01:02 /usr/share/doc/git/RelNotes/2.3.1.txt
-rw-r--r-- 1  3009 Aug 13 01:02 /usr/share/doc/git/RelNotes/2.3.2.txt
-rw-r--r-- 1  1522 Aug 13 01:02 /usr/share/doc/git/RelNotes/2.3.3.txt
-rw-r--r-- 1  1150 Aug 13 01:02 /usr/share/doc/git/RelNotes/2.3.4.txt


(*bloat) Like from 21.1M to 12.7M (as of version 2.0~) just by packing
   .deb-s w/xz -9e.  And now with the symlinks patch - from 12.5 MB to
   5.2 MB (@ xz -9e; 6.4M @ xz -1e) in total resulting binary packages
   size.  From 25.6 MB (2.5.3-1 @ unstable) to 18.5 MB in installed
   size for a git package.  Yes, that is 38% or 2.4x bloat in current
   Debian packaging!

   Yet more: 615 KB to _1_KB_ in installed size of git-all package as
   an extreme example.