* Re: git guidance
From: Al Boldi @ 2007-11-29 5:27 UTC (permalink / raw)
To: linux-kernel; +Cc: git
In-Reply-To: <200711282130.12864.a1426z@gawab.com>
Jakub Narebski wrote:
> Al Boldi wrote:
> > Johannes Schindelin wrote:
> >> By that definition, no SCM, not even CVS, is transparent. Nothing
> >> short of unpacked directories of all versions (wasting a lot of disk
> >> space) would.
> >
> > Who said anything about unpacking?
> >
> > I'm talking about GIT transparently serving a Virtual Version Control
> > dir to be mounted on the client.
>
> Are you talking about something like (in alpha IIRC) gitfs?
>
> http://www.sfgoth.com/~mitch/linux/gitfs/
This looks like a good start.
> Besides, you can always use "git show <revision>:<file>". For example
> gitweb (and I think other web interfaces) can show any version of a file
> or a directory, accessing only repository.
Sure, browsing is the easy part, but Version Control starts when things
become writable.
Thanks for the link!
--
Al
^ permalink raw reply
* Re: Some git performance measurements..
From: Junio C Hamano @ 2007-11-29 5:17 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <alpine.LFD.0.9999.0711281747450.8458@woody.linux-foundation.org>
Linus Torvalds <torvalds@linux-foundation.org> writes:
> Less than a hundredth of a second may not sound much, but when we have
> 1700+ directories in the kernel trees, doing that for each possible
> .gitignore file is really really expensive!
The only thing that wants to use excluded() in the unpack_trees()
codepath is the code to allow overwriting an existing, untracked file in
verify_absent(). When we find an untracked file at the same path as we
are just trying to check out a file, we allow overwriting it only if
that file is "ignored".
But the way the unpack_trees_rec() and the gitignore handling in dir.c
are structured currently means we do push/pop exclude-per-directory
stack as we enter and leave a new subdirectory. We do not do this
lazily on demand.
The newer gitattributes subsystem maintains a similar per-directory data
structure but this is purely done on-demand; until somebody asks "what
are the attrs for this path", we do not read .gitattributes file. We
should be able to restructure exclude-per-directory code in a similar
way.
^ permalink raw reply
* Re: Some git performance measurements..
From: Linus Torvalds @ 2007-11-29 4:32 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Git Mailing List
In-Reply-To: <alpine.LFD.0.99999.0711282244190.9605@xanadu.home>
On Wed, 28 Nov 2007, Nicolas Pitre wrote:
>
> Tree objects aren't all together. Related blob objects are interlaced
> with those tree objects.
Yeah, I noticed that a few minutes after saying this.
> But for a checkout that should actually correspond to a nice linear
> access.
For the initial check-out, yes. But the thing I timed was just a plain
"git checkout", which won't actually do any of the blobs if they already
exist checked-out (which I obviously had), which explains the non-dense
patterns.
The reason I care about "git checkout" (which is totally uninteresting in
itself) is that it is a trivial use-case that fairly closely approximates
two common cases that are *not* uninteresting: switching branches with
most files unaffected and a fast-forward merge (both of which are the
"two-way merge" special case).
I also suspect it is pretty close to a real three-way merge (again, with
just a few files changed).
IOW, there's a lot of these "tree operations" that actually leave 99% of
the tree totally unchanged, at least in the kernel. Even a fairly big
merge tends to change just a few hundred files. And when there are 23,000
files in the tree, a few hundred files is a fairly small percentage!
So it's actually fairly common to have "git checkout"-like behaviour with
no blobs needing to be updated, and the "initial checkout" is in fact
likely a less usual case. I wonder if we should make the pack-file have
all the object types in separate regions (we already do that for commits,
since "git rev-list" kind of operations are dense in the commit).
Making the tree objects dense (the same way the commit objects are) might
also conceivably speed up "git blame" and path history simplification,
since those also tend to be "dense" in the tree history but don't actually
look at the blobs themselves until they change.
Linus
^ permalink raw reply
* Re: can't commit files that have been git add'ed because "fatal: you need to resolve your current index first"
From: Bill Priest @ 2007-11-29 4:10 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Wed, 28 Nov 2007 12:08:40 -0800
Junio C Hamano <gitster@pobox.com> wrote:
> Bill Priest <priestwilliaml@yahoo.com> writes:
>
> > I merged from one branch to another and had lots
of
> > conflicts. I've resolved a set of files from the
> > conflicts (in a directory) and did a git-add on
this
> > set of files. I wasn't able to commit these
files.
> > On IRC I was told that all files must be resolved
> > before I can commit any of them. This seems
pretty
> > limiting.
>
> You have two parallel development lines that lead to
A and B and trying
> to come up with a "merge" M:
>
> o---o---A
> / \
> ---o---o---B---M
>
> What property should the merge commit "M" have? It
must keep the
> changes made on the upper line to make it better
than B, and it must
> keep the changes made on the lower line to make it
better than A.
Ok. One thing I probably wasn't clear on is these are
two distinct
product lines that share a great amount of code;
however, much of the
code is "incompatible". The two branches will never
be "merged" into
one "mainline" as the underlying hardware is by
definition
incompatible. In theory I could use a bunch of
conditional compilation
to unify the two lines; however, this means that every
time I make a
change to one branch I have to make sure that it
doesn't break the
other one. It would have been better if the code was
modularized
better to just include different files for the two
versions;
unfortunately this is easier said than done. I guess
you could think
of it line a 2.4 kernel vs. a 2.6 kernel; but in the
same repository.
So to sum it up there are changes in branch A that
will never go into
branch B (and vice versa); however, there are a number
of changes that
need to go into both. Unfortunately the rest of my
team uses
subversion and isn't even aware that I am using git
(we recently switch
to subversion from cvs, so it is a hard sell to
management to switch
again). I'm responsible for keeping bug fixes and new
features in both
product lines and I found subversion's merging to be
utterly useless.
> Let's say both upper and lower lines of development
touched files frotz
> and xyzzy in overlapping, different ways. You try
to merge A while you
> are at B and see conflicts in these two files.
>
> Let's say you resolved frotz; the contents in frotz
is in a desired
> shape, i.e you have the changes you want from the
line led to A and the
> other line led to B. But you haven't resolved xyzzy
yet.
>
> You seem to want to make this half-resolved state as
a commit. First
> question: what contents would you want to commit for
xyzzy?
As an example there is a directory in the tree that is
a program that
runs on a PC (vs. the other stuff that runs on
embedded processors) it
shares a handful of include files w/ the embedded side
for packet
definition but it is otherwise completely separate
from the programs
that run on the embedded processors. Once I complete
merging of this
directory and it builds it is ready to go. The
remaining merges have
no effect on this PC based program. I'm not sure if
it is possible or
not but if I could merge this directory and below
(does git support
this??) it might be one way of handling it or if I
cherry-pick'ed it
that could also work. This isn't always feasible as
the other users
often check in wholesale changes into subversion as
one change set
(remember that these are former cvs users that have
lots of bad habits
to lose). It would be great if branches were created
for each
"logical" change and checked in in one changeset; this
seems to be what
git is expecting (in a perfect world this would always
be the case).
>
> If you commit the contents from B (because you
started from it), then it
> should not be recorded as a proper merge. If you
did so, merging that
> back to A would obliterate all the work done up to A
to file xyzzy:
>
> o---o---A...X
> / \ .
> ---o---o---B---*
>
> because merge base of A and * (I am marking it
differently because such
> an incomplete merge should not be made) is A, so the
result (X) will be
> the half-merge * itself (fast forward). That's not
a merge as it is not
> better than A -- you discarded improvements made to
xyzzy by people who
> built up to A.
>
> This is inherent to what a merge is. With proper
understanding of what
> a merge is, you would not feel this limiting at all.
I've used clearcase in the past and although there
were many things I
didn't like about it (big, slow, costs $$$$, network
pig, needs a super
server, etc.) it did allow commits of files at any
time and tracked the
files that were merged independently. I know that git
tracks changes
and not files; but in the end you have to pick file(s)
or pieces of
them to be committed; having the tool restrict me from
committing files
because of the way it tracks merges IS limiting IMHO.
I guess the big
difference is that in kernel land you can reject
patches until they are
broken up into "atomic" pieces (I don't really have
the option of
reversing the subversion commit and turning it into
"atomic" commits).
> Having said that, I think something like the
following _could_ be done,
> although I do not know if it makes much sense.
>
> (1) Try merge, see it conflict, resolve only a part
of it, and record
> the result as "WIP to merge in A". Do not
record it as a merge, as
> it is not. diff between B and M will contain a
squash merge of A on
> top of B minus the changes to the path xyzzy.
>
> o---o---A
> /
> ---o---o---B---M
>
> (2) Fix up the conflicts in xyzzy to resolve the
conflicts fully, and
> record the result as "Final merge of A into B".
This should be
> recorded as a merge, as the result is "keeping
changes done on both
> branches to come up with something better than
either of them."
>
> o---o---A---,
> / \
> ---o---o---B---M---N
>
> If you look at the topology a bit differently, the
above actually makes
> some sense:
>
> .---o---o---A
> / \
> ---o---o---B---M---N
>
> That is, instead of merging A into B, you made
"preparatory changes" to
> branch B in order to make it easier to merge A.
That's what the commit
> M is about.
>
> Then you merge A on top of M. In reality, because
the difference
> between B to M contains most of the squash merge of
A into B, such a
> merge N will contain many accidental clean merges.
But in git,
> accidental clean merges are not a problem (people
can apply the same
> patch to their trees and later their branches can be
merged).
>
> But "git commit" after a conflicted merge will
always create a merge,
> and there is no canned option to do multi-step merge
like the above.
>
> You can still do that by hand, by doing something
like:
>
> $ git merge --squash A
> $ resolve only partly
> $ git commit -m 'Prepare to merge A'
> $ git reset --hard
> $ git merge A
> $ resolve the rest
> $ git commit -m 'Fully merged A'
Ok. I did a git merge --squash. So I should be able
to try this.
After I resolve only partly; I'm assuming that I git
checkout HEAD any
files that I don't want yet and then do the commit?
Assuming that I
commit the partial after throwing away any merges that
I wasn't ready
to do (via git checkout HEAD); what does the "git
reset --hard" do?
> For such a multi-step merge to make sense, the
change between B---M
> should make sense by itself for people who have to
read such a history
> later. Such a half-a-squash-merge may probably not
make sense by itself
> in most cases, so I suspect the above workflow would
not be useful in
> general.
I would agree for the case where in the end you really
only have one
product; but again think like you have a 2.4 kernel
and a 2.6 kernel in
the same repository. For most embedded development
(I've been doing it
for 20+ years) there is always newer hardware that
changes processors,
add features, gets all the new development while the
"old" production
board is still shipping and in customers hands and
needs bug fixes and
the occassional new feature. It doesn't make sense to
have two
separate repositories when much of the code is the
same and is likely
to need the same fixes.
Junio,
Thanks for your time and insight; git has already
saved me
countless hours and has certainly come a long way in a
very short
time. I'll give your multi-step merge a shot and see
how well it works
for my code base. I'm sure there are better ways to
structure my code
base to get what I am looking for; but as is usually
the case the rules
of the game have changed as I have been playing it
(the old hardware
was supposed to die and never be touched again; HA
HA).
Regards,
Bill
____________________________________________________________________________________
Be a better pen pal.
Text or chat with friends inside Yahoo! Mail. See how. http://overview.mail.yahoo.com/
^ permalink raw reply
* Re: Some git performance measurements..
From: Nicolas Pitre @ 2007-11-29 3:59 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <alpine.LFD.0.9999.0711281852160.8458@woody.linux-foundation.org>
On Wed, 28 Nov 2007, Linus Torvalds wrote:
> - the index accesses are much more "random": the initial 256-way fan-out
> followed by the binary search causes the access patterns to look very
> different:
>
> 0: 28367707
> 136: 18867574
> 140: 221280
> 141: 745890
> 142: 284427
> 143: 338
> 381: 9787459
> 377: 394
> 375: 255
> 376: 248
> 3344: 29885989
> 3347: 334
> 3346: 255
> 3684: 7251911
> 1055: 12954064
> 1052: 386
> 1050: 251
> 1049: 240
> 1947: 10501455
> 1944: 382
> 1946: 262
>
> where it doesn't even read-ahead at all in the beginning (because it
> looks entirely random), but the kernel eventually *does* actually go
> into read-ahead mode pretty soon simply because once it gets into the
> binary search thing, the data entries are close enough to be in
> adjacent pages, and it all looks ok.
Did you try with version 2 of the pack index? Because it should have
somewhat better locality as the object SHA1 and their offset are split
into separate tables.
> That said, I think there's something subtly wrong in our pack-file
> sorting, and it should be more contiguous when we just do tree object
> accesses on the top commit. I was really hoping that all the top-level
> trees should be written entirely together, but I wonder if the "write out
> deltas first" thing causes us to have those big gaps in between.
Tree objects aren't all together. Related blob objects are interlaced
with those tree objects. But for a checkout that should actually
correspond to a nice linear access.
And deltas aren't written first, but rather their base object. And
because deltas are based on newer objects, in theory the top commit
shouldn't have any delta at all, and the second commit should have all
the base objects for its deltas already written out a part of the first
commit. At least that's what a perfect data set would produce. Last
time I checked, there was about 20% of the deltas that happened to be in
the other direction, i.e. the deltified object was younger than its base
object, most probably because the new version of the file shrunk instead
of growing which is against the assumption in the delta search
object sort. But again, because the base object is needed to resolve
the delta, it will be read anyway.
Nicolas
^ permalink raw reply
* Re: [PATCH] receive-pack: allow deletion of corrupt refs
From: Petr Baudis @ 2007-11-29 3:55 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, gitster
In-Reply-To: <Pine.LNX.4.64.0711290101420.27959@racer.site>
Hi,
On Thu, Nov 29, 2007 at 01:02:53AM +0000, Johannes Schindelin wrote:
> Occasionally, in some setups (*cough* forks on repo.or.cz *cough*) some
> refs go stale, e.g. when the forkee rebased and lost some objects needed
> by the fork. The quick & dirty way to deal with those refs is to delete
> them and push them again.
repo.or.cz now has this patch. I'm also repacking the kernel
repository which is in a pretty awful state, I'm hoping that will fix
some of the heavy performance problems repo.or.cz is hitting currently.
--
Petr "Pasky" Baudis
We don't know who it was that discovered water, but we're pretty sure
that it wasn't a fish. -- Marshall McLuhan
^ permalink raw reply
* [PATCH/RFC] Teach repack to optionally retain otherwise lost objects
From: Johannes Schindelin @ 2007-11-29 3:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
In-Reply-To: <7v7ikfuxfk.fsf@gitster.siamese.dyndns.org>
When specifying --attic=<prefix>, the objects that would be lost when
calling repack with -d will be put into a packfile (or multiple
packfiles), using the file name prefix <prefix>.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
This implements the idea of Hannes.
The plan for repo.or.cz is now to invoke repack with
"--attic=attic" and copied attic-*.{idx,pack} to all the forks'
object stores, then delete the original attic-*{.idx,pack}.
The beauty of that approach is that the order in which the
repositories are repacked is no longer important.
This patch is marked RFC since there is a severe bottleneck
here: the new pack's index is sorted and made unique and every
SHA-1 displayed twice, then the old pack's index is sorted and
made unique. Then the combined result is sorted and only the
now-unique SHA-1s are actually packed.
(The sort is not necessary if there is only _one_ pack.
However, we cannot guarantee that.)
Of course, this is quick 'n dirty, and the price to be paid
is a substantial performance hit: in my tests, linux-2.6.git
needed half a second to show its pack's index, but that
sed 's/^.* //' | sort | uniq | sed p mantra needs 19 seconds.
The obvious thing is to exploit the fact that the pack indices
are already sorted:
I started patch git-show-index so it takes an argument
--missing-objects, followed by the new pack index file names,
followed by --, followed be the old pack index file names.
Then it would traverse all of them simultaneously, outputting
only the SHA-1s of objects that are in an old pack, but not
in any of the new packs.
Two issues: there might be a whole lot of pack files (Pasky
told me today that in one instance there were 416 pack files!)
and that might well exceed the maximum number of open files.
Second issue: there are two different pack index formats, and
the code is not easily refactored AFAICT.
Probably a better method would be not to read the files
simultaneously, but fill a "struct decorate *" with objects
(which can be faked, as we do not really need to parse them)
of the new packs, and then only use decorate_lookup() to determine
for all old packs' objects if they are present in the new ones.
The latter approach would allow for a relatively easy refactoring
of show-index.c; just provide a callback for each entry.
However, I am way too tired today to do it.
Besides, a completely different idea just struck me: before
repacking, .git/objects/pack/* could be _hard linked_ to the
forkee's object stores. Then nothing in git-repack's code
needs to be changed.
Oh, well. I just wasted 1.5 hours.
Documentation/git-repack.txt | 4 +++
git-repack.sh | 40 +++++++++++++++++++++++++++++++++----
t/t5303-repack-attic.sh | 44 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 5 deletions(-)
create mode 100644 t/t5303-repack-attic.sh
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index 12e2079..ec2c2bf 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -84,6 +84,10 @@ OPTIONS
If specified, multiple packfiles may be created.
The default is unlimited.
+--attic=<prefix>::
+ Put all objects that would/will be lost when running with `-d`
+ into its own packfile(s), with file name prefix `<prefix>`.
+
Configuration
-------------
diff --git a/git-repack.sh b/git-repack.sh
index e18eb3f..f83d6f0 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -18,12 +18,13 @@ window= size of the window used for delta compression
window-memory= same as the above, but limit memory size instead of entries count
depth= limits the maximum delta depth
max-pack-size= maximum size of each packfile
+attic= pack no-longer-packed used objects into an "attic" pack
"
SUBDIRECTORY_OK='Yes'
. git-sh-setup
no_update_info= all_into_one= remove_redundant= keep_unreachable=
-local= quiet= no_reuse= extra=
+local= quiet= no_reuse= extra= attic=
while test $# != 0
do
case "$1" in
@@ -37,6 +38,8 @@ do
-l) local=--local ;;
--max-pack-size|--window|--window-memory|--depth)
extra="$extra $1=$2"; shift ;;
+ --attic)
+ attic="$2"; shift ;;
--) shift; break;;
*) usage ;;
esac
@@ -119,6 +122,36 @@ for name in $names ; do
rm -f "$PACKDIR/old-pack-$name.pack" "$PACKDIR/old-pack-$name.idx"
done
+new_existing=
+for e in $existing
+do
+ case "$ fullbases " in
+ *" $e "*) ;;
+ *)
+ new_existing="$new_existing $e"
+ ;;
+ esac
+done
+existing="$new_existing"
+
+if test ! -z "$attic"
+then
+ # Find the objects which were in the existing packs, but are no
+ # longer in the new ones.
+ #
+ # This could be much more efficient.
+ (for name in $names
+ do
+ git show-index < $PACKDIR/pack-$name.idx
+ done | sed 's/^.* //' | sort | uniq | sed p &&
+ for e in $existing
+ do
+ git show-index < "$PACKDIR/$e.idx"
+ done | sed 's/^.* //' | sort | uniq) | sort | uniq -u |
+ git pack-objects --non-empty "$attic" ||
+ die "Could not create attic '$attic'."
+fi
+
if test "$remove_redundant" = t
then
# We know $existing are all redundant.
@@ -128,10 +161,7 @@ then
( cd "$PACKDIR" &&
for e in $existing
do
- case " $fullbases " in
- *" $e "*) ;;
- *) rm -f "$e.pack" "$e.idx" "$e.keep" ;;
- esac
+ rm -f "$e.pack" "$e.idx" "$e.keep"
done
)
fi
diff --git a/t/t5303-repack-attic.sh b/t/t5303-repack-attic.sh
new file mode 100644
index 0000000..9777748
--- /dev/null
+++ b/t/t5303-repack-attic.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='repack with an attic pack'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+ echo "Ten weary, footsore wanderers," > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ echo "all in a woeful plight," >> file &&
+ test_tick &&
+ git commit -m second file &&
+ echo "sought shelter in a wayside-inn" >> file &&
+ test_tick &&
+ git commit -m third file &&
+ echo "one dark and lonely night." >> file &&
+ test_tick &&
+ git commit -m fourth file &&
+ echo ">>Nine rooms, no more<<, the landlord said," >> file &&
+ test_tick && git commit -m fifth file &&
+ git repack -a -d &&
+ ! ls .git/objects/??/*
+
+'
+
+test_expect_success 'create attic pack' '
+
+ LAST_VERSION=$(git rev-parse --verify HEAD:file) &&
+ git reset --hard HEAD^ &&
+ rm .git/logs/HEAD .git/logs/refs/heads/master &&
+ git cat-file blob $LAST_VERSION &&
+ git repack --attic=attic -a -d &&
+ ! git cat-file blob $LAST_VERSION &&
+ test -f attic-*.idx &&
+ cat attic-*.idx | git show-index | grep $LAST_VERSION
+
+'
+
+test_done
--
1.5.3.6.2066.g09421
^ permalink raw reply related
* Re: [PATCH v2] Teach 'git pull' about --rebase
From: Nicolas Pitre @ 2007-11-29 3:23 UTC (permalink / raw)
To: J. Bruce Fields
Cc: Johannes Schindelin, Junio C Hamano, Lars Hjemli, Steven Grimm,
Linus Torvalds, git
In-Reply-To: <20071128223339.GF7376@fieldses.org>
On Wed, 28 Nov 2007, J. Bruce Fields wrote:
> On Wed, Nov 28, 2007 at 09:58:52PM +0000, Johannes Schindelin wrote:
> > Not so sure about that. We already have too many commands, according to
> > some outspoken people, and this would add to it.
>
> What they're really complaining about is the size and complexity of the
> interface, and the lack of a clearly identified subset for them to learn
> first.
Well, the idea is that once all those plumbing commands are hidden away
in some libexec dir, that makes a _lot_ of breathing room for a few
more porcelain commands if needed.
Nicolas
^ permalink raw reply
* Re: [PATCH] Move all dashed form git commands to libexecdir
From: Nguyen Thai Ngoc Duy @ 2007-11-29 3:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jan Hudec, Johannes Schindelin, git
In-Reply-To: <7vfxyq2c9b.fsf@gitster.siamese.dyndns.org>
On Nov 29, 2007 6:14 AM, Junio C Hamano <gitster@pobox.com> wrote:
>
> "Nguyen Thai Ngoc Duy" <pclouds@gmail.com> writes:
>
> > On Nov 28, 2007 8:13 AM, Junio C Hamano <gitster@pobox.com> wrote:
> >> In case somebody is thinking about 36e5e70e0f40 (Start deprecating
> >> "git-command" in favor of "git command"), that is a somewhat different
> >> issue. What Linus suggested is not installing git-foo link for built-in
> >> commands _anywhere_ on the filesystem. Not just "out of user's PATH".
> >> That is not deprecating dash form but removing the support for it. We
> >> need to give ample time for users to adjust to such a change.
> >
> > A little note on this one. I've been using git without builtin links
> > for a while with my git-box port. There are still some builtin fixups
> > needed. And because execv_git_cmd() always uses dash form, so it's
> > impossible to use vanilla git without builtin links.
>
> Thanks for a heads up.
>
> Would people agree with a rough roadmap like this?
>
> - v1.5.4 will ship with gitexecdir=$(bindir) in Makefile. But the
> release notes for the version will warn users that:
>
> (1) using git-foo from the command line, and
>
> (2) using git-foo from your scripts without first prepending the
> return value of "git --exec-path" to the PATH
>
> is now officially deprecated (it has been deprecated for a long time
> since January 2006, v1.2.0~149) and upcoming v1.5.5 will ship with
> the default configuration that does not install git-foo form in
> user's PATH.
>
> - Post v1.5.4, start cooking gitexecdir=$(libexecdir)/git-core, aiming
> for inclusion in v1.5.5, perhaps in Mar-Feb 2008 timeframe.
>
> - The release notes for v1.5.5 will warn users that git-foo will be
> removed in v1.6.0 for many commands and it will be merely an accident
> if some of them still work.
>
> - Post v1.5.5, start cooking the change that does not install hardlinks
> for built-in commands, aiming for inclusion in v1.6.0, by the end of
> 2008.
There won't be a stage when only porcelain git-foos are in $(bindir)?
I could stop working on the relevant patch then.
--
Duy
^ permalink raw reply
* Re: Some git performance measurements..
From: Linus Torvalds @ 2007-11-29 3:14 UTC (permalink / raw)
To: Git Mailing List
In-Reply-To: <alpine.LFD.0.9999.0711281747450.8458@woody.linux-foundation.org>
On Wed, 28 Nov 2007, Linus Torvalds wrote:
>
> Sadly, one big reason for performance downsides is actually hard to
> measure: since we mmap() all the really critical data structures (the
> pack-file index and data), it doesn't show up really well in any of the
> otherwise really useful performance tools (eg strace and ltrace), because
> the bulk of the time is actually spent not in libraries or in system
> calls, but simply on regular instructions that take a page fault.
Side note: while the ".gitignore" issue actually overshadowed everything
else for things like "git checkout" and "git merge", I do have some traces
for page faults too. They're kind of interesting, but actually show that
we do reasonably well in this area - certainly much better than if we
tried to keep things in multiple independent files.
The pack-files (both index and data) are accessed somewhat randomly, but
there is still enough locality that doing read-ahead and clustering really
does help.
So while "git checkout" actually end up reading a lot of git "tree"
objects (as many tree objects as there are .gitignore files that we try to
open unnecessarily!), we actually spend a *lot* less time on the pack-file
operations than we do on trying to do the futile ".gitignore" opens in
every directory.
If somebody cares, I do have the page fault traces on those things for the
same "git checkout" that had the horrid .gitignore behaviour. What's
interesting is:
- the pack-file really does get accessed in nice increasing patterns for
the top-of-tree. So the fact that we sort objects "topologically" does
actually seem to work pretty well (yeah, it was obvious, but it's nice
to have a real page fault trace that shows the effect!)
The accesses seemed to be *totally* ordered. There were obvously gaps
(ie they weren't *dense*, since we only looked at one version of the
trees in "git checkout"), but at the same time, it certainly wasn't
random or causing any horrible seeking back-and-forth.
- we're *reasonably* dense in pack-file accesses. Not wonderful, but not
horrible. That in turn means that read-ahead kicks in and works ok. The
pattern for the pack-file hat I caught looks like this (the format is
"pageindex: cycles-to-fill-in-kernel"):
6810: 15202545
6811: 353
6812: 267
6813: 476
6814: 559
6826: 1086510
6878: 13948057
6894: 9756446
6896: 300
6899: 307
6903: 319
6907: 293
6910: 666120
6912: 401
6913: 330
6916: 401
6918: 303
6919: 330
6931: 784373
6943: 405
6944: 187
6945: 315
...
and here you can see that read-ahead works fine about 60% of the time,
with most pages taking just 300-500 CPU cycles (no actual IO, of
course!) to find/lookup, but then when there are discontinuities we
have the cost of the real IO, and the cost for those obviously then
jumps into the tens of millions of cycles (ie we're talking
several milliseconds).
- the index accesses are much more "random": the initial 256-way fan-out
followed by the binary search causes the access patterns to look very
different:
0: 28367707
136: 18867574
140: 221280
141: 745890
142: 284427
143: 338
381: 9787459
377: 394
375: 255
376: 248
3344: 29885989
3347: 334
3346: 255
3684: 7251911
1055: 12954064
1052: 386
1050: 251
1049: 240
1947: 10501455
1944: 382
1946: 262
where it doesn't even read-ahead at all in the beginning (because it
looks entirely random), but the kernel eventually *does* actually go
into read-ahead mode pretty soon simply because once it gets into the
binary search thing, the data entries are close enough to be in
adjacent pages, and it all looks ok.
As a result, by the end of the run, all the index file pages have been
cached, and we're getting uniformly low numbers (ie in the hundreds of
cycles, not millions):
...
490: 810
489: 352
488: 334
2254: 907
91: 484
3580: 776
962: 806
522: 761
2494: 514
805: 653
177: 495
176: 375
2861: 439
649: 660
648: 518
...
so the pack index file access patterns are much less predictable, but
since the pack index is so dense and relatively small, that doesn't end
up being a problem in the long run, and only in the beginning do we pay
a highish cost for having to read it into memory.
In other words: we do ok. I think we could do better (and an SSD would
certainly help, since we're never going to do long and 100% contiguous
IO), but I was expecting to see *big* trouble, and it really wasn't that
horrid.
That said, I think there's something subtly wrong in our pack-file
sorting, and it should be more contiguous when we just do tree object
accesses on the top commit. I was really hoping that all the top-level
trees should be written entirely together, but I wonder if the "write out
deltas first" thing causes us to have those big gaps in between.
Linus
^ permalink raw reply
* Some git performance measurements..
From: Linus Torvalds @ 2007-11-29 2:49 UTC (permalink / raw)
To: Git Mailing List
So, today, I finally started looking a bit at one of the only remaining
performance issues that I'm aware of: git behaviour under cold-cache and
particularly with a slow laptop harddisk isn't as nice as I wish it should
be.
Sadly, one big reason for performance downsides is actually hard to
measure: since we mmap() all the really critical data structures (the
pack-file index and data), it doesn't show up really well in any of the
otherwise really useful performance tools (eg strace and ltrace), because
the bulk of the time is actually spent not in libraries or in system
calls, but simply on regular instructions that take a page fault.
Not a lot that I see we can do about that, unless we can make the
pack-files even denser.
But one very interesting thing I did notice: some loads open the
".gitignore" files *way* too much. Even in cases where we really don't
care. And when the caches are cold, that's actually very expensive, even
if - and perhaps _especially_when_ - the file doesn't exist at all (ie
some filesystems that don't use hashes will look through the whole
directory before they see that it's empty).
An example of totally unnecessary .gitignore files is what a plain "git
checkout" with no arguments ends up doing:
git read-tree -m -u --exclude-per-directory=.gitignore HEAD HEAD
which is *really* quite expensive, and a lot of the cost is trying to open
a .gitignore file in each subdirectory that are never even used.
Just to give a feel for *how* expensive that stupid .gitignore thing is,
here's a pretty telling comparison of using --exclude-per-directory and
not using it:
With totally pointless --exclude-per-directory (aka "git checkout"):
[torvalds@woody linux]$ time git read-tree -m -u --exclude-per-directory=.gitignore HEAD HEAD
real 0m13.475s
user 0m0.108s
sys 0m0.228s
Without:
[torvalds@woody linux]$ time git read-tree -m -u HEAD HEAD
real 0m5.923s
user 0m0.100s
sys 0m0.044s
now, I'm not all that happy about that latter six-second time either, but
both of the above numbers were done with completely cold caches (ie after
having done a "echo 3 > /proc/sys/vm/drop_caches" as root).
With hot caches, both of the numbers are under a tenth of a second (in
fact, they are very close: 0.092s and 0.096s respectively), but the
cold-cache case really shows just how horrible it is to (try to) open many
files.
Doing an open (or an lstat) on individual files will be a totally
synchronous operation, with no room for read-ahead etc, so even if your
disk in *theory* gets 80MB/s off the platter, when you do an open() or
lstat(), you're basically doing three or four small data-dependent IO
operations, and as a result even a fast disk will take almost a hundredth
of a second per open/lstat operation.
Less than a hundredth of a second may not sound much, but when we have
1700+ directories in the kernel trees, doing that for each possible
.gitignore file is really really expensive!
(Doing an "lstat()" of each file is much cheaper in comparison, because at
least you'll get several director entries and probably a few related
inodes with each IO. But opening just _one_ file per directory like the
.gitignore code does, really kills your IO throughput)
Now, timings like these are why I'm looking forward to SSD's. They may
have the same throughput as a disk, but they can do thousands of dependent
IOPS, and help latency-bound cases like this by an order of magnitude. But
when we're doing those .gitignore file reads totally unnecassarily, that
just hurts..
Linus
^ permalink raw reply
* Re: Adding Git to Better SCM Initiative : Comparison
From: Jakub Narebski @ 2007-11-29 2:26 UTC (permalink / raw)
To: git; +Cc: Robin Rosenberg
In-Reply-To: <200711282339.59938.jnareb@gmail.com>
Jakub Narebski wrote:
> To do that, I need to fill in information about Git. Most
> of questions / items didn't give much problem, but there
> are a few on which I would like your input.
By the way, below is patch with the information I have filled.
Check out the TO DO items.
diff --git a/src/comparison/scm-comparison.xml b/src/comparison/scm-comparison.xml
index b459747..6f84190 100644
--- a/src/comparison/scm-comparison.xml
+++ b/src/comparison/scm-comparison.xml
@@ -38,6 +38,9 @@ TODO:
<impl id="darcs">
<name>Darcs</name>
</impl>
+ <impl id="git">
+ <name>Git</name>
+ </impl>
<impl id="mercurial">
<name>Mercurial</name>
</impl>
@@ -106,6 +109,7 @@ TODO:
<s id="svk">Commits are atomic.</s>
<s id="aegis">Commits are atomic.</s>
<s id="bitkeeper">Yes (but need to verify)</s>
+ <s id="git">Yes.</s>
<s id="mercurial">Yes.</s>
<s id="monotone">Yes.</s>
<s id="opencm">Yes. Commits are atomic.</s>
@@ -142,6 +146,11 @@ TODO:
<s id="darcs">Yes. Renames are supported.</s>
<s id="bitkeeper">Yes. Renames are supported.</s>
<s id="aegis">Yes. Renames are supported.</s>
+ <s id="git">
+ N/A. Git does not track renames, but detects renames
+ and copies. You can follow history of file using
+ 'git log --follow'.
+ </s>
<s id="mercurial">Yes. Renames are supported.</s>
<s id="monotone">Yes. Renames are supported.</s>
<s id="opencm">Yes. Renames are supported</s>
@@ -214,6 +223,11 @@ TODO:
Yes. Copies are supported.
</s>
<s id="aegis">No. Copies are not supported.</s>
+ <s id="git">
+ N/A. Git does not track copies, but detects renames
+ and copies. You can follow history of file using
+ 'git log -C --follow'.
+ </s>
<s id="mercurial">Yes. Copies are supported</s>
<s id="monotone">Yes. Copies are supported</s>
<s id="opencm">No. Copies are not supported.</s>
@@ -267,6 +281,7 @@ TODO:
<s id="darcs">Yes.</s>
<s id="bitkeeper">Yes.</s>
<s id="aegis">Yes.</s>
+ <s id="git">Yes.</s>
<s id="mercurial">Yes.</s>
<s id="monotone">Yes.</s>
<s id="opencm">No.</s>
@@ -313,6 +328,7 @@ TODO:
<s id="darcs">Yes.</s>
<s id="bitkeeper">Yes.</s>
<s id="aegis">Yes.</s>
+ <s id="git">Yes.</s>
<s id="mercurial">Yes.</s>
<s id="monotone">Yes.</s>
<s id="opencm">No.</s>
@@ -373,6 +389,10 @@ TODO:
<s id="svk">
Same as subversion.
</s>
+ <s id="git">
+ Partial (?). It is possible to lock down repository
+ (access to branches and tags) using hooks.
+ </s>
<s id="mercurial">
Yes. It is possible to lock down repositories,
subdirectories, or files using hooks.
@@ -455,6 +475,9 @@ TODO:
<s id="darcs">
Yes. Changesets are supported.
</s>
+ <s id="git">
+ Yes. Changesets are supported.
+ </s>
<s id="mercurial">
Yes. Changesets are supported.
</s>
@@ -509,6 +532,7 @@ TODO:
<s id="arch">Not in the command line client, but ViewARCH,
a web-interface for Arch, has it.</s>
<s id="darcs">Yes. (darcs annotate)</s>
+ <s id="git">Yes. (git blame, git gui blame)</s>
<s id="mercurial">Yes. (hg annotate)</s>
<s id="monotone">Yes, as of version 0.19.</s>
<s id="aegis">Yes. aeannotate</s>
@@ -570,6 +594,9 @@ TODO:
whole.
</s>
<s id="aegis">No. All changes are made repository-wide.</s>
+ <s id="git">
+ No. All changes are made repository-wide.
+ But you can use submodules / subrpoject support for that.</s>
<s id="mercurial">
It is possible to commit changes only in a subset of the
tree. There are plans for partial checkouts.
@@ -636,6 +663,10 @@ TODO:
Yes, using "darcs whatsnew".
</s>
<s id="aegis">Yes. Using aediff</s>
+ <s id="git">
+ Yes. Using git diff.
+ Note that git uses staging area for commits (index).
+ </s>
<s id="mercurial">Yes. Using hg diff.</s>
<s id="monotone">Yes. In a similar fashion to CVS.</s>
<s id="opencm">Yes. Using cm diff</s>
@@ -681,6 +712,10 @@ TODO:
<s id="darcs">
No.
</s>
+ <s id="git">
+ No. But you can tag (with description) given contents
+ of a file (blob).
+ </s>
<s id="mercurial">
No.
</s>
@@ -782,6 +817,15 @@ TODO:
and the client contains a help tool that offers
an integrated help system.
</s>
+ <s id="git">
+ Medium. There's Git User's Manual, manpages, some
+ technical documentation and some howtos. All
+ documentation is also available online in HTML format;
+ there is additional information (including beginnings
+ of FAQ) on git wiki.
+ Nevertheles one of complaints in surveys is insufficient
+ or fragmented documentation.
+ </s>
<s id="mercurial">
Very good. There's an overview and tutorial on the
web site, and integrated help for every command.
@@ -894,6 +938,14 @@ TODO:
to install the subversion perl bindings and a few modules
from CPAN.
</s>
+ <s id="git">
+ TO DO. RPMs and deb packages for Linux. msysGit and
+ Cygwin for Win32 - Git requires POSIX shell, Perl,
+ and POSIX utilities for some commands (builtin).
+ Autoconf to generate Makefile configuration; ready
+ generic configuration for many OS. Compiling docs
+ requires asciidoc and xmlto toolchain, but prebuild.
+ </s>
<s id="mercurial">
Excellent. Binary packages are available for all
popular platforms. Building from source requires
@@ -1006,6 +1058,13 @@ TODO:
but since the model is different most commands are
unique.
</s>
+ <s id="git">
+ TO DO.
+ Tries to follow CVS conventions, but deviates where there
+ is a different design.
+ Large command set divided into plumbing (low lewel, to be
+ used in scripts) and porcelain (high level).
+ </s>
<s id="mercurial">
Tries to follow CVS conventions, but deviates where there
is a different design.
@@ -1106,6 +1165,10 @@ TODO:
There exists some HTTP-functionality, but it is quite
limited.
</s>
+ <s id="git">
+ Good. Uses HTTPS (with WebDAV) or ssh for push,
+ HTTP, FTP, ssh or custom protocol for fetch.
+ </s>
<s id="mercurial">
Excellent. Uses HTTP or ssh. Remote access also
works safely without locks over read-only network
@@ -1203,6 +1266,10 @@ TODO:
Very good. Supports many UNIXes, Mac OS X, and Windows,
and is written in a portable language.
</s>
+ <s id="git">TO DO.
+ Good. Portable across all POSIX systems.
+ There exists Win32 binary using MinGW.
+ </s>
<s id="mercurial">
Excellent. Runs on all platforms supported by
Python. Repositories are portable across CPU
@@ -1300,6 +1367,9 @@ TODO:
is included in the distribution.
</s>
<s id="aegis">Yes.</s>
+ <s id="git">
+ Yes. The web interface is a bundled component.
+ Other web interfaces: cgit, wit, git-php</s>
<s id="mercurial">Yes. The web interface is a bundled component.</s>
<s id="monotone">No.</s>
<s id="opencm">No.</s>
@@ -1373,6 +1443,11 @@ TODO:
<s id="aegis">
There is tkaegis.
</s>
+ <s id="git">RO DO
+ Bundled history viewer gitk and commit tool git-gui,
+ both use Tcl/Tk. There is also qgit (Qt) and Giggle
+ (GTK+).
+ </s>
<s id="mercurial">
History viewing available with hgit extension;
check-in extension (hgct) makes committing easier.
@@ -1453,6 +1528,7 @@ TODO:
GNU GPL (open-source)
</s>
<s id="svk">Perl License. (open source)</s>
+ <s id="git">GNU GPL (open source)</s>
<s id="mercurial">GNU GPL (open source)</s>
<s id="monotone">GNU GPL (open source)</s>
<s id="opencm">
--
Jakub Narebski
Poland
^ permalink raw reply related
* Re: [PATCH] Make Git accept absolute path names for files within the work tree
From: Junio C Hamano @ 2007-11-29 2:05 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <200711290215.34237.robin.rosenberg@dewire.com>
Robin Rosenberg <robin.rosenberg@dewire.com> writes:
> Maybe we should have a boolean indicating whether the arguments refer
> to filespecs or not to make this clear or rewite the mingw fallouts in
> some other way.
I wondered the same, but my vote would be to make them separate
functions. You would need a function to abstract out pasting of paths
to ease MinGW people even without this "ah absolute -- let's make it
relative to work tree first" hack, anyway.
^ permalink raw reply
* Re: Adding Git to Better SCM Initiative : Comparison
From: Robin Rosenberg @ 2007-11-29 1:48 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <200711282339.59938.jnareb@gmail.com>
onsdag 28 november 2007 skrev Jakub Narebski:
> I'd like to add Git to comparison table of SCMs at Better SCM
> Initiative site:
> http://better-scm.berlios.de
>
> To do that, I need to fill in infomration about Git. Most
> of questions / items didn't give much problem, but there
> are a few on which I would like your input.
>
> (Yes, I know that such SCM comparisons are usually biased towards the
> idea of what are most important features of a version control system.
> Nevertheless...)
[...]
> 4. Repository Permissions
>
> Is it possible to define permissions on access to different
> parts of a remote repository? Or is access open for all?
>
> "Partial (?). It is possible to lock down repository
> (access to branches and tags) using hooks."
>
> I don't know if it is possible to do finer level ACLs, i.e. if it
> is possible to lock subdirectories or files in Git. Although for
> distributed SCMs ACL doesn't matter much: check diffstat and merge or
> not from trusted people. We have "network of trust" (BTW. Karl Fogel
> in OSSBook recommends 'soft' control of access control to repository,
> on social rather than on technical level).
I think what is most interesting here is access to content for which git has
just about nothing worth mentioning, Just admit it. "Truth in advertising".
I did start doing this so here's my version (pre-msysgit). Please try to bring up the defintion
of "atomic" again with the author. I did complain a little but nothing happened. The issue is
that Clearcase is listed as having "atomic" commits which is not true for any usable definition
of atomic in SCM context. With the definition in use there I think CVS should be considered
having atomic commits too, at least I've never seen a half-committed file there.
% svn diff
Index: src/comparison/scm-comparison.xml
===================================================================
--- src/comparison/scm-comparison.xml (revision 290)
+++ src/comparison/scm-comparison.xml (arbetskopia)
@@ -71,6 +71,9 @@
<impl id="ls-sync">
<name>LibreSource Synchronizer</name>
</impl>
+ <impl id="git">
+ <name>Git</name>
+ </impl>
</implementations>
<timestamp>
$Id$
@@ -182,6 +185,13 @@
needs to be up-to-date before doing a rename/move operation.
This operation will be committed directly.
</s>
+ <s id="git">
+ Yes (or no depending on interpretation). Git typically detects
+ renames and copies based on content regardless of whether the
+ committer indicated the fact. The detection is content based
+ rather than file-id based. There is explicit rename too, but
+ it is not used much.
+ </s>
</compare>
</section>
<section id="copy">
@@ -236,6 +246,10 @@
limitations in Windows environments)
</s>
<s id="ls-sync">No, copies will start there own history.</s>
+ <s id="git">Yes(or no depending on interpretation). Git detects
+ copies and moves based on content. It does not track
+ history on a file-id based scheme.
+ </s>
</compare>
</section>
<section id="repos_clone">
@@ -288,6 +302,11 @@
Yes, but is not documented and its based on the dataflow feature of the
LibreSource Synchronizer.
</s>
+ <s id="git">
+ Yes. This is a fundamental part of using Git. A Git user typically always
+ has a full copy of the entire repostory (well compressed) that is initialized
+ using a clone command.
+ </s>
</compare>
</section>
<section id="push">
@@ -331,6 +350,7 @@
<s id="cmsynergy">Yes, as long as you have the (more expensive) Distributed package.</s>
<s id="clearcase">Yes, using Clearcase Multisite.</s>
<s id="ls-sync">Yes, it's what we call a dataflow.</s>
+ <s id="git">Yes. This is a fundamental part of using Git.</s>
</compare>
</section>
<section id="permissions">
@@ -417,7 +437,8 @@
multi-platform environments.
</s>
<s id="ls-sync">Permissions are set for the whole repository or branch.</s>
- </compare>
+ <s id="git">No, but bad changes can be reverted before they are published.</s>
+ </compare>
</section>
<section id="changesets">
<title>Changesets' Support</title>
@@ -490,6 +511,11 @@
Partial support. There are implicit changeset that are generated on
each commit.
</s>
+ <s id="git">Yes. Actually Git is snapshot based which means Git records
+ the full state in every commit, which means that any two
+ commits can be compared directly very quickly, although the
+ repository is typically browsed as a series of change sets.
+ </s>
</compare>
</section>
<section id="annotate">
@@ -534,6 +560,9 @@
Yes locally without any server connection with the standard graphical
Java client.
</s>
+ <s id="git">Yes. It can also detect the origin of copied and moved source
+ lines.
+ </s>
</compare>
</section>
</section>
@@ -610,6 +639,12 @@
It is possible to commit only a certain directory. However, one must
check out the entire repository as a whole.
</s>
+ <s id="git">No. However it is possible to commit only selected
+ changes in the working tree rather than everything. Subproject
+ support makes it possible to split large projects into several
+ repositories and link them. Related repositories need not be
+ checked out or cloned.
+ </s>
</compare>
</section>
<section id="tracking_uncommited_changes">
@@ -659,6 +694,10 @@
Yes, with the Synchronizer Studio (default Java client) or with the
standard diff command (diff -r . .so6/xxx/REFCOPY/)
</s>
+ <s id="git">Yes. In addition commits are local and will not be seen
+ until he/she decides to publish them making it possible to
+ track multiple versions locally before publishing.
+ </s>
</compare>
</section>
<section id="per_file_commit_messages">
@@ -714,6 +753,7 @@
for a per-changeset message.
</s>
<s id="ls-sync">No. Commit messages are per changeset.</s>
+ <s id="git">No. The same message applies the the commit as a whole.</s>
</compare>
</section>
</section>
@@ -828,6 +868,11 @@
documentation. Installing and getting started with the GUI is very easy
though. (update/commit-next-next-next-finished)
</s>
+ <s id="git">
+ There a good tutorials manual pages and a supportive community.
+ Basic usage is simple, but advanced usage requires understanding of
+ what makes git different.
+ </s>
</compare>
</section>
<section id="ease_of_deployment">
@@ -950,6 +995,10 @@
LibreSource repository web page.
(links: create workspace, update, commit, studio...)
</s>
+ <s id="git">
+ Very simple to deploy on Unix-like systems. Windows installs
+ is not fully developed yet. Installing in cygwin is simple though.
+ </s>
</compare>
</section>
<section id="command_set">
@@ -1048,6 +1097,13 @@
Basic commands available (commit/update), but it's really simple to
use the GUI. Ant task are also available.
</s>
+ <s id="git">Basic usage could be considered similar, but trying
+ to use Git like CVS would be counterproductive since many
+ cases of CVS usage is by design not possible in Git. The
+ number of command is large. ~140 but only ~20 commands
+ are typically used and less than ten will do for casual
+ users.
+ </s>
</compare>
</section>
<section id="networking">
@@ -1152,6 +1208,13 @@
<s id="ls-sync">
Good. Use of HTTP to get through firwalls.
</s>
+ <s id="git">
+ Excellent. Normal usage is off-line, but networking is
+ used for sharing changes Networking including ssh,
+ a special git protocol http and mail can be used to share
+ changes, both incoming and outgoing. Mail can be used
+ via IMAP and mbox files.
+ </s>
</compare>
</section>
<section id="portability">
@@ -1249,6 +1312,11 @@
Excellent. Clients and servers work on any Java 1.5-compatible
platform. (Windows, Linux and Mac OS X )
</s>
+ <s id="git">
+ Very good for POSIX compatible environments. A non-cygwin
+ port for windows is underway. There are some graphical
+ tools available for windows in cygwin.
+ </s>
</compare>
</section>
</section>
@@ -1323,6 +1391,7 @@
Yes, without diff features but with a better awareness support.
(allow to know at any time on each version each one is working on)
</s>
+ <s id="git">Yes. gitweb</s>
</compare>
</section>
<section id="availability_of_guis">
@@ -1421,6 +1490,10 @@
is automatically launched from the repository web page and
another one which is an Eclipse plugin.
</s>
+ <s id="git">
+ A number of good GUI's are availble for basic usage,
+ but typical usage is command based.
+ </s>
</compare>
</section>
</section>
@@ -1501,7 +1574,8 @@
additional licensing.
</s>
<s id="ls-sync">QPL - The Qt Public License (OpenSource)</s>
- </compare>
+ <s id="git">GPL</s>
+ </compare>
</section>
</section>
</contents>
-- robin
^ permalink raw reply
* To push into a non-bare repository, or not to push into it...
From: Johannes Schindelin @ 2007-11-29 1:33 UTC (permalink / raw)
To: git
Hi,
how about resolving this recurring subject of discussion by introducing a
config variable, say "branch.allowPushingIntoHEAD". We'd teach git-init
to set it to "false", and receive-pack would refuse to update HEAD if it
is "false", _unless_ core.bare = true.
Of course, we would default the value to "false" to leave existing setups
functional.
However, if it is "true" (and core.bare is not true) -- which would need
user interaction to explicitely set it -- receive-pack would also make
sure that the working tree is clean (locking the index for the complete
operation), and call "read-tree -u -m HEAD" in the end.
By refusing the update we would be able to give users a severe *WARNING*,
but a hint how to put their HEAD in the noose.
I'd do a patch, but I am 1) tired, and 2) more thinking about that
git-repack enhancement for repo.or.cz.
Ciao,
Dscho
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: Junio C Hamano @ 2007-11-29 1:26 UTC (permalink / raw)
To: J. Bruce Fields
Cc: Nicolas Pitre, Johannes Schindelin,
しらいしななこ,
Andreas Ericsson, Jakub Narebski, git
In-Reply-To: <20071129010606.GA5856@fieldses.org>
"J. Bruce Fields" <bfields@fieldses.org> writes:
> Yeah. I considered doing the above some time ago and ran into some
> differences between git-clone and "git init && git remote add && git
> fetch"--I think it may have just been that the latter didn't guess the
> HEAD in the same way. That's fixed now, right?
"git remote add" by itself does not talk with remote, so unless you let
it do the initial fetch it is not fixable (and no, "git remote add -f"
currently does not do the guesswork either).
^ permalink raw reply
* Re: [PATCH] Make Git accept absolute path names for files within the work tree
From: Robin Rosenberg @ 2007-11-29 1:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmysy7oav.fsf@gitster.siamese.dyndns.org>
onsdag 28 november 2007 skrev Junio C Hamano:
> This looks somewhat tighter than the previous one, but still made me
> worried if the caller of prefix_path() has run the setup sequence enough
> so that calling get_git_work_tree() is safe, so I ended up auditing the
> callpath. At least, I do not want to see that unconditional call to
> get_git_work_tree() when we do not need to do this "ah prefix got an
> unusual absolute path" stuff.
>
> * builtin-init-db.c uses prefix_path() to find where the template is
> (this is mingw fallout change); in general, I do not think we would
> want to trigger repository nor worktree discovery inside init-db,
> although I suspect this particular callpath could be made Ok (because
> it is taken only when template_dir is not absolute) if you do not
> unconditionally call get_git_work_tree() in prefix_path().
>
> * config.c uses prefix_path() to find the ETC_GITCONFIG that is not
> absolute (again, mingw fallout). When git_config() is called, we
> already should have discovered repository but worktree may not have
> been found yet (config.worktree can be used to specify where it is,
> so you have a chicken and egg problem). Again, this particular
> callpath happens to be Ok because this is used only for non-absolute
> path, but that is a bit subtle.
I wonder if this usage in config and initdb is what prefix_path() was intended for. The
interface is declared in cache.h and there are error conditions like '%s is outside repository'.
Maybe we should have a boolean indicating whether the arguments refer to filespecs
or not to make this clear or rewite the mingw fallouts in some other way.
> * get_pathspec() uses prefix_path() for obvious reasons, and the prefix
> it gets must have been discovered by finding out where the worktree
> is, so by definition that one is safe.
>
> Everybody else you would get from "git grep prefix_path" are after the
> proper setup, so they should all be safe.
Thanks for looking at the usages. I'll come up with some more tests too, though writing
negative tests sometimes is a challenge. Tests all to easily fail for the wrong reason which
is bad when we expect them to fail for the right reason.
-- robin
^ permalink raw reply
* Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive
From: Wincent Colaiuta @ 2007-11-29 1:08 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmysx2ac8.fsf@gitster.siamese.dyndns.org>
El 29/11/2007, a las 0:56, Junio C Hamano escribió:
> Wincent Colaiuta <win@wincent.com> writes:
>
>> @@ -774,14 +774,14 @@ EOF
>> }
>>
>> sub main_loop {
>> - my @cmd = ([ 'status', \&status_cmd, ],
>> - [ 'update', \&update_cmd, ],
>> - [ 'revert', \&revert_cmd, ],
>> - [ 'add untracked', \&add_untracked_cmd, ],
>> - [ 'patch', \&patch_update_cmd, ],
>> - [ 'diff', \&diff_cmd, ],
>> - [ 'quit', \&quit_cmd, ],
>> - [ 'help', \&help_cmd, ],
>> + my @cmd = ([ 'status', \&status_cmd, '[s]tatus', ],
>> + [ 'update', \&update_cmd, '[u]date', ],
>> + [ 'revert', \&revert_cmd, '[r]evert', ],
>> + [ 'add untracked', \&add_untracked_cmd, '[a]dd untracked', ],
>> + [ 'patch', \&patch_update_cmd, '[p]atch', ],
>> + [ 'diff', \&diff_cmd, '[d]iff', ],
>> + [ 'quit', \&quit_cmd, '[q]uit', ],
>> + [ 'help', \&help_cmd, '[h]elp', ],
>> );
>
> I like the general idea of making it more obvious that you can use the
> unique prefix, but I think you should make list_and_choose do this
> automatically without adding a redundant element in the command array.
>
> If you do so, the same highlighting will automatically appear when you
> are picking which paths to update in the update subcommand, for
> example.
Yes, I did consider that, and it's very easy when all the options have
a unique, single-letter prefix, as is the case with the main command
loop. But what to do if you've got a bunch of paths with lengthy
common prefixes? eg. what would you highlight here?
lib/ssl/crypto/foo.c
lib/ssl/crypto/bar.c
lib/ssl/crypto/baz.c
Highlighting "lib/ssl/crypto/f", "lib/ssl/crypto/bar" and "lib/ssl/
crypto/baz" doesn't sound like much help... Maybe there should be some
limit: if you need to go more than 3 characters deep in order to
differentiate unique prefixes then perhaps highlighting should be
omitted in that case. What do you think of that idea?
Cheers,
Wincent
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: J. Bruce Fields @ 2007-11-29 1:06 UTC (permalink / raw)
To: Junio C Hamano
Cc: Nicolas Pitre, Johannes Schindelin,
しらいしななこ,
Andreas Ericsson, Jakub Narebski, git
In-Reply-To: <7vlk8hzx0g.fsf@gitster.siamese.dyndns.org>
On Wed, Nov 28, 2007 at 05:00:15PM -0800, Junio C Hamano wrote:
> Nicolas Pitre <nico@cam.org> writes:
>
> > ... In all the tutorials for $job I've done so
> > far, I simply never talk about pull nor clone, but rather about init,
> > "git remote", fetch and merge, with explicit and meaningful branch
> > names. I think that basic commands, even if there is a bit more of
> > them, make Git easier to learn and understand than talking about those
> > magic meta commands hiding the truth away.
>
> That's actually a quite interesting approach for teaching.
>
> The original "tutorial" (now core-tutorial) was similar in spirit; it
> built the user experience by starting at sequence of low level commands,
> and then finally said "since this is so often used combination, there is
> a short-hand for it that does all". I think the approach would work
> quite well for people who want to use the tool with deep understanding.
Yeah. I considered doing the above some time ago and ran into some
differences between git-clone and "git init && git remote add && git
fetch"--I think it may have just been that the latter didn't guess the
HEAD in the same way. That's fixed now, right? Is there any other
difference people would run into? If not, I'll work on that. I
wouldn't want to break things down quite as far as the core-tutorial,
but this particular thing is so simple....
--b.
^ permalink raw reply
* Re: [PATCH] receive-pack: allow deletion of corrupt refs
From: Johannes Schindelin @ 2007-11-29 1:04 UTC (permalink / raw)
To: git, gitster, pasky
In-Reply-To: <Pine.LNX.4.64.0711290101420.27959@racer.site>
Hi,
On Thu, 29 Nov 2007, Johannes Schindelin wrote:
> Incidentally, some instances of "cd .." in the test cases were fixed, so
> that subsequent test cases run in t/trash/ irrespective of the outcome
> of the previous test cases.
Just to clarify: I was quite surprised that my test case did not succeed,
and eventually found out that $(pwd) was t/trash/child/child after the
last test.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] Move all dashed form git commands to libexecdir
From: Junio C Hamano @ 2007-11-29 1:02 UTC (permalink / raw)
To: gitzilla; +Cc: git
In-Reply-To: <474E0EE6.6070107@gmail.com>
A Large Angry SCM <gitzilla@gmail.com> writes:
> Junio C Hamano wrote:
> [...]
>> Would people agree with a rough roadmap like this?
>>
>> - v1.5.4 will ship with gitexecdir=$(bindir) in Makefile. But the
>> release notes for the version will warn users that:
>>
>> (1) using git-foo from the command line, and
>>
>> (2) using git-foo from your scripts without first prepending the
>> return value of "git --exec-path" to the PATH
>>
>> is now officially deprecated (it has been deprecated for a long time
>> since January 2006, v1.2.0~149) and upcoming v1.5.5 will ship with
>> the default configuration that does not install git-foo form in
>> user's PATH.
>>
>> - Post v1.5.4, start cooking gitexecdir=$(libexecdir)/git-core, aiming
>> for inclusion in v1.5.5, perhaps in Mar-Feb 2008 timeframe.
>>
>> - The release notes for v1.5.5 will warn users that git-foo will be
>> removed in v1.6.0 for many commands and it will be merely an accident
>> if some of them still work.
>>
>> - Post v1.5.5, start cooking the change that does not install hardlinks
>> for built-in commands, aiming for inclusion in v1.6.0, by the end of
>> 2008.
>
> So long as there remains the option in the Makefile to install the
> "dashed" commands in $(bindir) for those of us that wish it.
Surely.
Actually they already have that option of going dashless themselves, so
in a sense it is not strictly necessary to make a big deal out of this.
^ permalink raw reply
* [PATCH] receive-pack: allow deletion of corrupt refs
From: Johannes Schindelin @ 2007-11-29 1:02 UTC (permalink / raw)
To: git, gitster, pasky
Occasionally, in some setups (*cough* forks on repo.or.cz *cough*) some
refs go stale, e.g. when the forkee rebased and lost some objects needed
by the fork. The quick & dirty way to deal with those refs is to delete
them and push them again.
However, git-push first would first fetch the current commit name for the
ref, would receive a null sha1 since the ref does not point to a valid
object, then tell receive-pack that it should delete the ref with this
commit name. delete_ref() would be subsequently be called, and check that
resolve_ref() (which does _not_ check for validity of the object) returns
the same commit name. Which would fail.
The proper fix is to avoid corrupting repositories, but in the meantime
this is a good fix in any case.
Incidentally, some instances of "cd .." in the test cases were fixed, so
that subsequent test cases run in t/trash/ irrespective of the outcome of
the previous test cases.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
I was bitten one time too many by a rebased git/mingw.git/.
Will work on the "proper fix" I hinted at.
receive-pack.c | 4 ++++
t/t5516-fetch-push.sh | 41 ++++++++++++++++++++++++++---------------
2 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/receive-pack.c b/receive-pack.c
index ed44b89..fba4cf8 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -200,6 +200,10 @@ static const char *update(struct command *cmd)
}
if (is_null_sha1(new_sha1)) {
+ if (!parse_object(old_sha1)) {
+ warning ("Allowing deletion of corrupt ref.");
+ old_sha1 = NULL;
+ }
if (delete_ref(name, old_sha1)) {
error("failed to delete %s", name);
return "failed to delete";
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index fd5f284..9d2dc33 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -274,9 +274,8 @@ test_expect_success 'push with HEAD nonexisting at remote' '
test_expect_success 'push with dry-run' '
mk_test heads/master &&
- cd testrepo &&
- old_commit=$(git show-ref -s --verify refs/heads/master) &&
- cd .. &&
+ (cd testrepo &&
+ old_commit=$(git show-ref -s --verify refs/heads/master)) &&
git push --dry-run testrepo &&
check_push_result $old_commit heads/master
'
@@ -284,28 +283,40 @@ test_expect_success 'push with dry-run' '
test_expect_success 'push updates local refs' '
rm -rf parent child &&
- mkdir parent && cd parent && git init &&
- echo one >foo && git add foo && git commit -m one &&
- cd .. &&
- git clone parent child && cd child &&
+ mkdir parent &&
+ (cd parent && git init &&
+ echo one >foo && git add foo && git commit -m one) &&
+ git clone parent child &&
+ (cd child &&
echo two >foo && git commit -a -m two &&
git push &&
- test $(git rev-parse master) = $(git rev-parse remotes/origin/master)
+ test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
'
test_expect_success 'push does not update local refs on failure' '
rm -rf parent child &&
- mkdir parent && cd parent && git init &&
+ mkdir parent &&
+ (cd parent && git init &&
echo one >foo && git add foo && git commit -m one &&
echo exit 1 >.git/hooks/pre-receive &&
- chmod +x .git/hooks/pre-receive &&
- cd .. &&
- git clone parent child && cd child &&
- echo two >foo && git commit -a -m two || exit 1
- git push && exit 1
- test $(git rev-parse master) != $(git rev-parse remotes/origin/master)
+ chmod +x .git/hooks/pre-receive) &&
+ git clone parent child &&
+ (cd child &&
+ echo two >foo && git commit -a -m two &&
+ ! git push &&
+ test $(git rev-parse master) != \
+ $(git rev-parse remotes/origin/master))
+
+'
+
+test_expect_success 'allow deleting an invalid remote ref' '
+
+ pwd &&
+ rm -f testrepo/.git/objects/??/* &&
+ git push testrepo :refs/heads/master &&
+ (cd testrepo && ! git rev-parse --verify refs/heads/master)
'
--
1.5.3.6.2065.gd47ac
^ permalink raw reply related
* Re: What's cooking in git.git (topics)
From: Junio C Hamano @ 2007-11-29 1:00 UTC (permalink / raw)
To: Nicolas Pitre
Cc: J. Bruce Fields, Johannes Schindelin,
しらいしななこ,
Andreas Ericsson, Jakub Narebski, git
In-Reply-To: <alpine.LFD.0.99999.0711271155250.9605@xanadu.home>
Nicolas Pitre <nico@cam.org> writes:
> ... In all the tutorials for $job I've done so
> far, I simply never talk about pull nor clone, but rather about init,
> "git remote", fetch and merge, with explicit and meaningful branch
> names. I think that basic commands, even if there is a bit more of
> them, make Git easier to learn and understand than talking about those
> magic meta commands hiding the truth away.
That's actually a quite interesting approach for teaching.
The original "tutorial" (now core-tutorial) was similar in spirit; it
built the user experience by starting at sequence of low level commands,
and then finally said "since this is so often used combination, there is
a short-hand for it that does all". I think the approach would work
quite well for people who want to use the tool with deep understanding.
However, I am not so sure about people who just want canned set of
instructions and follow them blindly to get their work done. And I do
not think the latter classes of users are necessarily wrong.
Such a canned set of instructions would (if the project that supplies
the cheat-sheet encourages merges instead of rebases) talk about "clone
then commit then push then pull and repeat", without mentioning what
pull does is fetch+merge nor what fetch means and what merge means, and
that would let people get started without deeper understanding.
But the lack of deeper understanding would hurt them in the longer run
(e.g. "my push was rejected with something called non-fast-forward ---
what does that mean and what would I do now?").
^ permalink raw reply
* Re: [PATCH] Move all dashed form git commands to libexecdir
From: A Large Angry SCM @ 2007-11-29 0:59 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfxyq2c9b.fsf@gitster.siamese.dyndns.org>
Junio C Hamano wrote:
[...]
> Would people agree with a rough roadmap like this?
>
> - v1.5.4 will ship with gitexecdir=$(bindir) in Makefile. But the
> release notes for the version will warn users that:
>
> (1) using git-foo from the command line, and
>
> (2) using git-foo from your scripts without first prepending the
> return value of "git --exec-path" to the PATH
>
> is now officially deprecated (it has been deprecated for a long time
> since January 2006, v1.2.0~149) and upcoming v1.5.5 will ship with
> the default configuration that does not install git-foo form in
> user's PATH.
>
> - Post v1.5.4, start cooking gitexecdir=$(libexecdir)/git-core, aiming
> for inclusion in v1.5.5, perhaps in Mar-Feb 2008 timeframe.
>
> - The release notes for v1.5.5 will warn users that git-foo will be
> removed in v1.6.0 for many commands and it will be merely an accident
> if some of them still work.
>
> - Post v1.5.5, start cooking the change that does not install hardlinks
> for built-in commands, aiming for inclusion in v1.6.0, by the end of
> 2008.
So long as there remains the option in the Makefile to install the
"dashed" commands in $(bindir) for those of us that wish it.
^ permalink raw reply
* Re: [PATCH 3/3] cvsimport: miscellaneous packed-ref fixes
From: Junio C Hamano @ 2007-11-29 0:52 UTC (permalink / raw)
To: Jeff King; +Cc: Emanuele Giaquinta, git
In-Reply-To: <20071128185628.GC11320@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> @@ -998,7 +996,7 @@ if ($orig_branch) {
> $orig_branch = "master";
> print "DONE; creating $orig_branch branch\n" if $opt_v;
> system("git-update-ref", "refs/heads/master", "$remote/$opt_o")
> - unless -f "$git_dir/refs/heads/master";
> + defined get_headref('refs/heads/master');
Where did the unless go ;-)?
Thanks, queued.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox