Re: Reverting an uncommitted revert
- From
Junio C Hamano <gitster@pobox.com>
- Date
- May 20, 2009, 17:50 UTC
- Message-ID
- <7vfxezzms0.fsf@alter.siamese.dyndns.org>
- In-Reply-To
- <20090520032139.GB10212@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
Show 16 quoted lines
> Related to this, I have wondered if it might be useful to have an "index
> reflog". If I do something like this:
>
> $ git add foo
> $ hack hack hack
> $ git add foo
>
> Then the first added state of "foo" is available in the object database,
> but it is not connected to the name "foo" in any way, which makes it
> much harder to find. If we had a reflog pointing to trees representing
> the index state after each change, then it would be simple (you could
> look at "INDEX@{1}:foo" or similar).
>
> I don't know if the performance is an issue. We are writing an extra
> tree every time we touch the index, but in many cases you are already
> writing a blob.It is not just "an extra tree every time". For example, in the kernel repository, one of the path that is deepest [*1*] (i.e. whose modification affects the most number of trees) is:
arch/cris/include/arch-v32/mach-a3/mach/hwregs/iop/asm/iop_reg_space_asm.h
If you modify this file and then "git add", and if you write-tree the index at that point, you need to write a tree object for ".", arch/, arch/cris, ..., arch/cris/include/arch-v32/mach-a3/mach/hwregs/iop/asm, 10 trees in total (if I am counting them right ;-).
If your cache-tree is fresh (and if you "git write-tree" every time you "git add", that will make it stay fresh), you do not have to recompute object names of other 1728 tree objects (they are unchanged) [*2*], which should help somewhat, but the majority of time is spent in the I/O (and perhaps slow fsync on ext3 ;-) of writing these 10 tree objects [*3*].
People like Shawn who work with Java projects, where the tree hierarchy tends to be (unnecessary) deep with prefixes like org/spearce/jgit due to the namespace issues will have bigger overhead than a relatively shallow project like git.git itself.
[Footnotes]
*1* You can find it out yourself with...
git ls-files "$(
git ls-files |
sed -e 's|[^/]||g' |
sort -u |
tail -n 1 |
sed -e 's|/|*/|g' -e 's/$/*/'
)" | head -n 1*2* The total number of tree objects in a commit is...
echo $(git ls-tree -r -d HEAD | wc -l) 1 + p | dc
*3* write-tree with or without help from cache-tree in the kernel repository with a hot cache (we are talking about running "git write-tree" every time you do "git add" so the cold cache case does not matter) looks like this:
$ l=arch/cris/include/arch-v32/mach-a3/mach/hwregs/iop/asm/iop_reg_space_asm.h $ echo >>$l && git add $l $ /usr/bin/time git write-tree 04bc92c40a5d0f0d44e162e140cb00964a52046b 0.02user 0.01system 0:00.03elapsed 102%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+6387minor)pagefaults 0swaps
$ git reset --hard
$ echo >>$l && git add $l $ /usr/bin/time git write-tree --ignore-cache-tree 04bc92c40a5d0f0d44e162e140cb00964a52046b 0.13user 0.04system 0:00.17elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+5336outputs (0major+17141minor)pagefaults 0swaps
(The numbers are from my Athlon(tm) 64 X2 3800+ with slow IDE disks).