* Re: [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().
From: Junio C Hamano @ 2005-06-25 2:40 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506241755280.11175@ppc970.osdl.org>
>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:
LT> I really don't want to do this.
LT> Can you fix the "optimized" one instead?
Will do.
^ permalink raw reply
* Re: git Tutorial?
From: Patrick Mochel @ 2005-06-25 1:27 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0506240910040.11175@ppc970.osdl.org>
On Fri, 24 Jun 2005, Linus Torvalds wrote:
>
>
> [ git-list cc'd, since these example things might be useful to others ]
>
> On Fri, 24 Jun 2005, Patrick Mochel wrote:
> > The handy things I've noticed missing are the equivalents of
> >
> > - bk changes -u<user> (Great for tracking down a change one did)
>
> You can script it (and if you do so nicely, feel free to send me a
> patch). Here's the magic long-hand version that does something fairly
> close to it:
>
> git-rev-list --header HEAD |
> grep -z author.*torvalds |
> tr '\0\n' '\n:' |
> cut -d: -f1 |
> git-diff-tree --pretty --stdin -p |
> less -S
>
> (That's really hacky, because "cut" and other standard unix tools don't
> like using '\0' as a record separator, but hey, whatever works..)
>
> The above gives the result in "git-whatchanged" format, ie you get the
> patch too. If you don't want to see the patch, give the "-s" flag to
> git-diff-tree instead of the "-p" flag, but if you script it, I'd suggest
> allowing the user to give that as an option to the script.
Ok, it ain't exactly pretty, but it works.
Below is a patch to git-whatchanged that adds some optional parameters to
it that allow users to filter the changesets returned by git-rev-list.
-a Specify the author's name.
This can be any part of the "author" line: the first name,
the last name, both, the login name, the domain name, or
the entire email address.
For example:
git-whatchanged -a "Linus"
git-whatchanged -a "Linus Torvalds"
git-whatchanged -a "torvalds"
git-whatchanged -a "torvalds@ppc970.osdl.org"
git-whatchanged -a "@osdl.org"
-c Specify the committer's name
Like the above, this can be any part of the "committer"
line. For example:
git-whatchanged -c "Greg"
git-whatchanged -c "suse.de"
git-whatchanged -c "gregkh@suse.de"
And for good measure:
-s Specify a person that signed off on a patch.
git-whatchanged -s "Linus Torvalds"
git-whatchanged -s "mochel@digitalimplant.org"
It doesn't support multiple "Signed-off-by" entries.
They can also be used together:
git-whatchanged -a mochel@digitalimplant.org -c gregkh@suse.de
git-whatchanged -a Dunlap -s Torvalds
By default, it still just prints the changeset comments. Passing '-p' will
print the patches.
Please note that my script-fu isn't exactly good, so the patch is probably
done in the worst possible way. Please feel free to rewrite it or simply
just toss it.
Thanks,
Pat
diff --git a/git-whatchanged b/git-whatchanged
--- a/git-whatchanged
+++ b/git-whatchanged
@@ -1,4 +1,44 @@
#!/bin/sh
-git-rev-list $(git-rev-parse --default HEAD --revs-only "$@") |
- git-diff-tree --stdin --pretty -r $(git-rev-parse --no-revs "$@") |
+
+Author=""
+Committer=""
+SignedOffBy=""
+Args=""
+
+while [ $# -gt 0 ] ; do
+
+ echo $1
+case $1 in
+ -a)
+ shift
+ Author="$1"
+ ;;
+ -c)
+ shift
+ Committer="$1"
+ ;;
+ -s)
+ shift
+ SignedOffBy="$1"
+ ;;
+ *)
+ Args="$Args $1"
+ ;;
+
+esac
+ shift
+done
+
+filter_cset() {
+ egrep -z "author[[:print:]]+$Author" |
+ egrep -z "committer[[:print:]]+$Committer" |
+ egrep -z "Signed-off-by:[[:print:]]+$SignedOffBy"
+}
+
+
+git-rev-list --header $(git-rev-parse --default HEAD --revs-only "$Args") |
+ filter_cset |
+ tr '\0\n' '\n:' | cut -d: -f1 |
+ git-diff-tree --stdin --pretty $(git-rev-parse --no-revs "$Args") |
LESS="$LESS -S" ${PAGER:-less}
+
^ permalink raw reply
* Re: [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().
From: Linus Torvalds @ 2005-06-25 0:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvf439vdl.fsf@assigned-by-dhcp.cox.net>
On Fri, 24 Jun 2005, Junio C Hamano wrote:
>
> Resurrect the unoptimized directory-file conflict check code for
> now as well. The new one did not handle higher stages properly.
I really don't want to do this.
Can you fix the "optimized" one instead? Currently the only "optimization"
is really to just not call it for any non-stage0 thing, the real advantage
is that the old code was totally unreadable and did everything in one big
thing.
I'm ok with dropping the optimization, but I don't want to lose the
cleanup of splitting that horrible old function into two.
Linus
^ permalink raw reply
* [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().
From: Junio C Hamano @ 2005-06-24 23:40 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <7vaclgfynv.fsf@assigned-by-dhcp.cox.net>
An earlier change to optimize directory-file conflict check
broke what "read-tree --emu23" expects. Introduce an explicit
flag to tell add_cache_entry() not to check for conflicts and
use it when reading an existing tree into an empty stage ---
by definition this case can never introduce such conflicts.
Resurrect the unoptimized directory-file conflict check code for
now as well. The new one did not handle higher stages properly.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
cache.h | 1
read-cache.c | 177 +++++++++++++++++++------------------
t/t1005-read-tree-m-2way-emu23.sh | 6 +
tree.c | 2
4 files changed, 95 insertions(+), 91 deletions(-)
cb13405368b0132ec3b3edcda22d32d89e9c1f85
diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -130,6 +130,7 @@ extern int write_cache(int newfd, struct
extern int cache_name_pos(const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
+#define ADD_CACHE_SKIP_DF_CHECK 4 /* Ok to skip directory/file conflict checks */
extern int add_cache_entry(struct cache_entry *ce, int option);
extern int remove_cache_entry_at(int pos);
extern int remove_file_from_cache(char *path);
diff --git a/read-cache.c b/read-cache.c
--- a/read-cache.c
+++ b/read-cache.c
@@ -171,83 +171,6 @@ int ce_same_name(struct cache_entry *a,
return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
}
-/*
- * Do we have another file that has the beginning components being a
- * proper superset of the name we're trying to add?
- */
-static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replace)
-{
- int retval = 0;
- int len = ce_namelen(ce);
- const char *name = ce->name;
-
- while (pos < active_nr) {
- struct cache_entry *p = active_cache[pos++];
-
- if (len >= ce_namelen(p))
- break;
- if (memcmp(name, p->name, len))
- break;
- if (p->name[len] != '/')
- continue;
- retval = -1;
- if (!ok_to_replace)
- break;
- remove_cache_entry_at(--pos);
- }
- return retval;
-}
-
-/*
- * Do we have another file with a pathname that is a proper
- * subset of the name we're trying to add?
- */
-static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace)
-{
- int retval = 0;
- const char *name = ce->name;
- const char *slash = name + ce_namelen(ce);
-
- for (;;) {
- int len;
-
- for (;;) {
- if (*--slash == '/')
- break;
- if (slash <= ce->name)
- return retval;
- }
- len = slash - name;
-
- pos = cache_name_pos(name, len);
- if (pos >= 0) {
- retval = -1;
- if (ok_to_replace)
- break;
- remove_cache_entry_at(pos);
- continue;
- }
-
- /*
- * Trivial optimization: if we find an entry that
- * already matches the sub-directory, then we know
- * we're ok, and we can exit
- */
- pos = -pos-1;
- if (pos < active_nr) {
- struct cache_entry *p = active_cache[pos];
- if (ce_namelen(p) <= len)
- continue;
- if (p->name[len] != '/')
- continue;
- if (memcmp(p->name, name, len))
- continue;
- break;
- }
- }
- return retval;
-}
-
/* We may be in a situation where we already have path/file and path
* is being added, or we already have path and path/file is being
* added. Either one would result in a nonsense tree that has path
@@ -257,19 +180,98 @@ static int has_dir_name(const struct cac
* from the cache so the caller should recompute the insert position.
* When this happens, we return non-zero.
*/
-static int check_file_directory_conflict(const struct cache_entry *ce, int pos, int ok_to_replace)
+static int check_file_directory_conflict(const struct cache_entry *ce,
+ int ok_to_replace)
{
+ int pos, replaced = 0;
+ const char *path = ce->name;
+ int namelen = strlen(path);
+ int stage = ce_stage(ce);
+ char *pathbuf = xmalloc(namelen + 1);
+ char *cp;
+
+ memcpy(pathbuf, path, namelen + 1);
+
/*
- * We check if the path is a sub-path of a subsequent pathname
- * first, since removing those will not change the position
- * in the array
+ * We are inserting path/file. Do they have path registered at
+ * the same stage? We need to do this for all the levels of our
+ * subpath.
*/
- int retval = has_file_name(ce, pos, ok_to_replace);
- /*
- * Then check if the path might have a clashing sub-directory
- * before it.
+ cp = pathbuf;
+ while (1) {
+ char *ep = strchr(cp, '/');
+ int len;
+ if (!ep)
+ break;
+ *ep = 0; /* first cut it at slash */
+ len = ep - pathbuf;
+ pos = cache_name_pos(pathbuf,
+ ntohs(create_ce_flags(len, stage)));
+ if (0 <= pos) {
+ /* Our leading path component is registered as a file,
+ * and we are trying to make it a directory. This is
+ * bad.
+ */
+ if (!ok_to_replace) {
+ free(pathbuf);
+ return -1;
+ }
+ fprintf(stderr, "removing file '%s' to replace it with a directory to create '%s'.\n", pathbuf, path);
+ remove_cache_entry_at(pos);
+ replaced = 1;
+ }
+ *ep = '/'; /* then restore it and go downwards */
+ cp = ep + 1;
+ }
+ free(pathbuf);
+
+ /* Do we have an entry in the cache that makes our path a prefix
+ * of it? That is, are we creating a file where they already expect
+ * a directory there?
+ */
+ pos = cache_name_pos(path,
+ ntohs(create_ce_flags(namelen, stage)));
+
+ /* (0 <= pos) cannot happen because add_cache_entry()
+ * should have taken care of that case.
+ */
+ pos = -pos-1;
+
+ /* pos would point at an existing entry that would come immediately
+ * after our path. It could be the same as our path in higher stage,
+ * or different path but in a lower stage.
+ *
+ * E.g. when we are inserting path at stage 2,
+ *
+ * 1 path
+ * pos-> 3 path
+ * 2 path/file1
+ * 3 path/file1
+ * 2 path/file2
+ * 2 patho
+ *
+ * We need to examine pos, ignore it because it is at different
+ * stage, examine next to find the path/file at stage 2, and
+ * complain. We need to do this until we are not the leading
+ * path of an existing entry anymore.
*/
- return retval + has_dir_name(ce, pos, ok_to_replace);
+
+ while (pos < active_nr) {
+ struct cache_entry *other = active_cache[pos];
+ if (strncmp(other->name, path, namelen))
+ break; /* it is not our "subdirectory" anymore */
+ if ((ce_stage(other) == stage) &&
+ other->name[namelen] == '/') {
+ if (!ok_to_replace)
+ return -1;
+ fprintf(stderr, "removing file '%s' under '%s' to be replaced with a file\n", other->name, path);
+ remove_cache_entry_at(pos);
+ replaced = 1;
+ continue; /* cycle without updating pos */
+ }
+ pos++;
+ }
+ return replaced;
}
int add_cache_entry(struct cache_entry *ce, int option)
@@ -277,6 +279,7 @@ int add_cache_entry(struct cache_entry *
int pos;
int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
+ int skip_df_check = option & ADD_CACHE_SKIP_DF_CHECK;
pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
/* existing match? Just replace it */
@@ -302,7 +305,7 @@ int add_cache_entry(struct cache_entry *
if (!ok_to_add)
return -1;
- if (!ce_stage(ce) && check_file_directory_conflict(ce, pos, ok_to_replace)) {
+ if (!skip_df_check && check_file_directory_conflict(ce, ok_to_replace)) {
if (!ok_to_replace)
return -1;
pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
diff --git a/t/t1005-read-tree-m-2way-emu23.sh b/t/t1005-read-tree-m-2way-emu23.sh
--- a/t/t1005-read-tree-m-2way-emu23.sh
+++ b/t/t1005-read-tree-m-2way-emu23.sh
@@ -389,7 +389,7 @@ test_expect_success \
:'
# Emu23 can grok I having more than H. Make sure we did not
-# botch the conflict tests (Linus code botches this test).
+# botch the conflict tests (fixed).
test_expect_success \
'DF vs DF/DF case test (#2).' \
'rm -f .git/index &&
@@ -400,8 +400,8 @@ test_expect_success \
# This should fail because I and H have a conflict
# at DF.
if git-read-tree --emu23 $treeDF $treeDFDF
- then true ;# should be false
- else false ;# should be true
+ then false
+ else true
fi'
test_done
diff --git a/tree.c b/tree.c
--- a/tree.c
+++ b/tree.c
@@ -18,7 +18,7 @@ static int read_one_entry(unsigned char
memcpy(ce->name, base, baselen);
memcpy(ce->name + baselen, pathname, len+1);
memcpy(ce->sha1, sha1, 20);
- return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
+ return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DF_CHECK);
}
static int read_tree_recursive(void *buffer, unsigned long size,
------------
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Kyle Moffett @ 2005-06-24 23:08 UTC (permalink / raw)
To: Matt Mackall; +Cc: Jeff Garzik, Linux Kernel, Git Mailing List, mercurial
In-Reply-To: <20050623235634.GC14426@waste.org>
On Jun 23, 2005, at 19:56:34, Matt Mackall wrote:
> On Wed, Jun 22, 2005 at 06:24:54PM -0400, Jeff Garzik wrote:
>> Things in git-land are moving at lightning speed, and usability has
>> improved a lot since my post a month ago: http://lkml.org/lkml/
>> 2005/5/26/11
>
> And here's a quick comparison with the current state of Mercurial..
Oooh!!! Nice!!! This is my new official source keeper for my next
project. I
especially like the fast operation and low disk storage
requirements. Many
kudos to Matt Mackall for his awesome program! The efficient network
protocol
is great too!
Cheers,
Kyle Moffett
--
There are two ways of constructing a software design. One way is to
make it so simple that there are obviously no deficiencies. And the
other way is to make it so complicated that there are no obvious
deficiencies.
-- C.A.R. Hoare
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Joel Becker @ 2005-06-24 22:45 UTC (permalink / raw)
To: Petr Baudis
Cc: Matt Mackall, Jeff Garzik, Linux Kernel, Git Mailing List,
mercurial
In-Reply-To: <20050624064101.GB14292@pasky.ji.cz>
On Fri, Jun 24, 2005 at 08:41:01AM +0200, Petr Baudis wrote:
> Theoretically, dotest should work just fine even if you use Cogito.
> Anyone tested it?
When I update the OCFS2 git tree, I clone with Cogito and patch
with dotest. Been doing it for a month or two, no problems.
Joel
--
"I think it would be a good idea."
- Mahatma Ghandi, when asked what he thought of Western
civilization
Joel Becker
Senior Member of Technical Staff
Oracle
E-mail: joel.becker@oracle.com
Phone: (650) 506-8127
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Jeff Garzik @ 2005-06-24 22:38 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Matthias Urlichs, git, linux-kernel
In-Reply-To: <Pine.LNX.4.58.0506241153180.11175@ppc970.osdl.org>
Linus Torvalds wrote:
> I still think you can go a bit too far on your branch usage (ie Jeff), but
> hey, what's the difference between three branches and fifty, really?
LOL ;-)
> (I'm kidding. The difference between three and fifty is how well you can
> keep track of them in your head, but maybe Jeff just has a bigger head
> than most people do. Jeff, do people go "Boy, you've got a big head" the
> first time they meet you?)
50 branches is just easier than 50 different trees, for my usage :)
Poor kernel.org would melt if I had 50 trees :)
Jeff
^ permalink raw reply
* Re: 2.6.12 hangs on boot
From: Linus Torvalds @ 2005-06-24 22:20 UTC (permalink / raw)
To: Alexander Y. Fomichev; +Cc: Kernel Mailing List, admin, Git Mailing List
In-Reply-To: <200506221813.50385.gluk@php4.ru>
On Wed, 22 Jun 2005, Alexander Y. Fomichev wrote:
>
> I've been trying to switch from 2.6.12-rc3 to 2.6.12 on Dual EM64T 2.8 GHz
> [ MoBo: Intel E7520, intel 82801 ]
> but kernel hangs on boot right after records:
>
> Booting processor 2/1 rip 6000 rsp ffff8100023dbf58
> Initializing CPU#2
Hmm.. Since you seem to be a git user, maybe you could try the git
"bisect" thing to help narrow down exactly where this happened (and help
test that thing too ;).
You can basically use git to find the half-way point between a set of
"known good" points and a "known bad" point ("bisecting" the set of
commits), and doing just a few of those should give us a much better view
of where things started going wrong.
For example, since you know that 2.6.12-rc3 is good, and 2.6.12 is bad,
you'd do
git-rev-list --bisect v2.6.12 ^v2.6.12-rc3
where the "v2.6.12 ^v2.6.12-rc3" thing basically means "everything in
v2.6.12 but _not_ in v2.6.12-rc3" (that's what the ^ marks), and the
"--bisect" flag just asks git-rev-list to list the middle-most commit,
rather than all the commits in between those kernel versions.
You should get the answer "0e6ef3e02b6f07e37ba1c1abc059f8bee4e0847f", but
before you go any further, just make sure your git index is all clean:
git status
should not print anything else than "nothing to commit". If so, then
you're ready to try the new "mid-point" head:
git-rev-list --bisect v2.6.12 ^v2.6.12-rc3 > .git/refs/heads/try1
git checkout try1
which will create a new branch called "try1", where the head is that
"mid-point", and it will switch to that branch (this requires a fairly
recent "git", btw, so make sure you update your git first).
Then, compile that kernel, and try it out.
Now, there are two possibilities: either "try1" ends up being good, or it
still shows the bug. If it is a buggy kernel, then you now have a new
"bad" point, and you do
git-rev-list --bisect try1 ^v2.6.12-rc3 > .git/refs/heads/try2
git checkout try2
which is all the same thing as you did before, except now we use "try1" as
the known bad one rather than v2.6.12 (and we call the new branch "try2"
of course).
However, if that "try1" is _good_, and doesn't show the bug, then you
shouldn't replace the other "known good" case, but instead you should add
it to the list of good commits (aka commits we don't want to know about):
git-rev-list --bisect v2.6.12 ^v2.6.12-rc3 ^try1 > .git/refs/heads/try2
git checkout try2
ie notice how we now say: want to get the bisection of the commits in
v2.6.12 (known bad) but _not_ in either of v2.6.12-rc3 or the 'try1'
branch (which are known good).
After compiling and testing a few kernels, you will have narrowed the
range down a _lot_, and at some point you can just say
git-rev-list --pretty try4 ^v2.6.12-rc3 ^try1 ^try3
(or however the "success/failure" pattern ends up being - the above
example line assumes that "try1" didn't have the bug, but "try2" did, and
then "try3" was ok again but "try4" was buggy), and you'll get a fairly
small list of commits that are the potential "bad" ones.
After the above four tries, you'd have limited it down to a list of 95
changes (from the original 1520), so it would really be best to try six or
seven different kernels, but at that point you'd have it down to less than
20 commits and then pinpointing the bug is usually much easier.
And when you're done, you can just do
git checkout master
and you're back to where you started.
Linus
^ permalink raw reply
* Should "git-read-tree -m -u" delete files?
From: Junio C Hamano @ 2005-06-24 22:08 UTC (permalink / raw)
To: Matthias Urlichs; +Cc: git
In-Reply-To: <pan.2005.06.24.13.16.10.406827@smurf.noris.de>
>>>>> "MU" == Matthias Urlichs <smurf@smurf.noris.de> writes:
MU> The only problem I have with it is that "git-read-tree -m -u"
MU> doesn't delete files yet. To repeat my question from last week:
>>> Would it be safe to add all files for which
>>> read_tree.c:merge_cache:fn() returns zero to a "delete me" list?
MU> (files on which which then actually get deleted, of course, if g-r-t
MU> doesn't find any problems.)
As the guilty party for the "read-tree two-way semantics table"
you quoted in your "question from last week" message, I should
have replied sooner but could not. Sorry about that [*1*].
Anyway, here are my answers.
(1) No, merge_function[] returning zero just means "I did not
cause anything to change the number of already processed
entries". When it wants to delete an entry, it explicitly
marks the entry to be deleted by calling deleted_entry(),
and the deletion is processed at the very end by
check_updates() function. Note that we do _not_ return
zero in this case.
(2) The part you quoted in your "last week" message is case 10;
the current code does delete the path with -u [*2*].
(3) There could be cases where twoway_merge() does not delete a
clean path that _should_ be removed. If that is the case
then you have spotted a bug --- I would appreciate it if
you can show a reproduction recipe. I have looked at the
function briefly again while writing this reply and did not
find suspicious code that would just return 0 without
calling deleted_entry(), though.
(4) Using --emu23 (followed by git-merge-cache, of course),
instead of doing "git-read-tree -m -u H M", should remove
deleted paths as well.
[Footnote]
*1* I was on a crazy travel schedule, going just for 3 days last
week and then for another 2 days this week to Japan from US west
coast, two 10-hour roundtrip flights X-<. Now I am back and
hopefully fully functional ;-).
*2* The part you quoted in your previous message was this. I am
re-quoting from the original to give it a bit more context:
Two Tree Merge
~~~~~~~~~~~~~~
...
In this case, the "git-read-tree -m $H $M" command makes sure
that no local change is lost as the result of this "merge".
Here are the "carry forward" rules:
I (index) H M Result
-------------------------------------------------------
...
clean I==H I==M
------------------
...
10 yes yes N/A exists nothing remove path from cache
This case is covered by this test in t1002:
test_expect_success \
'10 - path removed.' \
'rm -f .git/index &&
echo rezrov >rezrov &&
git-update-cache --add rezrov &&
git-read-tree -m -u $treeH $treeM &&
git-ls-files --stage >10.out &&
cmp M.out 10.out &&
sha1sum -c M.sha1'
Where paths involved are:
path treeH treeM
-----------------------------------------------------
bozbar exists modified from treeH
frotz does not exist added in treeM
nitfol exists same as in treeH
rezrov exists deleted in treeM
and after this test runs, you can see that the path "rezrov"
gets removed from your work tree. Insert "exit" just before the
next test, run "cd t && sh t1002-*.sh -i -v", and inspect what
is in the "t/trash" directory.
^ permalink raw reply
* Mercurial 0.6 released!
From: Matt Mackall @ 2005-06-24 21:24 UTC (permalink / raw)
To: mercurial, linux-kernel, git
This is release 0.6 of Mercurial, the distributed SCM.
Mercurial is:
- fast: as fast or faster than git or others for all important operations
- easy to use: familiar commands, integrated help, integrated web server
- space efficient: Linux kernel history back to 2.4.0 in 300MB
- bandwidth efficient: 120MB to transfer that history
- distributed: supports decentralized development with arbitrary merging
- scalable: handles large numbers of files and revisions effortlessly
- robust: append-only storage model with journalling and rollback
- lightweight: small Python codebase
Available at http://selenic.com/mercurial/
Linux kernel repository at http://www.kernel.org/hg/
This release contains a huge number of improvements:
improved source tracking
multi-head support
permission tracking
rename and copy tracking
improved tag handling
friendlier, more robust command line interface
integrated help
faster startup
better exception handling
smarter three-way merge helper
improved communication
faster outstanding changeset detection
SSH-based push support
non-transparent proxy support
improved configuration handling
support for .hgrc and .hg/hgrc files
save per-repo defaults for pull
new delta extension
faster, smaller, and simpler than GNU diff or xdiff
faster commit, push/pull, and annotate
improved interoperability
convert-repo framework for importing from other SCMs
can work with gitk and git-viz
portability improvements
tested on big and little-endian 32 and 64-bit UNIX platforms
Windows support is nearly complete
and much more
numerous performance tweaks and bugfixes
automated test suite
updated docs and FAQ
--
Mathematics is the supreme nostalgia of our time.
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Daniel Barkalow @ 2005-06-24 21:11 UTC (permalink / raw)
To: Matthias Urlichs; +Cc: git, linux-kernel
In-Reply-To: <pan.2005.06.24.13.16.10.406827@smurf.noris.de>
On Fri, 24 Jun 2005, Matthias Urlichs wrote:
> Hi, Petr Baudis wrote:
>
> > Switching branches in place will be supported soon (although I have
> > doubts about its usefulness).
>
> Well, I don't. Main reason: It's simply a lot faster to create+switch to a
> branch locally for doing independent work, than to hardlink the whole
> Linux directory tree into a clone tree.
There's another option, which I may be the only person currently
using: have a repo (.git directory) not in a working directory, and have
the objects/ and refs/ subdirectories of the .git directories in your
working directories symlinked to those subdirectories of the repo. Then
you can have any number of functionally identical working directories,
each of which is set to some branch. If you have a reasonably small number
of branches at any time, they can each have a working directory switched
to them. On the other hand, all of the branches are accessible from any of
them.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: John W. Linville @ 2005-06-24 19:25 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Matthias Urlichs, git, linux-kernel
In-Reply-To: <Pine.LNX.4.58.0506241153180.11175@ppc970.osdl.org>
On Fri, Jun 24, 2005 at 12:00:33PM -0700, Linus Torvalds wrote:
> Jeff, do people go "Boy, you've got a big head" the
> first time they meet you?)
FWIW, Jeff _does_ have quite the melon riding around on his shoulders...
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: The coolest merge EVER!
From: Linus Torvalds @ 2005-06-24 19:22 UTC (permalink / raw)
To: Matthias Urlichs; +Cc: git
In-Reply-To: <pan.2005.06.24.11.54.51.598627@smurf.noris.de>
On Fri, 24 Jun 2005, Matthias Urlichs wrote:
> Hi, Junio C Hamano wrote:
>
> > I suspect there
> > would be a massive additional support needed if you want to make it easy
> > for Paul to pull changes made to gitk in your tree.
>
> I don't think that's possible; after all, the trees are now merged, so any
> pull would fetch all of Linus' tree.
No no.
A merge is a one-way thing. I merged Paul's tree, but Paul didn't merge
mine. His is still independent, and you can still pull his tree without
getting the rest of git, and Paul can still continue to work on his tree
as if I never merged it at all.
Now, merging back isn't as easy: if any gitk changes get done in my
"union" tree, Paul can't just pull those, becasue they now end up being
linked to the history of the unified thing, so when pulling, he'd now end
up getting all of the regular git stuff too.
Which is probably acceptable, but Junio's point was that this is not a
symmetric setup: git is like a black hole that never lets any information
escape, and once you've been sucked into a git archive, you end up not
being able to separate it.
Or rather, you _can_ separate out pieces of it, but now it's a matter of
cherry-picking, not automatic merges. Of course, people want to be able to
do that anyway, and normally that will also merge back perfectly, so
there's no huge downside, except that we should make it fairly easy.
Linus
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Linus Torvalds @ 2005-06-24 19:00 UTC (permalink / raw)
To: Matthias Urlichs; +Cc: git, linux-kernel
In-Reply-To: <pan.2005.06.24.13.16.10.406827@smurf.noris.de>
On Fri, 24 Jun 2005, Matthias Urlichs wrote:
>
> Well, I don't. Main reason: It's simply a lot faster to create+switch to a
> branch locally for doing independent work, than to hardlink the whole
> Linux directory tree into a clone tree.
>
> Having one tree also simpifies the "what do I have that's not merged yet"
> question -- just call "gitk $(cat .git/refs/heads/*)". ;-)
Actually, I think that gets close to another real advantage of branches:
that is also what allows you to edit things that failed a merge.
For example, let's say that a merge fail. You've got the HEAD and the
MERGE_HEAD, but a file type conflict (like a symlink that has turned into
a directory) or something like that means that you can't resolve them
sanely at all.
So this is merge problem where you can't just do a three-way merge and fix
up the result and commit: you have to fix things up before you can even
really do the merge. This is when switching to the MERGE_HEAD thing and
fixing it up there, committing it, and then doing the merge with the
original HEAD and the new MERGE_HEAD is really convenient.
(No, the scripts don't help you in cases like this, and we don't do the
MERGE_HEAD as a real branch right now, but the point is that we _can_, and
that this is more than an efficiency issue, it's a fundamental issue of
working with multiple end-points together. You _could_ clone the other
head into a totally new repository, fix it there, and then try the merge
anew, but now you're working around a limitation, not just doing
something slower).
I still think you can go a bit too far on your branch usage (ie Jeff), but
hey, what's the difference between three branches and fifty, really?
(I'm kidding. The difference between three and fifty is how well you can
keep track of them in your head, but maybe Jeff just has a bigger head
than most people do. Jeff, do people go "Boy, you've got a big head" the
first time they meet you?)
Linus
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Matt Mackall @ 2005-06-24 18:03 UTC (permalink / raw)
To: Kevin Smith; +Cc: Git Mailing List, mercurial
In-Reply-To: <42BC112C.1040009@qualitycode.com>
On Fri, Jun 24, 2005 at 09:57:00AM -0400, Kevin Smith wrote:
> Mercurial's tags use a radical approach, whereas cogito's are more
> conventional. I haven't yet used mercurial's versioned-tags enough yet
> to judge whether they are better, worse, or just different.
FYI, after reading Linus' rant about tags, I added a second kind of
tags to Mercurial. So now it has both 'official' tags, which are
properly version controlled, and 'private' tags (like git's) as well.
To add a local tag, add a section like this to .hg/hgrc:
[tags]
tested = d6ac88a738c4b3afea56ff09e449b91d85abff68
(This was a bit of a no-brainer, as it was two lines of code)
--
Mathematics is the supreme nostalgia of our time.
^ permalink raw reply
* Re: The coolest merge EVER!
From: Daniel Barkalow @ 2005-06-24 17:49 UTC (permalink / raw)
To: Matthias Urlichs; +Cc: git
In-Reply-To: <pan.2005.06.24.11.54.51.598627@smurf.noris.de>
On Fri, 24 Jun 2005, Matthias Urlichs wrote:
> Hi, Junio C Hamano wrote:
>
> > I suspect there
> > would be a massive additional support needed if you want to make it easy
> > for Paul to pull changes made to gitk in your tree.
>
> I don't think that's possible; after all, the trees are now merged, so any
> pull would fetch all of Linus' tree.
Linus could do:
git-read-tree gitk-head
git-update-cache gitk
git-commit-tree `write-tree` -p gitk-head > gitk-patched-head
git-read-tree HEAD
git merge gitk-patched-head
(or, better, use a separate index file for the gitk index)
(to commit changes to the gitk script made in a git working directory)
The change I proposed earlier would be so that the system would know what
was going on and users wouldn't have to. Then someone who didn't know that
gitk was (also) a separate project and just committed changes to it would
still generate gitk commits when appropriate.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: rev-parse, unknown arguments and extended sha1's
From: Linus Torvalds @ 2005-06-24 17:32 UTC (permalink / raw)
To: Sven Verdoolaege; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506240941520.11175@ppc970.osdl.org>
On Fri, 24 Jun 2005, Linus Torvalds wrote:
>
> Anyway, I think I'll make git-rev-parse have some option to "error out if
> the result is anything but a single revision number", since this is really
> the only reason for git-rev-parse in the first place: to make readable
> scripts.
How about something like
rev=$(git-rev-parse --default HEAD --revs-only --verify "$@") || exit 1
which now should work correctly.
In particular, the "--default" field is now expanded properly as a
revision, instead of just output raw, so the "HEAD" actually gets
translated into its SHA1 representation (and this also means that you can
now use SHA1 expressions in "default", ie you don't need to do two
git-rev-parse phases to do "--default HEAD^" etc).
The "--verify" thing then checks that the end result isn't a revision
argument (ie "--max-age=.." isn't accepted), and that there's exactly one
revision in the result (ie no ranges or multiple revisions some other
way).
So now you shouldn't need to check the result any more. You know that if
it worked, "rev" will be a nice SHA1 (of course, it might still be an
_invalid_ SHA1, that's a different issue. But it's at least syntactically
ok)
Linus
^ permalink raw reply
* Re: rev-parse, unknown arguments and extended sha1's
From: Linus Torvalds @ 2005-06-24 16:43 UTC (permalink / raw)
To: Sven Verdoolaege; +Cc: git
In-Reply-To: <20050624161718.GA14909@pc117b.liacs.nl>
On Fri, 24 Jun 2005, Sven Verdoolaege wrote:
>
> This is what I use:
>
> rev2=`echo $rev | sed -e 's/[^0-9a-f]//'`
> rev3=`echo $rev2 | sed -e 's/........................................//'`
> if test "x$rev3" = "x" -a "x$rev" = "x$rev2"; then
> echo "valid SHA1"
> fi
Oooh. UGGHLEE.
This is one reason I don't do much shell.
Anyway, I think I'll make git-rev-parse have some option to "error out if
the result is anything but a single revision number", since this is really
the only reason for git-rev-parse in the first place: to make readable
scripts.
Linus
^ permalink raw reply
* Re: [RFC] Order of push/pull file transfers
From: Daniel Barkalow @ 2005-06-24 16:38 UTC (permalink / raw)
To: Russell King; +Cc: git
In-Reply-To: <20050623111255.A1162@flint.arm.linux.org.uk>
On Thu, 23 Jun 2005, Russell King wrote:
> Last night, I pulled Linus' kernel tree from k.o, but Linus was in the
> middle of pushing an update to it. The way cogito works, it grabs the
> HEAD first, and then rsyncs the objects.
It needs to do this, in case HEAD changes after or during the rsync (to
include objects written after the rsync looked for them).
> However, this retrieved the updated HEAD, and only some of the objects.
> cogito happily tried to merge the result, and failed. A later pull
> and git-fsck-cache confirmed everything was fine _in this instance_.
It should be fine in all instances; it makes no assuptions about the
presence or absence of objects in the local database before the pull, so
doing a pull after the previous one didn't work right should be just as
likely to result in a functional state as any other pull.
> Therefore, may I suggest the following two changes in the way git
> works:
>
> 1. a push updates HEAD only after the rsync/upload of all objects is
> complete. This means that any pull will not try to update to the
> new head with a partial object tree.
git-ssh-push only updates the HEAD (or, rather, the thing the HEAD is a
symlink to) afterwards. I'm not sure how Linus was getting things
there. It's also possible that the mirroring process is failing to
maintain this constraint.
> 2. a pull only tries to fetch objects if HEAD has been updated since
> the last pull.
That's no good; if the only recent change is a new tag, you want to get
the tag object. Also, having it not do this is what let it recover in your
case on the second try. The only risk is that you'll pick up some objects
that you don't need yet (but would need if you pulled again when the push
completes).
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: git Tutorial?
From: Linus Torvalds @ 2005-06-24 16:37 UTC (permalink / raw)
To: Patrick Mochel; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.50.0506240842090.24799-100000@monsoon.he.net>
[ git-list cc'd, since these example things might be useful to others ]
On Fri, 24 Jun 2005, Patrick Mochel wrote:
>
> I've been able to make my away around a bit so far. And, as long as
> everything is cached in memory, it's pretty damn fast.
Indeed. It can be slow if things aren't in cache, but even then it's
usually not really slower than something like CVS would be.
> The handy things I've noticed missing are the equivalents of
>
> - bk changes -u<user> (Great for tracking down a change one did)
You can script it (and if you do so nicely, feel free to send me a
patch). Here's the magic long-hand version that does something fairly
close to it:
git-rev-list --header HEAD |
grep -z author.*torvalds |
tr '\0\n' '\n:' |
cut -d: -f1 |
git-diff-tree --pretty --stdin -p |
less -S
(That's really hacky, because "cut" and other standard unix tools don't
like using '\0' as a record separator, but hey, whatever works..)
The above gives the result in "git-whatchanged" format, ie you get the
patch too. If you don't want to see the patch, give the "-s" flag to
git-diff-tree instead of the "-p" flag, but if you script it, I'd suggest
allowing the user to give that as an option to the script.
> - bk undo (Good for fixing a quick screw up)
Same deal. No nice script, but it's easy to do:
- find the top-of-tree you want to go back to. If you know this is the
parent of the current HEAD, you can use the git-rev-parse helper:
target=$(git-rev-parse HEAD^)
to find that.
- do a "fast-forward" from the current HEAD to the head you want to go
to. Never mind that it's a "fast-backward" in this case, that's
symmetrical:
git-read-tree -m -u HEAD $target &&
(echo $target > .git/HEAD)
This magic line just says "merge (-m) while keeping the working
directory up-to-date with the changes (-u) from my current position
(HEAD) to my new position ($target), and if that worked, write the new
position into the HEAD file"
- If you then want to get _rid_ of the old HEAD stuff (ie you know you
don't want to go back to it) you can then follow up with a "git prune",
which will prune away all the unreachable objects. Be careful, though,
that really _will_ throw it all away, and it's gone, gone, gone. Before
you did "git prune", you could still get your old data back by just
looking for unconnected commits (git-fsck-cache and git-cat-file will
help you) and doing the above in reverse.
And that was it. You can make it even nicer when scripting by using
something like this
#!/bin/sh
# get the thing to undo to (default the first parent of the
# last commit, regardless of whether it was a merge or a
# regular commit
#
default_target=$(git-rev-parse HEAD^)
target=$(git-rev-parse --default $default_target --revs-only "$@")
# Check that it's a valid commit
git-cat-file commit "$target" > /dev/null || exit 1
# Do it
git-read-tree -m -u HEAD $target &&
(echo $target > .git/HEAD)
and then you can add some fancy flags or whatever.
> - bk export -tpatch -r<rev>
This one is trivial.
git-diff-tree --pretty $rev
does exactly that: it shows a single revision, with a pretty changelog.
And if you want to get diffs or ranges, use
git diff rev1..rev2
or similar.
Linus
^ permalink raw reply
* Re: rev-parse, unknown arguments and extended sha1's
From: Sven Verdoolaege @ 2005-06-24 16:17 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506240904240.11175@ppc970.osdl.org>
On Fri, Jun 24, 2005 at 09:09:23AM -0700, Linus Torvalds wrote:
> Anyway, add the --revs-only, and the test against empty should make a bit
> more sense. In fact, it _should_ test that it's a SHA1 (and not a rev
> argument), but I couldn't come up with a good way to test that in shell.
>
This is what I use:
rev2=`echo $rev | sed -e 's/[^0-9a-f]//'`
rev3=`echo $rev2 | sed -e 's/........................................//'`
if test "x$rev3" = "x" -a "x$rev" = "x$rev2"; then
echo "valid SHA1"
fi
skimo
^ permalink raw reply
* Re: rev-parse, unknown arguments and extended sha1's
From: Linus Torvalds @ 2005-06-24 16:09 UTC (permalink / raw)
To: Sven Verdoolaege; +Cc: git
In-Reply-To: <20050624122436.GA15182@pc117b.liacs.nl>
On Fri, 24 Jun 2005, Sven Verdoolaege wrote:
>
> Is git-rev-parse supposed to echo arguments it doesn't understand ?
> It currently does, but git-checkout-script seems to think it doesn't:
>
> rev=$(git-rev-parse "$arg")
> if [ -z "$rev" ]; then
> echo "unknown flag $arg"
> exit 1
> fi
Argh, there's a "--revs-only" thing that I was planning to use there, some
remnant of an ealy plan (unimplemented) to use that to determine if it is
a filename to be checked out, or a revision.
But then I never got around to do the "specify individual filenames" part
of "git checkout".
Anyway, add the --revs-only, and the test against empty should make a bit
more sense. In fact, it _should_ test that it's a SHA1 (and not a rev
argument), but I couldn't come up with a good way to test that in shell.
Linus
^ permalink raw reply
* Re: Finding what change broke ARM
From: Linus Torvalds @ 2005-06-24 16:03 UTC (permalink / raw)
To: Russell King
Cc: Linux Kernel List, Git Mailing List, Andy Whitcroft, Dave Hansen
In-Reply-To: <20050624101951.B23185@flint.arm.linux.org.uk>
On Fri, 24 Jun 2005, Russell King wrote:
>
> When building current git for ARM, I see:
>
> CC arch/arm/mm/consistent.o
> arch/arm/mm/consistent.c: In function `dma_free_coherent':
> arch/arm/mm/consistent.c:357: error: `mem_map' undeclared (first use in this function)
> arch/arm/mm/consistent.c:357: error: (Each undeclared identifier is reported only once
> arch/arm/mm/consistent.c:357: error: for each function it appears in.)
> make[2]: *** [arch/arm/mm/consistent.o] Error 1
>
> How can I find what change elsewhere in the kernel tree caused this
> breakage?
Ahhah! A real-world example of what cool things git can do.
Anyway, the first starting point is _exactly_ the same as under BK, except
the syntax is very different, and git does it better, in fact:
git-whatchanged -p arch/arm/mm/consistent.c
However, in this case nothing has changed in that file over the whole
git history, so you get an empty answer. Let's go to phase two, but first
a comment:
> With bk, you could ask for a per-file revision history of the likely
> candidates, and then find the changeset to view the other related
> changes.
>
> With git... ? We don't have per-file revision history so...
We don't _store_ changes as per-file revision histories, but we do store
it in a way where finding out what happened is efficient even per-file.
While a line-by-line "annotate" is not efficient, the "what changed"
certainly is.
And git actually does better than BK (or _any_ per-file history thing),
because "git-whatchanged" actually works over directories or multiple
independent files too, and it works purely on pathnames, so you can say
"git-whatchanged" for a file that has gone away to see _why_ it went away.
In most other systems it's really hard to see what happened to something
that isn't there any more..
Anyway, the problem clearly didn't happen because of any changes to that
file at all, so here per-file history simply doesn't help. But never fear,
we're not screwed yet. In particular, you will now obviously suspect that
since it wasn't that _file_ that changed, and since you know what changed
in the ARM code, it's going to be a generic linux header file change that
screwed you over.
So phase #2 is to do
git-whatchanged -p include/linux
(which shows every commit that touches include/linux, and shows that part
as a patch, thus the "-p"). That starts up a pager on the results by
default, so we just be stupid about it and do a "/mem_map" to look for
changes that mention mem_map. Maybe we'll be lucky.
Even that doesn't show a whole lot: but it does point a very suspicious
finger to the recently merged sparse-mem stuff from Andy Whitcroft,
though.
And now you have a commit to look at, namely the "sparsemem memory model"
one, commit ID d41dee369bff3b9dcb6328d4d822926c28cc2594.
In fact, looking at it, I think it's simply config option changes, and
probably the SPARSEMEM config option that has preempted your lack of
DISCONTIGMEM support. But now you have somebody to blame and to ask for
help from: Andy Whitcroft and Dave Hansen, whom I've cc'd.
I might start phase #3 with
git-whatchanged -p mm/Kconfig arch/arm/Kconfig
but at this point you may already have enough of a clue that you don't
even care any more.
Linus
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Christopher Li @ 2005-06-24 12:38 UTC (permalink / raw)
To: Petr Baudis
Cc: Matt Mackall, Jeff Garzik, Linux Kernel, Git Mailing List,
mercurial
In-Reply-To: <20050624064101.GB14292@pasky.ji.cz>
On Fri, Jun 24, 2005 at 08:41:01AM +0200, Petr Baudis wrote:
> > 5.1) undo the last commit or pull
> >
> > $ hg undo
>
> $ cg-admin-uncommit
>
> Note that you should never do this if you already pushed the changes
> out, or someone might get them. (That holds for regular Git too.) See
>
> $ cg-help cg-admin-uncommit # (or cg-admin-uncommit --help)
>
> for details. (That's another Cogito's cool feature. Handy docs! ;-)
>
Does it still works if the last commit was interrupted or due to error for some
reason? Undo pull is pretty cool because you might pull a lot of commit
in one blow. Get rid of commit one by one is going to be painful. Some times
the object you pull has more than one chain of history it will be very nasty
if you want to clean it up.
Mercurial's undo is taking a snapshot of all the changed file's repo file length
at every commit or pull. It just truncate the file to original size and undo
is done.
Chris
^ permalink raw reply
* Re: Mercurial vs Updated git HOWTO for kernel hackers
From: Christopher Li @ 2005-06-24 12:19 UTC (permalink / raw)
To: Paolo Ciarrocchi
Cc: Theodore Ts'o, Andrea Arcangeli, Petr Baudis, mercurial,
Jeff Garzik, Linux Kernel, Git Mailing List
In-Reply-To: <4d8e3fd3050624064620a4945e@mail.gmail.com>
On Fri, Jun 24, 2005 at 03:46:21PM +0200, Paolo Ciarrocchi wrote:
> >
> > Which do you think is going to be faster to operate from a cold start
> > using 4200 rpm laptop drives? :-)
> >
> > - Ted
>
> That's quite intersting, what the rational behind such a difference in
> terms of disk occupation ?
>
Let me see. Mercurial using delta or full storage for the repository.
It insert a full node when it detect that delta it need to reach
certain node is too big. It just like MPEG movies, most of the frame
is delta to the previous frame. Once a while you have full frame to
allow you seek to.
But git has delta as well right? Another factor is that all file has
same path in mercurial using the same storage file. So in mercurial
it has far less file to store in the repository. Each file has two repository
files, the data storage file and the index file. Remember that file system
like ext3 is using blocks, if you store very small stuff on a file, it is
still going to take at least one block on disk. So that will defeat the delta
compression if the delta is always on a new file.
Chris
^ 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