Git development
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] diffcore-rename: support rename cache
From: Yann Dirson @ 2008-11-08  9:24 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: Junio C Hamano, git
In-Reply-To: <fcaeb9bf0811072001o6df7ae00k1b1bffaadf75d3a1@mail.gmail.com>

On Sat, Nov 08, 2008 at 11:01:20AM +0700, Nguyen Thai Ngoc Duy wrote:
> On 11/8/08, Junio C Hamano <gitster@pobox.com> wrote:
> > Yann Dirson <ydirson@altern.org> writes:
> >
> >  > On Fri, Nov 07, 2008 at 09:35:32PM +0700, Nguy???n Thái Ng???c Duy wrote:
> >  >> This patch teaches diffcore_rename() to look into
> >  >> $GIT_DIR/rename-cache and make use of it to recreate diff_filepair.
> >  >> With proper cache, there should be no available entry for estimation
> >  >> after exact matching.
> >  >
> >  > This is something I have thought about in the past, good to see that
> >  > implemented :)
> >  >
> >  >> Rename caching is per commit. I don't think abitrary tree-tree caching
> >  >> is worth it.
> >  >
> >  > That could be a nice complement to my directory-rename patch.
> >
> >
> > Has anybody thought about interaction between that caching and pathspec
> >  limited operation?
> >
> 
> I didn't. But I think all out-of-pathspec diff pairs are removed
> before it reaches diffcore_rename() so the cache has nothing to do
> with it (except it still loads full cache for a commit).

Well, it could be that an out-of-pathspec pair would have a better
score than an in-pathspec one.  Maybe cache recording should be turned
off when doing pathspec limitation ?

^ permalink raw reply

* Re: [PATCH 1/2] diffcore-rename: support rename cache
From: Nguyen Thai Ngoc Duy @ 2008-11-08  9:29 UTC (permalink / raw)
  To: Yann Dirson; +Cc: Junio C Hamano, git
In-Reply-To: <20081108092409.GD4030@nan92-1-81-57-214-146.fbx.proxad.net>

On 11/8/08, Yann Dirson <ydirson@altern.org> wrote:
> On Sat, Nov 08, 2008 at 11:01:20AM +0700, Nguyen Thai Ngoc Duy wrote:
>  > On 11/8/08, Junio C Hamano <gitster@pobox.com> wrote:
>  > > Yann Dirson <ydirson@altern.org> writes:
>  > >
>  > >  > On Fri, Nov 07, 2008 at 09:35:32PM +0700, Nguy???n Thái Ng???c Duy wrote:
>  > >  >> This patch teaches diffcore_rename() to look into
>  > >  >> $GIT_DIR/rename-cache and make use of it to recreate diff_filepair.
>  > >  >> With proper cache, there should be no available entry for estimation
>  > >  >> after exact matching.
>  > >  >
>  > >  > This is something I have thought about in the past, good to see that
>  > >  > implemented :)
>  > >  >
>  > >  >> Rename caching is per commit. I don't think abitrary tree-tree caching
>  > >  >> is worth it.
>  > >  >
>  > >  > That could be a nice complement to my directory-rename patch.
>  > >
>  > >
>  > > Has anybody thought about interaction between that caching and pathspec
>  > >  limited operation?
>  > >
>  >
>  > I didn't. But I think all out-of-pathspec diff pairs are removed
>  > before it reaches diffcore_rename() so the cache has nothing to do
>  > with it (except it still loads full cache for a commit).
>
>
> Well, it could be that an out-of-pathspec pair would have a better
>  score than an in-pathspec one.  Maybe cache recording should be turned
>  off when doing pathspec limitation ?

Right, recording should be turned off or something. Let me see..
-- 
Duy

^ permalink raw reply

* Re: [PATCH] checkout: Don't crash when switching away from an invalid branch.
From: Alexandre Julliard @ 2008-11-08 10:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, git
In-Reply-To: <7vbpwrf85x.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> For that matter, dying without removing the trace of that funny state
> might be even preferrable if you need to do postmortem to figure out why
> you got into such a funny state to begin with, but not everybody uses git
> to debug git.

It turns out to be user error, that was a tree I hadn't used in a long
time and I didn't realize it was using alternates, so HEAD was pointing
to a commit that had been rebased and garbage-collected in the source
repository.

Most other commands die with a "bad object HEAD" in that situation, and
checkout could certainly do that too, but I think it's nicer to provide
an easy way of getting out of that broken state.  I'll resend an updated
patch.

-- 
Alexandre Julliard
julliard@winehq.org

^ permalink raw reply

* Re: [PATCH 2/2] Cached the git configuration, which is now noticibly faster on windows.
From: Jakub Narebski @ 2008-11-08 10:13 UTC (permalink / raw)
  To: David Symonds; +Cc: John Chapman, git
In-Reply-To: <ee77f5c20811072119y65738f54o7e6792fb405c142c@mail.gmail.com>

"David Symonds" <dsymonds@gmail.com> writes:

> On Fri, Nov 7, 2008 at 7:22 PM, John Chapman <thestar@fussycoder.id.au> wrote:
> 
> > +_gitConfig = {}
> >  def gitConfig(key):
> > -    return read_pipe("git config %s" % key, ignore_error=True).strip()
> > +    if not _gitConfig.has_key(key):
> > +        _gitConfig[key] = read_pipe("git config %s" % key, ignore_error=True).strip()
> > +    return _gitConfig[key]
> 
> If this is truly a noticeable bottleneck on Windows, something like
> the following might be even better:  (completely untested!)
> 
> _gitConfig = None
> def gitConfig(key):
>   if _gitConfig is None:
>     lines = read_pipe("git config -l", ignore_error=True).readlines():
>     _gitConfig = dict([l.strip().split('=', 1) for l in lines])
>   return _gitConfig.get(key, None)

Wouldn't it be better to use "git config -l -z", split lines at "\0"
(NUL), and split key from value at first "\N" (CR)? This format was
meant for scripts.

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* [PATCH v2 1/2] diffcore-rename: support rename cache
From: Nguyễn Thái Ngọc Duy @ 2008-11-08 11:27 UTC (permalink / raw)
  To: git, Junio C Hamano, Yann Dirson; +Cc: Nguyễn Thái Ngọc Duy

This patch teaches diffcore_rename() to look into
$GIT_DIR/rename-cache and make use of it to recreate diff_filepair.
With proper cache, there should be no available entry for estimation
after exact matching.

Rename caching is per commit. I don't think abitrary tree-tree caching
is worth it.

$GIT_DIR/rename-cache spans out like $GIT_DIR/objects. Each file
corresponds to one commit. Its content consists of lines like this

<Destination SHA-1> <SPC> <Source SHA-1> <SPC> <Score in decimal> <NL>

This can be used to:

 - Make --find-copies-harder pratically usable for moderate-size
   repositories. The first "git show" on a linux kernel commit was 5.3
   sec, it then went down to 0.13 sec.
 - Give git-svn a chance to (locally) import explicit renames from
   Subversion
 - People may correct rename results for better diff, if automatic
   rename detection is not good enough.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 >  > > Has anybody thought about interaction between that caching and pathspec
 >  > >  limited operation?
 >  > >
 >  >
 >  > I didn't. But I think all out-of-pathspec diff pairs are removed
 >  > before it reaches diffcore_rename() so the cache has nothing to do
 >  > with it (except it still loads full cache for a commit).
 >
 >
 > Well, it could be that an out-of-pathspec pair would have a better
 >  score than an in-pathspec one.  Maybe cache recording should be turned
 >  off when doing pathspec limitation ?

 Changes from v1:
  - rebased to next to avoid conflict
  - no longer generate cache if pathspec is used

 diff.h                  |    2 +
 diffcore-rename.c       |  142 ++++++++++++++++++++++++++++++++++++++++++++++-
 log-tree.c              |    2 +
 t/t4031-rename-cache.sh |   56 ++++++++++++++++++
 4 files changed, 200 insertions(+), 2 deletions(-)
 create mode 100755 t/t4031-rename-cache.sh

diff --git a/diff.h b/diff.h
index 42582ed..64a1edd 100644
--- a/diff.h
+++ b/diff.h
@@ -111,6 +111,8 @@ struct diff_options {
 	add_remove_fn_t add_remove;
 	diff_format_fn_t format_callback;
 	void *format_callback_data;
+
+	struct commit *commit;
 };
 
 enum color_diff {
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 168a95b..598cc8d 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -5,6 +5,7 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "hash.h"
+#include "commit.h"
 
 /* Table of rename/copy destinations */
 
@@ -409,13 +410,130 @@ static void record_if_better(struct diff_score m[], struct diff_score *o)
 		m[worst] = *o;
 }
 
+struct cached_filepair {
+	unsigned char dst[20];
+	unsigned char src[20];
+	int score;
+};
+
+static int free_cached_filepair(void *p)
+{
+	free(p);
+	return 0;
+}
+
+static void load_rename_cache(struct diff_queue_struct *q,
+			      struct diff_queue_struct *cacheq,
+			      struct diff_options *options)
+{
+	char *sha1_hex;
+	FILE *fp;
+	struct hash_table filepair_table;
+	struct hash_table src_table;
+	struct cached_filepair *pp;
+	int i, hash;
+	static int no_cache_available = -1;
+	struct stat st;
+	char *path;
+
+	if (no_cache_available == -1)
+		no_cache_available = stat(git_path("rename-cache"), &st) || !S_ISDIR(st.st_mode);
+
+	/* return soon so we don't need to waste CPU */
+	if (no_cache_available > 0)
+		return;
+
+
+	/* src_table initialization */
+	init_hash(&src_table);
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		if (DIFF_FILE_VALID(p->one)) {
+			unsigned int hash = hash_filespec(p->one);
+			insert_hash(hash, p, &src_table);
+		}
+	}
+
+	/* filepair_table initialization */
+	init_hash(&filepair_table);
+	sha1_hex = sha1_to_hex(options->commit->object.sha1);
+	path = git_path("rename-cache/%c%c/%s",sha1_hex[0], sha1_hex[1], sha1_hex+2);
+	if (stat(path, &st))
+		fp = NULL;
+	else
+		fp = fopen(path, "r");
+	if (fp) {
+		char src_sha1_hex[41], dst_sha1_hex[41];
+		struct cached_filepair p;
+
+		src_sha1_hex[40] = dst_sha1_hex[40] = '\0';
+		while (fscanf(fp, "%40c %40c %d\n", dst_sha1_hex, src_sha1_hex, &p.score) == 3) {
+			if (get_sha1_hex(src_sha1_hex, p.src) ||
+			    get_sha1_hex(dst_sha1_hex, p.dst))
+				break;
+
+			pp = xmalloc(sizeof(*pp));
+			memcpy(pp, &p, sizeof(*pp));
+			memcpy(&hash, p.dst, sizeof(hash));
+			insert_hash(hash, pp, &filepair_table);
+		}
+		fclose(fp);
+	}
+
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		struct diff_filepair *dp, *src;
+
+		/* find remote_dst */
+		if (DIFF_FILE_VALID(p->one) ||
+		    !DIFF_FILE_VALID(p->two) ||
+		    (options->single_follow && strcmp(options->single_follow, p->two->path)))
+			continue;
+
+		memcpy(&hash, p->two->sha1, sizeof(hash));
+		pp = lookup_hash(hash, &filepair_table);
+		if (!pp || memcmp(p->two->sha1, pp->dst, 20))
+			continue;
+
+		/* create pair */
+		if (is_null_sha1(pp->src)) {
+			if (DIFF_FILE_VALID(p->one))
+				continue;
+			diff_q(cacheq, p);
+			q->queue[i] = NULL;
+			continue;
+		}
+
+		memcpy(&hash, pp->src, sizeof(hash));
+		src = lookup_hash(hash, &src_table);
+		if (!src || memcmp(pp->src, src->one->sha1, 20))
+			continue;
+
+		src->one->rename_used++;
+		src->one->count++;
+		p->two->count++;
+
+		dp = diff_queue(NULL, src->one, p->two);
+		dp->renamed_pair = 1;
+		dp->score = pp->score;
+
+		diff_q(cacheq, dp);
+		q->queue[i] = NULL;
+		diff_free_filepair(p);
+	}
+
+	for_each_hash(&filepair_table, free_cached_filepair);
+	free_hash(&src_table);
+	free_hash(&filepair_table);
+}
+
 void diffcore_rename(struct diff_options *options)
 {
 	int detect_rename = options->detect_rename;
 	int minimum_score = options->rename_score;
 	int rename_limit = options->rename_limit;
 	struct diff_queue_struct *q = &diff_queued_diff;
-	struct diff_queue_struct outq;
+	struct diff_queue_struct outq, cacheq;
 	struct diff_score *mx;
 	int i, j, rename_count;
 	int num_create, num_src, dst_cnt;
@@ -423,8 +541,19 @@ void diffcore_rename(struct diff_options *options)
 	if (!minimum_score)
 		minimum_score = DEFAULT_RENAME_SCORE;
 
+	cacheq.queue = NULL;
+	cacheq.nr = cacheq.alloc = 0;
+
+	if (detect_rename && options->commit)
+		load_rename_cache(q, &cacheq, options);
+
 	for (i = 0; i < q->nr; i++) {
 		struct diff_filepair *p = q->queue[i];
+
+		/* was consumed by rename cache */
+		if (!p)
+			continue;
+
 		if (!DIFF_FILE_VALID(p->one)) {
 			if (!DIFF_FILE_VALID(p->two))
 				continue; /* unmerged */
@@ -563,10 +692,17 @@ void diffcore_rename(struct diff_options *options)
 	 */
 	outq.queue = NULL;
 	outq.nr = outq.alloc = 0;
-	for (i = 0; i < q->nr; i++) {
+	for (i = j = 0; i < q->nr; i++) {
 		struct diff_filepair *p = q->queue[i];
 		struct diff_filepair *pair_to_free = NULL;
 
+		if (!p) {
+			if (j >= cacheq.nr)
+				die("Internal error: running out of cacheq.");
+			diff_q(&outq, cacheq.queue[j++]);
+			continue;
+		}
+
 		if (!DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
 			/*
 			 * Creation
@@ -635,6 +771,8 @@ void diffcore_rename(struct diff_options *options)
 	diff_debug_queue("done copying original", &outq);
 
 	free(q->queue);
+	if (cacheq.queue)
+		free(cacheq.queue);
 	*q = outq;
 	diff_debug_queue("done collapsing", q);
 
diff --git a/log-tree.c b/log-tree.c
index 5444f08..040e095 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -522,6 +522,7 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
 	log.commit = commit;
 	log.parent = NULL;
 	opt->loginfo = &log;
+	opt->diffopt.commit = commit;
 
 	shown = log_tree_diff(opt, commit, &log);
 	if (!shown && opt->loginfo && opt->always_show_header) {
@@ -531,5 +532,6 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
 	}
 	opt->loginfo = NULL;
 	maybe_flush_or_die(stdout, "stdout");
+	opt->diffopt.commit = NULL;
 	return shown;
 }
diff --git a/t/t4031-rename-cache.sh b/t/t4031-rename-cache.sh
new file mode 100755
index 0000000..f7c53fd
--- /dev/null
+++ b/t/t4031-rename-cache.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nguyen Thai Ngoc Duy
+#
+
+test_description='Test diff rename cache'
+. ./test-lib.sh
+
+cat >expected <<EOF
+ create mode 100644 sub/c
+ copy a => sub/d (100%)
+EOF
+test_expect_success 'setup' '
+	echo a > a
+	echo b > b
+	mkdir sub
+	echo c > sub/c
+	cp a sub/d
+	A_SHA1=$(git hash-object a)
+	B_SHA1=$(git hash-object b)
+	C_SHA1=$(git hash-object sub/c)
+	D_SHA1=$(git hash-object sub/d)
+	git add a b
+	test_tick
+	git commit -m first
+	git add sub
+	git commit -m second
+	git show --pretty=oneline --summary -C -M --find-copies-harder HEAD|sed 1d > result
+	test_cmp expected result
+'
+
+cat >expected <<EOF
+ copy a => sub/c (100%)
+ copy a => sub/d (100%)
+EOF
+test_expect_success 'load rename pair cache' '
+	P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,")
+	mkdir -p $(dirname $P)
+	echo $C_SHA1 $A_SHA1 60000 >> $P
+	git show --pretty=oneline --summary -C -M --find-copies-harder HEAD|sed 1d > result
+	test_cmp expected result
+'
+
+cat >expected <<EOF
+ copy a => sub/c (100%)
+ create mode 100644 sub/d
+EOF
+test_expect_success 'load create pair cache' '
+	P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,")
+	mkdir -p $(dirname $P)
+	echo $D_SHA1 0000000000000000000000000000000000000000 0 >> $P
+	git show --pretty=oneline --summary -C -M --find-copies-harder HEAD|sed 1d > result
+	test_cmp expected result
+'
+
+test_done
-- 
1.6.0.3.892.g83538

^ permalink raw reply related

* [PATCH v2 2/2] diffcore-rename: add config option to allow to cache renames
From: Nguyễn Thái Ngọc Duy @ 2008-11-08 11:27 UTC (permalink / raw)
  To: git, Junio C Hamano, Yann Dirson; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1226143653-3758-1-git-send-email-pclouds@gmail.com>

If diff.cacherenames is true, then renames will be cached to
$GIT_DIR/rename-cache. By default, it will not overwrite existing
cache. Add --refresh-cache to overwrite.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/config.txt       |    5 ++++
 Documentation/diff-options.txt |    5 ++++
 diff.c                         |   12 +++++++++
 diff.h                         |    2 +
 diffcore-rename.c              |   49 ++++++++++++++++++++++++++++++++++++++++
 t/t4031-rename-cache.sh        |   36 +++++++++++++++++++++++++++++
 6 files changed, 109 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 965ed74..8a7f00e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -630,6 +630,11 @@ diff.renames::
 	will enable basic rename detection.  If set to "copies" or
 	"copy", it will detect copies, as well.
 
+diff.cacherenames::
+	Tells git to automatically cache renames when detected. The
+	cache resides in $GIT_DIR/rename-cache, which is used by git
+	if exists.
+
 fetch.unpackLimit::
 	If the number of objects fetched over the git native
 	transfer is below this
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index c62b45c..d477a40 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -102,6 +102,11 @@ endif::git-format-patch[]
 	Turn off rename detection, even when the configuration
 	file gives the default to do so.
 
+--refresh-rename-cache::
+	By default, when git finds a cached version of a commit, it
+	will not overwrite the cache. This option makes git overwrite
+	old cache or create a new one.
+
 --check::
 	Warn if changes introduce trailing whitespace
 	or an indent that uses a space before a tab. Exits with
diff --git a/diff.c b/diff.c
index f644947..604cb12 100644
--- a/diff.c
+++ b/diff.c
@@ -26,6 +26,7 @@ int diff_use_color_default = -1;
 static const char *external_diff_cmd_cfg;
 int diff_auto_refresh_index = 1;
 static int diff_mnemonic_prefix;
+static int diff_cache_renames;
 
 static char diff_colors[][COLOR_MAXLEN] = {
 	"\033[m",	/* reset */
@@ -103,6 +104,11 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
+	if (!strcmp(var, "diff.cacherenames")) {
+		diff_cache_renames = git_config_bool(var, value);
+		return 0;
+	}
+
 	switch (userdiff_config(var, value)) {
 		case 0: break;
 		case -1: return -1;
@@ -2272,6 +2278,8 @@ int diff_setup_done(struct diff_options *options)
 
 	if (options->detect_rename && options->rename_limit < 0)
 		options->rename_limit = diff_rename_limit_default;
+	if (options->detect_rename && diff_cache_renames)
+			DIFF_OPT_SET(options, CACHE_RENAMES);
 	if (options->setup & DIFF_SETUP_USE_CACHE) {
 		if (!active_cache)
 			/* read-cache does not die even when it fails
@@ -2439,6 +2447,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		DIFF_OPT_SET(options, RELATIVE_NAME);
 		options->prefix = arg + 11;
 	}
+	else if (!strcmp(arg, "--refresh-rename-cache")) {
+		DIFF_OPT_SET(options, CACHE_RENAMES);
+		DIFF_OPT_SET(options, REFRESH_RENAME_CACHE);
+	}
 
 	/* xdiff options */
 	else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
diff --git a/diff.h b/diff.h
index 64a1edd..0503b57 100644
--- a/diff.h
+++ b/diff.h
@@ -66,6 +66,8 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 #define DIFF_OPT_DIRSTAT_CUMULATIVE  (1 << 19)
 #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
 #define DIFF_OPT_ALLOW_TEXTCONV      (1 << 21)
+#define DIFF_OPT_CACHE_RENAMES       (1 << 22)
+#define DIFF_OPT_REFRESH_RENAME_CACHE (1 << 23)
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
 #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 598cc8d..49651ea 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -527,6 +527,44 @@ static void load_rename_cache(struct diff_queue_struct *q,
 	free_hash(&filepair_table);
 }
 
+static void save_rename_cache(struct diff_queue_struct *outq,
+			      struct diff_options *options)
+{
+	int i;
+	FILE *fp = NULL;
+	struct stat st;
+
+	for (i = 0;i < outq->nr; i++) {
+		struct diff_filepair *dp = outq->queue[i];
+
+		if (!(dp->renamed_pair || /* rename pair */
+		      (!DIFF_FILE_VALID(dp->one) && DIFF_FILE_VALID(dp->two)))) /* create pair */
+			continue;
+
+		if (!fp) {
+			char *sha1 = sha1_to_hex(options->commit->object.sha1);
+			char *path = git_path("rename-cache/%c%c/%s", sha1[0], sha1[1], sha1+2);
+
+			/* Already cached. If not force refresh, move on */
+			if (!stat(path, &st) && !DIFF_OPT_TST(options, REFRESH_RENAME_CACHE))
+				return;
+
+			safe_create_leading_directories(path);
+			fp = fopen(path, "w");
+
+			if (!fp)
+				return;
+		}
+
+		fprintf(fp, "%s ", sha1_to_hex(dp->two->sha1));
+		fprintf(fp, "%s %d\n",
+			sha1_to_hex(DIFF_FILE_VALID(dp->one) ?  dp->one->sha1 : null_sha1),
+			dp->score);
+	}
+	if (fp)
+		fclose(fp);
+}
+
 void diffcore_rename(struct diff_options *options)
 {
 	int detect_rename = options->detect_rename;
@@ -770,6 +808,17 @@ void diffcore_rename(struct diff_options *options)
 	}
 	diff_debug_queue("done copying original", &outq);
 
+	/*
+	 * Only cache if:
+	 * - Have a commit hint
+	 * - diff.cacherenames is on
+	 * - no pathspec limits
+	 */
+	if (options->commit &&
+	    DIFF_OPT_TST(options, CACHE_RENAMES) &&
+	    !options->nr_paths)
+		save_rename_cache(&outq, options);
+
 	free(q->queue);
 	if (cacheq.queue)
 		free(cacheq.queue);
diff --git a/t/t4031-rename-cache.sh b/t/t4031-rename-cache.sh
index f7c53fd..2d3f993 100755
--- a/t/t4031-rename-cache.sh
+++ b/t/t4031-rename-cache.sh
@@ -53,4 +53,40 @@ test_expect_success 'load create pair cache' '
 	test_cmp expected result
 '
 
+cat >expected <<EOF
+f2ad6c76f0115a6ba5b00456a849810e7ec0af20 0000000000000000000000000000000000000000 0
+78981922613b2afb6025042ff6bd878ac1994e85 78981922613b2afb6025042ff6bd878ac1994e85 60000
+EOF
+test_expect_success 'save rename cache' '
+	P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,")
+	rm -r .git/rename-cache
+	git config diff.cacherenames true
+	git show --summary -C -M --find-copies-harder > /dev/null
+	test_cmp expected $P
+'
+
+test_expect_success 'do not save rename cache with limited pathspec' '
+	P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,")
+	echo $P
+	rm $P
+	git config diff.cacherenames true
+	git log --summary -C -M --find-copies-harder HEAD -- sub
+	! test -f $P
+'
+
+test_expect_success 'subsequent command does not change cache' '
+	P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,")
+	echo corrupted > $P
+	! test_cmp expected $P &&
+	git show --summary -C -M --find-copies-harder HEAD > /dev/null &&
+	! test_cmp expected $P
+'
+
+test_expect_success 'overwrite cache with --refresh-rename-cache' '
+	P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,")
+	! test_cmp expected $P &&
+	git show --summary -C -M --find-copies-harder --refresh-rename-cache HEAD > /dev/null &&
+	test_cmp expected $P
+'
+
 test_done
-- 
1.6.0.3.892.g83538

^ permalink raw reply related

* Re: [PATCH 1/2] diffcore-rename: support rename cache
From: Jeff King @ 2008-11-08 11:47 UTC (permalink / raw)
  To: Yann Dirson; +Cc: Nguyen Thai Ngoc Duy, Junio C Hamano, git
In-Reply-To: <20081108092409.GD4030@nan92-1-81-57-214-146.fbx.proxad.net>

On Sat, Nov 08, 2008 at 10:24:10AM +0100, Yann Dirson wrote:

> Well, it could be that an out-of-pathspec pair would have a better
> score than an in-pathspec one.  Maybe cache recording should be turned
> off when doing pathspec limitation ?

One thing I notice is that the cache works at the level of "here is the
best rename for this commit." Maybe it could go down a level and say
"here is the inexact rename score between these blobs". Then you would
still find the best score between two blobs each time, but save the
really computationally intensive part (which is comparing the actual
_content_ of the blobs).

That should work in the face of path limiting or any other option,
because it is caching something immutable: this is the similarity score
between two pieces of content. And then you get arbitrary tree-to-tree
speedups for free, since such a cache would be valid for every commit.

The downsides are:

 - your cache is potentially bigger, since you are caching the score of
   every pair you look at, instead of just "good" pairs (OTOH, you are
   not doing a per-commit cache, which helps reduce the size)

 - you can still "lie" about a score to pre-seed imported SVN renames,
   but such lying will actually apply to all commits.

-Peff

^ permalink raw reply

* Re: [minor usability suggestion] git rebase <upstream> --onto <newbase> ?
From: Ingo Molnar @ 2008-11-08 11:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Daniel Barkalow, git
In-Reply-To: <7vy6zvfdp5.fsf@gitster.siamese.dyndns.org>


* Junio C Hamano <gitster@pobox.com> wrote:

> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > "git log origin/master -p" works, though.
> 
> That's an accident.  Do not rely on it.

hm, i frequently rely on tacking-on options after the fact, especially 
the -- ones.

Just like the best workflow is append-mostly, command parameters are 
often added append-only as well, without jumping back and forth in the 
command line to edit the command.

Path or brach names starting with '--' are weird anyway, so isnt this 
a reasonable expectation? I hope i'm not misunderstanding something 
here.

	Ingo

^ permalink raw reply

* Re: [PATCH 1/2] diffcore-rename: support rename cache
From: Nguyen Thai Ngoc Duy @ 2008-11-08 12:00 UTC (permalink / raw)
  To: Jeff King; +Cc: Yann Dirson, Junio C Hamano, git
In-Reply-To: <20081108114719.GA4989@sigill.intra.peff.net>

On 11/8/08, Jeff King <peff@peff.net> wrote:
> On Sat, Nov 08, 2008 at 10:24:10AM +0100, Yann Dirson wrote:
>
>  > Well, it could be that an out-of-pathspec pair would have a better
>  > score than an in-pathspec one.  Maybe cache recording should be turned
>  > off when doing pathspec limitation ?
>
>
> One thing I notice is that the cache works at the level of "here is the
>  best rename for this commit." Maybe it could go down a level and say
>  "here is the inexact rename score between these blobs". Then you would
>  still find the best score between two blobs each time, but save the
>  really computationally intensive part (which is comparing the actual
>  _content_ of the blobs).
>  That should work in the face of path limiting or any other option,
>  because it is caching something immutable: this is the similarity score
>  between two pieces of content. And then you get arbitrary tree-to-tree
>  speedups for free, since such a cache would be valid for every commit.

I did that and realized the cost was not from each diff, in
--find-copies-harder case, but from the number of diffs you had to do.
Even with exact matching on linux-2.6.git, it could take significant
time (it was about 5 minutes in no-cache case, 1 minute without exact
match cache, and less than 1 sec if everything is cached).

>
>  The downsides are:
>
>   - your cache is potentially bigger, since you are caching the score of
>    every pair you look at, instead of just "good" pairs (OTOH, you are
>    not doing a per-commit cache, which helps reduce the size)

It is huge if you accidentially add --find-copies-harder to your
command, considering that every new file will be compared against
every files in tree (about 25k).

>   - you can still "lie" about a score to pre-seed imported SVN renames,
>    but such lying will actually apply to all commits.
-- 
Duy

^ permalink raw reply

* [PATCH] checkout: Don't crash when switching away from an invalid branch.
From: Alexandre Julliard @ 2008-11-08 12:03 UTC (permalink / raw)
  To: git

When using alternates, it is possible for HEAD to end up pointing to
an invalid commit. git checkout should be able to recover from that
situation without crashing.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
 builtin-checkout.c               |    8 ++++----
 t/t2011-checkout-invalid-head.sh |   18 ++++++++++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)
 create mode 100755 t/t2011-checkout-invalid-head.sh

diff --git a/builtin-checkout.c b/builtin-checkout.c
index 57b94d2..06904c3 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -47,7 +47,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
 
 	memset(&proc, 0, sizeof(proc));
 	argv[0] = name;
-	argv[1] = xstrdup(sha1_to_hex(old->object.sha1));
+	argv[1] = xstrdup(sha1_to_hex(old ? old->object.sha1 : null_sha1));
 	argv[2] = xstrdup(sha1_to_hex(new->object.sha1));
 	argv[3] = changed ? "1" : "0";
 	argv[4] = NULL;
@@ -492,10 +492,10 @@ static void update_refs_for_switch(struct checkout_opts *opts,
 	}
 
 	old_desc = old->name;
-	if (!old_desc)
+	if (!old_desc && old->commit)
 		old_desc = sha1_to_hex(old->commit->object.sha1);
 	strbuf_addf(&msg, "checkout: moving from %s to %s",
-		    old_desc, new->name);
+		    old_desc ? old_desc : "(invalid)", new->name);
 
 	if (new->path) {
 		create_symref("HEAD", new->path, msg.buf);
@@ -551,7 +551,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 	 * a new commit, we want to mention the old commit once more
 	 * to remind the user that it might be lost.
 	 */
-	if (!opts->quiet && !old.path && new->commit != old.commit)
+	if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
 		describe_detached_head("Previous HEAD position was", old.commit);
 
 	if (!old.commit) {
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
new file mode 100755
index 0000000..764bb0a
--- /dev/null
+++ b/t/t2011-checkout-invalid-head.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+test_description='checkout switching away from an invalid branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo hello >world &&
+	git add world &&
+	git commit -m initial
+'
+
+test_expect_success 'checkout master from invalid HEAD' '
+	echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+	git checkout master --
+'
+
+test_done
-- 
1.6.0.3.669.g76740

-- 
Alexandre Julliard
julliard@winehq.org

^ permalink raw reply related

* [question] git svn fail to fetch GCC source due to index mismatch
From: dennis @ 2008-11-07 20:24 UTC (permalink / raw)
  To: git

HI:
   I have problem when use git svn fetch command to
retrieve the GCC source code.
It says index mismatch, then  abort,  any suggestion?

  
$git svn fetch
Index mismatch: 98ba56dbceddf50ebfab9e4649e9b1b1a319b377 !=
4f40f4619690f89454614be0eba63d584d25523e
rereading 19e22aa4cbc9f7e3667243481f33c859e3bba358
Found possible branch point: svn://gcc.gnu.org/svn/gcc/trunk =>
svn://gcc.gnu.org/svn/gcc/trunk, 130802
Initializing parent: git-svn@130802
Found branch parent: (git-svn) 9a08076e1ad241080838d547f64a2a9aceb083ca
Index mismatch: 4f40f4619690f89454614be0eba63d584d25523e !=
98ba56dbceddf50ebfab9e4649e9b1b1a319b377
rereading 9a08076e1ad241080838d547f64a2a9aceb083ca
Following parent with do_switch
Malformed network data: Malformed network data at
/usr/libexec/git-core/git-svn line 2340

$git branch -a
git-svn
git-svn@130802
 

^ permalink raw reply

* Re: libgit2 - a true git library
From: Steve Frécinaux @ 2008-11-08 13:26 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git, Scott Chacon
In-Reply-To: <20081031170704.GU14786@spearce.org>

Shawn O. Pearce wrote:
> During the GitTogether we were kicking around the idea of a ground-up
> implementation of a Git library.  This may be easier than trying
> to grind down git.git into a library, as we aren't tied to any
> of the current global state baggage or the current die() based
> error handling.
> 
> I've started an _extremely_ rough draft.  The code compiles into a
> libgit.a but it doesn't even implement what it describes in the API,
> let alone a working Git implementation.  Really what I'm trying to
> incite here is some discussion on what the API looks like.

Just a random question: is there a reason why you have put all the .h in 
a separate includes/ directory instead of relying on the install target 
to put the include files at the right place ?

To me it makes it much harder to hack on the files as one is always 
required to switch between both directories...

^ permalink raw reply

* Re: How it was at GitTogether'08 ?
From: Jeff King @ 2008-11-08 14:17 UTC (permalink / raw)
  To: Johan Herland; +Cc: git, Jakub Narebski
In-Reply-To: <200811080441.25796.johan@herland.net>

On Sat, Nov 08, 2008 at 04:41:25AM +0100, Johan Herland wrote:

> > * Discussion on notes
> 
> Can someone elaborate on this? AFAIK, notes have popped up on this list 
> often enough that I'm convinced it would be a _really_ useful feature. The 
> only drawback I was aware of, was the lack of an efficient implementation, 
> but then Jeff comes out of the blue and posts some interesting numbers [1] 
> a week or so ago. Does this mean there are no remaining obstacles?
> 
> [1]: http://article.gmane.org/gmane.comp.version-control.git/99415

The discussion was along the lines of "here are some more cool things we
could do, if we had notes." I don't remember the specifics of the cool
things, but they were related to annotating patches with review
information. Shawn can probably elaborate more.

That led to a "notes as a tree are nice, but too slow because looking up
a tree entry is linear" (and obviously you do a ton of lookups in the
notes tree during "git log"). Dscho had posted an implementation with a
persistent notes cache long ago. Since I failed to actually look at
that, I started on a slightly different approach, which is simply doing
an in-memory hash table to speedup the notes tree. And those are the
numbers and patch I posted.

My eventual plan was to re-work Dscho's patches with this performance
approach. But it is not at the top of my queue, so if somebody else
wanted to pick it up, I would be very happy. Everything I have done so
far is in the post you referenced.

The only other thing I remember discussing was notes namespaces. The two
obvious approaches are:

 1. a separate ref for each notes namespace, with each note ending up a
    blob in a tree. So you might have refs/notes/acked-by:$SHA1 as a
    blob.

 2. one notes ref, with the notes tree pointing a sub-tree that has
    named entries, one for each note type. So you might have
    refs/notes:$SHA1/acked-by as a blob.

The advantage of '1' is that it keeps your different note types
separate, which means it is easy to distribute one type but not the
other. The advantage of '2' is that I do one lookup per-commit, and then
I can see all of the notes, which keeps performance nice when you want
to annotate with several note types.

After some discussion, I think Dscho and I came to the conclusion that
supporting both might be desirable. And it should be pretty
straightforward. You can just have multiple note refs (but default to a
"main" one), and within each one, either point to a tree or blob (and we
will see which and use it appropriately).

And then depending on which notes the user wants, they can refer to them
appropriately. My suggestion for naming (and this wasn't discussed
earlier, so Dscho has not endorsed this) would be something like
"$X:$Y", which would mean "to get the notes for $SHA1, look at the tree
in refs/notes/$X for the file $SHA1/$Y". If $Y is empty, then expect
$SHA1 to be a blob (if it's a tree, maybe look at $SHA1/default). If
"$X" is empty, then use "refs/notes/default". If there is no colon,
assume we have "$Y".

So you could have a bunch of notes in some "main" namespace just by
calling them some name; without a name, you get some "default" note. But
if you wanted a separate database (say, for SVN information), you could
use "svn:" or "svn:name".

-Peff

^ permalink raw reply

* Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo
From: Jeff King @ 2008-11-08 14:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Sam Vilain
In-Reply-To: <7v3ai3f7oa.fsf@gitster.siamese.dyndns.org>

On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:

> > The FAQ even says "don't do this until you know what you are doing." So
> > the safety valve is configurable, so that those who know what they are
> > doing can switch it off.
> 
> "We are breaking your existing working setup but you can add a new
> configuration to unbreak it" should not be done lightly.  I think as the
> end result it is a reasonable thing to aim for for this particular
> feature, but we do need a transition plan patch in between that introduces
> a step that warns but not forbids.  We can ship 1.6.1 with it and then
> switch the default to forbid in 1.6.3, for example.

Yeah, I was kind of hoping we could assume that anybody relying on this
behavior was somewhat insane, and wouldn't be too upset when it broke.
But you're probably right that we should be more conservative. I'll
rework it with a "yes/no/warn" option for the config, and we can set it
to "warn" (and those who really do want it can shut off the warning with
"no"). Or we can even start with just leaving it on "no", but I think
the deprecation period should begin when we switch it to "warn".

> > Patch 4/4 is the interesting one. 1/4 is a cleanup I saw while fixing
> > tests. 2/4 is a cleanup to prepare for 3/4. And 3/4 fixes a bunch of
> > tests which were inadvertently doing such a push (but didn't care
> > because they didn't look at the working directory).
> 
> I wonder if you can use the tests 3/4 touches as the test for your "keep
> existing setup" configuration variable, pretending that they are old
> timer's repositories?

Yes, they do break with 4/4 applied without 3/4 (that was how I found
them, but "git rebase -i" let me pretend I had the proper foresight. ;)
). We can keep 3/4 back until the switch from "warn" to "yes", if that's
what you are suggesting.

-Peff

^ permalink raw reply

* Re: libgit2 - a true git library
From: Andreas Ericsson @ 2008-11-08 14:35 UTC (permalink / raw)
  To: Steve Frécinaux; +Cc: Shawn O. Pearce, git, Scott Chacon
In-Reply-To: <4915939B.1070306@gmail.com>

Steve Frécinaux wrote:
> Shawn O. Pearce wrote:
>> During the GitTogether we were kicking around the idea of a ground-up
>> implementation of a Git library.  This may be easier than trying
>> to grind down git.git into a library, as we aren't tied to any
>> of the current global state baggage or the current die() based
>> error handling.
>>
>> I've started an _extremely_ rough draft.  The code compiles into a
>> libgit.a but it doesn't even implement what it describes in the API,
>> let alone a working Git implementation.  Really what I'm trying to
>> incite here is some discussion on what the API looks like.
> 
> Just a random question: is there a reason why you have put all the .h in 
> a separate includes/ directory instead of relying on the install target 
> to put the include files at the right place ?
> 
> To me it makes it much harder to hack on the files as one is always 
> required to switch between both directories...

I agree with this, but as I guess Shawn will do roughly 45 times more
work on it than me (according to current commit-count in git.git), I'll
live with it.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: pull --preserve-merges
From: Johannes Schindelin @ 2008-11-08 15:08 UTC (permalink / raw)
  To: Stephen Haberman; +Cc: git
In-Reply-To: <20081107160138.aa96405c.stephen@exigencecorp.com>

Hi,

On Fri, 7 Nov 2008, Stephen Haberman wrote:

> Awhile ago I brought up wanting to have a "rebase with preserve merges"
> option for `git pull`

That might be something you want, but you cannot call it

	git pull --preserve-merges

since everybody used to "pull = fetch && merge" would go "Huh? A merge 
_does_ preserve merges".

If at all, you could call it "--rebase=preserve-merges".

Ciao,
Dscho

^ permalink raw reply

* Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo
From: Johannes Schindelin @ 2008-11-08 15:12 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, git, Sam Vilain
In-Reply-To: <20081108142756.GC17100@coredump.intra.peff.net>

Hi,

On Sat, 8 Nov 2008, Jeff King wrote:

> On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:
> 
> > > The FAQ even says "don't do this until you know what you are doing." 
> > > So the safety valve is configurable, so that those who know what 
> > > they are doing can switch it off.
> > 
> > "We are breaking your existing working setup but you can add a new 
> > configuration to unbreak it" should not be done lightly.  I think as 
> > the end result it is a reasonable thing to aim for for this particular 
> > feature, but we do need a transition plan patch in between that 
> > introduces a step that warns but not forbids.  We can ship 1.6.1 with 
> > it and then switch the default to forbid in 1.6.3, for example.
> 
> Yeah, I was kind of hoping we could assume that anybody relying on this
> behavior was somewhat insane, and wouldn't be too upset when it broke.

I think I have a repository with "git read-tree -u -m HEAD" as update hook 
for that kind of behavior.

But I will not be the person responsible to keep that behavior, if I am 
the only one relying on it.

I very much like the approach of defaulting to "warn" for quite some time 
(but setting the variable to "refuse" in git-init) and then adapt the 
default after some time.

Ciao,
Dscho

^ permalink raw reply

* Re: Repo corrupted somehow?
From: Andrew Arnott @ 2008-11-08 15:19 UTC (permalink / raw)
  To: Eyvind Bernhardsen; +Cc: Daniel Barkalow, git
In-Reply-To: <77005B51-0170-42EC-BBA7-DCF39C7CFC5E@orakel.ntnu.no>

I thought that autocrlf always 'added' CRLF instead of adding merely
CR.  Dang.  I'd rather have CRLF text files.

On Wed, Nov 5, 2008 at 4:26 AM, Eyvind Bernhardsen
<eyvind-git@orakel.ntnu.no> wrote:
> On 5. nov.. 2008, at 06.56, Daniel Barkalow wrote:
>
>> On Tue, 4 Nov 2008, Andrew Arnott wrote:
>>
>>> It was the CRLF conversion.  When I played around with
>>> git config --global core.autocrlf true/false
>>> I got the problem to eventually go away.
>>>
>>> Thanks for all your responses.
>>
>> It's still worth debugging further, because git should know that it wrote
>> the files differently and not see that as changes. It's not too helpful to
>> have autocrlf if it causes this problem.
>
> I think I know what this is.  If a repository contains files with CRLFs,
> those files will show as modified when core.autcorlf is true (if you commit
> them, the CRLFs will be converted to CRs in the repository, so in a sense
> they _are_ modified).  Try turning autocrlf back on, cloning the repository,
> then touching all the files (to make git check them for changes) and see if
> you get the same problem.
>
> I proposed an alternative autocrlf implementation on the list a while back:
> making it an attribute instead of a configuration setting and adding a
> configuration setting to tell git which line ending is preferred when the
> autocrlf attribute is set.
>
> That would allow you to turn on autocrlf and let git convert all CRLFs to
> CRs in a single commit, thus converting a repository with CRLFs to one that
> can be used with autocrlf in a versioned way.  In theory that lets you check
> out new commits with EOL conversion while old commits will be left alone
> (avoiding the problem you saw), but since .gitattributes is read from the
> working directory and not the tree to be checked out, it doesn't work
> perfectly.
>
> I implemented the easy bit (reading autocrlf from .gitattributes), but for
> various reasons the patch has just been gathering dust in my private git.git
> repo.  Maybe I should dust it off :)
> --
> Eyvind
>
>

^ permalink raw reply

* Re: How it was at GitTogether'08 ?
From: Jakub Narebski @ 2008-11-08 15:31 UTC (permalink / raw)
  To: David Symonds; +Cc: git, Johannes Schindelin
In-Reply-To: <ee77f5c20811072108o21f97c97i8174f4f7ecd67030@mail.gmail.com>

On Sat, 8 Nov 2008, David Symonds wrote:
> On Fri, Nov 7, 2008 at 5:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:
> 
> Here's my thoughts on some of these talks.
> 
> > Mon, Oct 27, 2008
> > -----------------
> > * Dscho: Contributing with Git
> >  http://www.youtube.com/watch?v=j45cs5_nY2k
> 
> It was a good intro, but I was expecting a few more non-GitTogether
> people. We had quite a large room, but there was only about a dozen
> other people who came along. I don't know whether that was the fault
> of the timing, lack of advertising, or a lack of interest.

By the way, it would be nice to have transcript for this talk, just
like there is for Linus talk:
  http://git.or.cz/gitwiki/LinusTalk200705Transcript
(but this would take some doing).
 
It would be also nice to have slides for the talk available somewhere,
just like slides for "Git Chronicle".

> > * Junio: Git Chronicle
> >
> >  blog: Junio went though a sort of statistical history of the Git project
> >  that was fascinating (turns out there are still about 220 lines of code
> >  still around from Linus original first commit).
> 
> This was really interesting. It would be great to put this on a
> general web page instead of in a PDF.

Something like Sam Vilain slides from "perl.git" talk?, 
  http://utsl.gen.nz/talks/perl-history/slides/

It shouldn't be that hard, depending on the original program the slides
were made... well, it was made in Impress from OpenOffice.org 2.4; it
might have export to (X)HTML + images, and to SWF (Flash presentation).

> > * Petr: Renames Again and Again and Again
> >
> >  IRC: detection of wholesame renames of directories (WIP) and '--follow'
> >  limitation were mentioned, but outcome is unclear; pasky plans to hack
> >  together some patch implementing explicit renames hinting
> 
> One thing I didn't get around to bringing up: one of the benefits of
> diff-time rename detection that is often touted is that algorithms can
> improve over time. Do folk here know whether that has actually
> happened recently, in a general way? Do people actually expect major
> improvements in the future?

If I remember correctly there was at least one improvement in rename
detection, namely better talking into account filename similarity score,
so for example similar files moved (or copied) didn't get marked as
coming from one source (and rest deleted).

> > * Tom: GitHub
> >
> >  IRC: a tour, some history, and insight into how it works; some nice
> >  gimmicks, such as "gist" (a git backed pastebin), or like network graphs
> >  (look graphically at forks of a repository).
> >
> >  blog: Tom got to demonstrate GitHub and Gist to the group, most of whom
> >  are very command line oriented and had not used either before.
> 
> The demo of iGitHub (an iPhone app that can act as a clone/push
> target) looked really cool, if it can get further development. It
> could potentially be really handy for travellers who could push to
> their iPhone, and then push from there to an internet server.

iGitHub has nothing to do with GitHub; I think you put the comment in
a wrong place; the iGitHub (or iGit / iGitRouter) was a separate talk
in "Lighting Round Talks" next day.

> > * Scott: Linkable Library
> >
> >  blog: got to talk about the need for a linkable git library
> >
> >  http://thread.gmane.org/gmane.comp.version-control.git/99608
> 
> It's good to see this starting to get wider traction. I think we
> discussed that there could be benefits to git itself, beyond just
> helping other programs access git repositories faster than fork/exec.

What benefits would be those? Current design of "fire and forget",
which stopped libification efforts till now was used for a reason...

> > * Sam: perl.git
> >
> >  blog: Sam demonstrated the work he went through to import 20 years of Perl
> >  history into the git repository that the Perl team is just now finishing
> >  transitioning to from Perforce.
> >
> >  http://utsl.gen.nz/talks/perl-history/slides/
> 
> It was very cool to see old-school email addresses like <isis!aburt>
> in git, handled just fine.

This is not suprising, as Git treats committer and author email data
as opaque data, not analysing it at all (some commits from early
versions of git might not have this data at all, IIRC).
 
> > * Tim: Git as a Media Repository
> >  http://www.thousandparsec.net/~tim/media+git.pdf
> 
> This has kicked off some mailing list discussion; I think this can be
> a major weak point for git, since checking out only a subtree (and
> only the latest revision) is the common SVN way, which copes with
> media repositories and the like just fine.

Well, you can workaround this weakness by (ab)using submodules...
...and one should always remember that casual partial checkouts
interfere a bit with whole-tree commits.

-- 
Jakub Narebski
Poland

^ permalink raw reply

* [PATCH 7/7 v3 updated] bisect: use "--bisect-replace" options when checking merge bases
From: Christian Couder @ 2008-11-08 15:33 UTC (permalink / raw)
  To: Junio C Hamano, Johannes Schindelin; +Cc: git

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 git-bisect.sh             |    4 ++--
 t/t6035-bisect-replace.sh |   10 ++++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

	This is the same as [PATCH 7/7 v3] but with a test case
	added.

diff --git a/git-bisect.sh b/git-bisect.sh
index 1daa81c..87e186f 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -401,7 +401,7 @@ check_merge_bases() {
 	_bad="$1"
 	_good="$2"
 	_skip="$3"
-	for _mb in $(git merge-base --all $_bad $_good)
+	for _mb in $(git merge-base --all --bisect-replace $_bad $_good)
 	do
 		if is_among "$_mb" "$_good"; then
 			continue
@@ -436,7 +436,7 @@ check_good_are_ancestors_of_bad() {
 	# Bisecting with no good rev is ok
 	test -z "$_good" && return
 
-	_side=$(git rev-list $_good ^$_bad)
+	_side=$(git rev-list --bisect-replace $_good ^$_bad)
 	if test -n "$_side"; then
 		# Return if a checkout was done
 		check_merge_bases "$_bad" "$_good" "$_skip" || return
diff --git a/t/t6035-bisect-replace.sh b/t/t6035-bisect-replace.sh
index 8fe7cc5..dabf1ae 100755
--- a/t/t6035-bisect-replace.sh
+++ b/t/t6035-bisect-replace.sh
@@ -144,6 +144,16 @@ test_expect_success '"git merge-base --bisect-replace" works' '
      test "$hash" = "$HASH1"
 '
 
+test_expect_success 'git bisect works when starting on the replace branch' '
+     git bisect start $HASH7 $HASHFIX3 &&
+     test "$(git rev-parse --verify HEAD)" = "$HASH5" &&
+     git bisect bad &&
+     test "$(git rev-parse --verify HEAD)" = "$HASHFIX4" &&
+     git bisect good > my_bisect_log.txt &&
+     grep "$HASH5 is first bad commit" my_bisect_log.txt &&
+     git bisect reset
+'
+
 #
 #
 test_done
-- 
1.6.0.3.620.ge1fc

^ permalink raw reply related

* Re: absurdly slow git-diff
From: Davide Libenzi @ 2008-11-08 16:27 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Linus Torvalds, Abhijit Menon-Sen, Pierre Habouzit,
	Git Mailing List
In-Reply-To: <7v7i7eeqcz.fsf@gitster.siamese.dyndns.org>

On Fri, 7 Nov 2008, Junio C Hamano wrote:

> Davide Libenzi <davidel@xmailserver.org> writes:
> 
> > Yeah, similar. Mine is below. There's one less branch in the for loops.
> 
> Thanks, will apply like this, but I am not sure if you meant windowN or
> just window...

Whoops, just WINDOW.


- Davide

^ permalink raw reply

* Re: pull --preserve-merges
From: Francis Galiegue @ 2008-11-08 17:07 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Stephen Haberman, git
In-Reply-To: <alpine.DEB.1.00.0811081607300.30769@pacific.mpi-cbg.de>

Le Saturday 08 November 2008 16:08:41 Johannes Schindelin, vous avez écrit :
> Hi,
>
> On Fri, 7 Nov 2008, Stephen Haberman wrote:
> > Awhile ago I brought up wanting to have a "rebase with preserve merges"
> > option for `git pull`
>
> That might be something you want, but you cannot call it
>
> 	git pull --preserve-merges
>
> since everybody used to "pull = fetch && merge" would go "Huh? A merge
> _does_ preserve merges".
>
> If at all, you could call it "--rebase=preserve-merges".
>

Why not --rebase --keep-merges? Personnally, I think it makes things clearer 
since in general options are either standalone or have a value.

-- 
fge

^ permalink raw reply

* Init on push
From: Robin Rosenberg @ 2008-11-08 16:08 UTC (permalink / raw)
  To: git

Hi,

I am missing the ability to do this (command line or GUI)

git remote add someremote someurl
git push --init someremote/someurl

The implementation would invoke receive pack on the receiving side with
an --init option. On the server side the repository would be created and
initialized just as one had executed and mkdir and git init --bare.

The target audience is people who are either lazy (like me) or "shellofobic" users.
GUI's would get an extra check box.

This could be extended by passing options to the init switch with init options
for the server side, say --init="--shared=false".

Could a patch for this be acceptable?

-- robin

^ permalink raw reply

* Re: libgit2 - a true git library
From: Pierre Habouzit @ 2008-11-08 17:27 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: Steve Frécinaux, Shawn O. Pearce, git, Scott Chacon
In-Reply-To: <4915A3CB.5010909@op5.se>

[-- Attachment #1: Type: text/plain, Size: 1272 bytes --]

On Sat, Nov 08, 2008 at 02:35:55PM +0000, Andreas Ericsson wrote:
> Steve Frécinaux wrote:
> > Just a random question: is there a reason why you have put all the
> > .h in a separate includes/ directory instead of relying on the
> > install target to put the include files at the right place ?
> > To me it makes it much harder to hack on the files as one is always
> > required to switch between both directories...
> 
> I agree with this, but as I guess Shawn will do roughly 45 times more
> work on it than me (according to current commit-count in git.git), I'll
> live with it.

I don't, modifying the public includes may break the ABI and the API.

I believe it to be a good practice to put them in a separate directory
so that people modifying them will know this particular header is
public. Yes you can name your private headers differently, but it's not
really the same, it doesn't make editing public headers hard, and it has
to. People modifying them _have_ to thing "err why am I modifying this
specific header in the first place" before doing anything in it.

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: pull --preserve-merges
From: Stephen Haberman @ 2008-11-08 17:57 UTC (permalink / raw)
  To: Francis Galiegue; +Cc: Johannes Schindelin, git
In-Reply-To: <200811081807.53199.fg@one2team.net>


Replying to both Johannes and Francis...

> > > Awhile ago I brought up wanting to have a "rebase with preserve merges"
> > > option for `git pull`
> >
> > That might be something you want, but you cannot call it
> >
> > 	git pull --preserve-merges
> >
> > since everybody used to "pull = fetch && merge" would go "Huh? A merge
> > _does_ preserve merges".

Ah, right, sorry, Johannes, I know it only makes sense in the context if
--rebase is also being in use, I was just being too brief.

> > If at all, you could call it "--rebase=preserve-merges".

I'd be fine with that, I had not thought of it.

> Why not --rebase --keep-merges? Personnally, I think it makes things clearer 
> since in general options are either standalone or have a value.

I originally had --rebase --preserve-merges in mind because it matches
the existing -p/--preserve-merges flag that git rebase has that I'd
like git pull to just pass along.

If they were separate flags, passing just --preserve-merges without
--rebase should likely report an error. Probably the same thing if
someone sets `branch.name.preservemerges` but `branch.name.rebase` is
not set.

Unless instead of separate config parameters, `branch.name.rebase` uses
Johannes's suggestion and has separate values...true or false or
preserve-merges. That would probably better parallelize with the
--rebase=preserve-merges style command line argument.

Between one flag/config parameter or two flags/config parameters, I
could go either way and would be willing to patch together either one
to get it in.

Thanks,
Stephen

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox