Git development
 help / color / mirror / Atom feed
* [PATCH 1/2] diffcore-rename: support rename cache
From: Nguyễn Thái Ngọc Duy @ 2008-11-07 14:35 UTC (permalink / raw)
  To: git; +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>
---
 diff.h                  |    2 +
 diffcore-rename.c       |  142 ++++++++++++++++++++++++++++++++++++++++++++++-
 log-tree.c              |    2 +
 t/t4030-rename-cache.sh |   55 ++++++++++++++++++
 4 files changed, 199 insertions(+), 2 deletions(-)
 create mode 100755 t/t4030-rename-cache.sh

diff --git a/diff.h b/diff.h
index a49d865..8b68f6f 100644
--- a/diff.h
+++ b/diff.h
@@ -110,6 +110,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 cec3c06..a67ef6d 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -518,6 +518,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) {
@@ -527,5 +528,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/t4030-rename-cache.sh b/t/t4030-rename-cache.sh
new file mode 100755
index 0000000..0d8390c
--- /dev/null
+++ b/t/t4030-rename-cache.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nguyen Thai Ngoc Duy
+#
+
+test_description='Test diff rename cache'
+. ./test-lib.sh
+
+cat >expected <<EOF
+ create mode 100644 c
+ copy a => d (100%)
+EOF
+test_expect_success 'setup' '
+	for i in a b c
+	do
+		echo $i > $i
+	done
+	cp a d
+	A_SHA1=$(git hash-object a)
+	B_SHA1=$(git hash-object b)
+	C_SHA1=$(git hash-object c)
+	D_SHA1=$(git hash-object d)
+	git add a b
+	git commit -m first
+	git add c d
+	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 => c (100%)
+ copy a => 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 => c (100%)
+ create mode 100644 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.802.g47c38

^ permalink raw reply related

* Re: Git and Media repositories....
From: Santi Béjar @ 2008-11-07 13:19 UTC (permalink / raw)
  To: Tim Ansell; +Cc: git
In-Reply-To: <1225655428.11693.10.camel@vaio>

On Sun, Nov 2, 2008 at 8:50 PM, Tim Ansell <mithro@mithis.com> wrote:
> Hey guys,
>

[...]

>
> The general idea is that we always clone the complete meta-data (tags,
> commits and trees) and then only clone blobs when they are needed (using
> something like alternates). This allows us to support shallow, narrow
> and sparse checkouts while still being able to perform operations such
> as committing and merging.
>

A related use case could be to remove a blob from a repo but being
able to work normally with it, similar to:

http://wiki.freebsd.org/VCSFeatureObliterate

Santi

^ permalink raw reply

* [PATCH] Remove the period after the git-check-attr summary
From: Matt Kraai @ 2008-11-07 12:26 UTC (permalink / raw)
  To: git, gitster; +Cc: Matt Kraai

Signed-off-by: Matt Kraai <kraai@ftbfs.org>
---
The period at the end of the git-check-attr summary causes there to be
two periods after the summary in the git(1) manual page, so remove it.

 Documentation/git-check-attr.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index 256659a..8c2ac12 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -3,7 +3,7 @@ git-check-attr(1)
 
 NAME
 ----
-git-check-attr - Display gitattributes information.
+git-check-attr - Display gitattributes information
 
 
 SYNOPSIS
-- 
1.5.6.5

^ permalink raw reply related

* Re: Git and Media repositories....
From: Jakub Narebski @ 2008-11-07 13:00 UTC (permalink / raw)
  To: Tim Ansell; +Cc: git
In-Reply-To: <1225655428.11693.10.camel@vaio>

Tim Ansell <mithro@mithis.com> writes:

> Last week at the gittogether I lead some discussions about how we could
> make Git better support large media repositories (which is one area
> where Subversion still make sense). It was suggested that I post to this
> list to get a discussion going. 
> 
> The general idea is that we always clone the complete meta-data (tags,
> commits and trees) and then only clone blobs when they are needed (using
> something like alternates). This allows us to support shallow, narrow
> and sparse checkouts while still being able to perform operations such
> as committing and merging.
[...]

Well, the *workaround* you could currently use is to put large media
files in separate subdirectory, and make this subdirectory into
submodule.  This uses the fact that you can selectively clone
submodules, or leave them as a stubs...

...and this is also the code you might want to look at when
implementings stubs for 'remote' blob objects

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH 1/2] Introduce rename factorization in diffcore.
From: Jakub Narebski @ 2008-11-07 12:55 UTC (permalink / raw)
  To: Baz; +Cc: Yann Dirson, git
In-Reply-To: <2faad3050811070328t31babed4v1ba895a6ac36df94@mail.gmail.com>

Baz <brian.ewins@gmail.com> writes:
> 2008/10/30 Yann Dirson <ydirson@altern.org>:

> > Rename factorization tries to group together files moving from and to
> > identical directories - the most common case being directory renames.
> > This feature is activated by the new --factorize-renames diffcore
> > flag.
> 
> Sorry to bikeshed a bit here, but this isn't what 'factorize' means,
> and adding a flag with this name unnecessarily adds to the
> git-specific terms users have to learn.

Well, I think from _mathematical_ (arithmetic) point of view it makes
perfect sense.  Before you had:

  (rename-of-sub1-file1 rename-of-sub1-file2 rename-of-sub1-file3)

and after you have

  (rename-of-sub1) * (changes in files)
 
> Looking back through the archives, there's only a few people who've
> used the word 'factorize', and /mostly/ it seems to have been used as
> a synonym for 'refactor' in comments; not common usage but
> understandable. However in this case, factorize is being used in the
> opposite sense from its dictionary definition - to break down into
> factors - and instead is being used to mean to /combine/ things; I
> don't think that should be in the UI.
> 
> Why not just '--group-renames'?

That said, I think that '--group-renames' makes better sense (and is
shorted than '--detect-directory-renames')

+1 for '--group-renames'

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH (GITK) v3 6/6] gitk: Explicitly position popup windows.
From: Paul Mackerras @ 2008-11-07 11:57 UTC (permalink / raw)
  To: Alexander Gavrilov; +Cc: git
In-Reply-To: <1225652389-22082-7-git-send-email-angavrilov@gmail.com>

Alexander Gavrilov writes:

> For some reason, on Windows all transient windows are placed
> in the upper left corner of the screen. Thus, it is necessary
> to explicitly position the windows relative to their parent.
> For simplicity this patch uses the function that is used
> internally by Tk dialogs.

Is there any reason to call tk::PlaceWindow under Linux or MacOS?
If not I'd rather add an if statement so we only call it on Windows.

Paul.

^ permalink raw reply

* Re: [PATCH (GITK) v3 2/6] gitk: Make gitk dialog windows transient.
From: Paul Mackerras @ 2008-11-07 11:41 UTC (permalink / raw)
  To: Alexander Gavrilov; +Cc: git
In-Reply-To: <1225652389-22082-3-git-send-email-angavrilov@gmail.com>

Alexander Gavrilov writes:

> Transient windows are always kept above their parent,
> and don't occupy any space in the taskbar, which is useful
> for dialogs. Also, when transient is used, it is important
> to bind windows to the correct parent.
> 
> This commit adds transient annotations to all dialogs,
> ensures usage of the correct parent for error and
> confirmation popups, and, as a side job, makes gitk
> preserve the create tag dialog window in case of errors.
> 
> Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>

Thanks, applied.

Paul.

^ permalink raw reply

* Re: [PATCH (GITK) v3 4/6] gitk: Make cherry-pick call git-citool on conflicts.
From: Paul Mackerras @ 2008-11-07 11:51 UTC (permalink / raw)
  To: Alexander Gavrilov; +Cc: git
In-Reply-To: <1225652389-22082-5-git-send-email-angavrilov@gmail.com>

Alexander Gavrilov writes:

> Now that git-gui has facilities to help users resolve
> conflicts, it makes sense to launch it from other GUI
> tools when they happen.

The resolution capabilities of git citool seem to be that it detects
the conflict markers and lets you run meld on the 3 versions.  Have I
missed anything there?  Do people find that fixing things manually in
meld is sufficient, or do we really want something more powerful?

Paul.

^ permalink raw reply

* Re: [PATCH (GITK) v3 1/6] gitk: Add Return and Escape bindings to dialogs.
From: Paul Mackerras @ 2008-11-07 11:41 UTC (permalink / raw)
  To: Alexander Gavrilov; +Cc: git
In-Reply-To: <1225652389-22082-2-git-send-email-angavrilov@gmail.com>

Alexander Gavrilov writes:

> It is often more convenient to dismiss or accept a
> dialog using the keyboard, than by clicking buttons
> on the screen. This commit adds key binding to make
> it possible with gitk's dialogs.

Thanks, applied.

Paul.

^ permalink raw reply

* Re: [PATCH (GITK) v3 3/6] gitk: Add accelerators to frequently used menu commands.
From: Paul Mackerras @ 2008-11-07 11:50 UTC (permalink / raw)
  To: Alexander Gavrilov; +Cc: git
In-Reply-To: <1225652389-22082-4-git-send-email-angavrilov@gmail.com>

Alexander Gavrilov writes:

> -	eval $m add $params [lrange $i 4 end]
> +	set tail [lrange $i 4 end]
> +	regsub -all {\$M1T\y} $tail $M1T tail
> +	eval $m add $params $tail

This is solving the problem that the $M1T doesn't get expanded in the
call below because it's inside {}.  If we are going to have a magic
string that gets expanded like this, I'd rather it didn't look like a
variable reference, because that is confusing.

Alternatively, we could define a [meta] function that does this:

proc meta {x} {
    if {[tk windowingsystem] eq "aqua"} {
	return Cmd-$x
    }
    return Ctrl-$x
}

and then use -accelerator [meta F5] in the makemenu call, and not have
any magic string substitution in makemenu.  That will work since the
eval will evaluate the [].

Paul.

^ permalink raw reply

* Re: multiple-commit cherry-pick?
From: Miles Bader @ 2008-11-07 11:46 UTC (permalink / raw)
  To: Björn Steinbrink; +Cc: Deskin Miller, git
In-Reply-To: <20081107110331.GA2938@atjola.homenet>

>> >> > git reset --hard C
>> >> > git rebase --onto ORIG_HEAD A^

>> Hmm, I guess using rebase --abort isn't a very good idea in this case
>> though... :-/
>
> Why not? I mean, ok, you end up at C, and not where you have been before
> the reset --hard, but there's the reflog to help you get back to
> whatever previous state of the branch it is that you want.

I just mean it's not a trivial way to get back to the state before the
multi-cherry-pick -- you need to know the details of what's going on,
and handle the rest of the cleanup manually.

So, for instance, if you were to package up the above commands in a
shell script, the abort issue is one of those rough edges which would
prevent it from being as convenient as a real git command.  [A
hypothetical extension of the cherry-pick command to handle multiple
commits would presumably offer a "cherry-pick --abort" option that did
everything magically.]

-Miles

-- 
Do not taunt Happy Fun Ball.

^ permalink raw reply

* Re: [PATCH 1/2] Introduce rename factorization in diffcore.
From: Baz @ 2008-11-07 11:28 UTC (permalink / raw)
  To: Yann Dirson; +Cc: git
In-Reply-To: <20081030221645.3325.78288.stgit@gandelf.nowhere.earth>

2008/10/30 Yann Dirson <ydirson@altern.org>:
> Rename factorization tries to group together files moving from and to
> identical directories - the most common case being directory renames.
> This feature is activated by the new --factorize-renames diffcore
> flag.

Sorry to bikeshed a bit here, but this isn't what 'factorize' means,
and adding a flag with this name unnecessarily adds to the
git-specific terms users have to learn.

Looking back through the archives, there's only a few people who've
used the word 'factorize', and /mostly/ it seems to have been used as
a synonym for 'refactor' in comments; not common usage but
understandable. However in this case, factorize is being used in the
opposite sense from its dictionary definition - to break down into
factors - and instead is being used to mean to /combine/ things; I
don't think that should be in the UI.

Why not just '--group-renames'?

Cheers,
Baz

>
> This is only the first step, adding the basic functionnality and
> adding support to raw diff output (and it breaks unified-diff output
> which does not know how to handle that stuff yet).
>
> Even the output format may not be kept as is.  For now both the result
> of "mv a b" and "mv a/* b/" are displayed as "Rnnn a/ b/", which is
> probably not what we want.  "Rnnn a/* b/" could be a good choice for
> the latter if we want them to be distinguished, and even if we want
> them to look the same.
>
> Other future developements to be made on top of this include:
> * extension of unified-diff format to express this
> * application of such new diffs
> * teach git-svn (and others ?) to make use of that flag
> * merge correctly in case of addition into a moved dir
> * detect "directory splits" so merge can flag a conflict on file adds
> * use inexact dir renames to bump score of below-threshold renames
>  from/to same locations
> * add yours here
> ---
>
>  diff-lib.c        |    6 +
>  diff.c            |    5 +
>  diff.h            |    3 +
>  diffcore-rename.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++--
>  diffcore.h        |    1
>  tree-diff.c       |    4 +
>  6 files changed, 235 insertions(+), 11 deletions(-)
>
> diff --git a/diff-lib.c b/diff-lib.c
> index ae96c64..dcc4c2c 100644
> --- a/diff-lib.c
> +++ b/diff-lib.c
> @@ -179,7 +179,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
>                changed = ce_match_stat(ce, &st, ce_option);
>                if (!changed) {
>                        ce_mark_uptodate(ce);
> -                       if (!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
> +                       if (!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER) &&
> +                           !DIFF_OPT_TST(&revs->diffopt, FACTORIZE_RENAMES))
>                                continue;
>                }
>                oldmode = ce->ce_mode;
> @@ -310,7 +311,8 @@ static int show_modified(struct oneway_unpack_data *cbdata,
>
>        oldmode = old->ce_mode;
>        if (mode == oldmode && !hashcmp(sha1, old->sha1) &&
> -           !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
> +           !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER) &&
> +           !DIFF_OPT_TST(&revs->diffopt, FACTORIZE_RENAMES))
>                return 0;
>
>        diff_change(&revs->diffopt, oldmode, mode,
> diff --git a/diff.c b/diff.c
> index e368fef..f91fcf6 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -2437,6 +2437,11 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
>                DIFF_OPT_SET(options, REVERSE_DIFF);
>        else if (!strcmp(arg, "--find-copies-harder"))
>                DIFF_OPT_SET(options, FIND_COPIES_HARDER);
> +       else if (!strcmp(arg, "--factorize-renames")) {
> +               DIFF_OPT_SET(options, FACTORIZE_RENAMES);
> +               if (!options->detect_rename)
> +                       options->detect_rename = DIFF_DETECT_RENAME;
> +       }
>        else if (!strcmp(arg, "--follow"))
>                DIFF_OPT_SET(options, FOLLOW_RENAMES);
>        else if (!strcmp(arg, "--color"))
> diff --git a/diff.h b/diff.h
> index a49d865..db1658b 100644
> --- a/diff.h
> +++ b/diff.h
> @@ -65,6 +65,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
>  #define DIFF_OPT_IGNORE_SUBMODULES   (1 << 18)
>  #define DIFF_OPT_DIRSTAT_CUMULATIVE  (1 << 19)
>  #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
> +#define DIFF_OPT_FACTORIZE_RENAMES   (1 << 21)
>  #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)
> @@ -220,6 +221,8 @@ extern void diffcore_std(struct diff_options *);
>  "  -C            detect copies.\n" \
>  "  --find-copies-harder\n" \
>  "                try unchanged files as candidate for copy detection.\n" \
> +"  --factorize-renames\n" \
> +"                factorize renames of all files of a directory.\n" \
>  "  -l<n>         limit rename attempts up to <n> paths.\n" \
>  "  -O<file>      reorder diffs according to the <file>.\n" \
>  "  -S<string>    find filepair whose only one side contains the string.\n" \
> diff --git a/diffcore-rename.c b/diffcore-rename.c
> index 1b2ebb4..fc789bc 100644
> --- a/diffcore-rename.c
> +++ b/diffcore-rename.c
> @@ -52,6 +52,32 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
>        return &(rename_dst[first]);
>  }
>
> +static struct diff_rename_dst *locate_rename_dst_dir(struct diff_filespec *dir)
> +{
> +       /* code mostly duplicated from locate_rename_dst - not sure we
> +        * could merge them efficiently,though
> +        */
> +       int first, last;
> +       int dirlength = strlen(dir->path);
> +
> +       first = 0;
> +       last = rename_dst_nr;
> +       while (last > first) {
> +               int next = (last + first) >> 1;
> +               struct diff_rename_dst *dst = &(rename_dst[next]);
> +               int cmp = strncmp(dir->path, dst->two->path, dirlength);
> +               if (!cmp)
> +                       return dst;
> +               if (cmp < 0) {
> +                       last = next;
> +                       continue;
> +               }
> +               first = next+1;
> +       }
> +       /* not found */
> +       return NULL;
> +}
> +
>  /* Table of rename/copy src files */
>  static struct diff_rename_src {
>        struct diff_filespec *one;
> @@ -409,6 +435,165 @@ static void record_if_better(struct diff_score m[], struct diff_score *o)
>                m[worst] = *o;
>  }
>
> +struct diff_dir_rename {
> +       struct diff_filespec *one;
> +       struct diff_filespec *two;
> +       int discarded;
> +       struct diff_dir_rename* next;
> +};
> +
> +/*
> + * Marks as such file_rename if it is made uninteresting by dir_rename.
> + * Returns -1 if the file_rename is outside of the range in which given
> + * renames concerned by dir_rename are to be found (ie. end of loop),
> + * 0 otherwise.
> + */
> +static int maybe_mark_uninteresting(struct diff_rename_dst* file_rename,
> +                                   struct diff_dir_rename* dir_rename,
> +                                   int one_len, int two_len)
> +{
> +       if (!file_rename->pair) /* file add */
> +               return 0;
> +       if (strncmp(file_rename->two->path,
> +                   dir_rename->two->path, two_len))
> +               return -1;
> +       if (strncmp(file_rename->pair->one->path,
> +                   dir_rename->one->path, one_len) ||
> +           !basename_same(file_rename->pair->one, file_rename->two) ||
> +           file_rename->pair->score != MAX_SCORE)
> +               return 0;
> +
> +       file_rename->pair->uninteresting_rename = 1;
> +       fprintf (stderr, "[DBG] %s* -> %s* makes %s -> %s uninteresting\n",
> +               dir_rename->one->path, dir_rename->two->path,
> +               file_rename->pair->one->path, file_rename->two->path);
> +       return 0;
> +}
> +
> +// FIXME: prevent possible overflow
> +/*
> + * Copy dirname of src into dst, with final "/".
> + * Only handles relative paths since there is no relative path in a git repo.
> + * Writes "./" when there is no "/" in src.
> + * May overwrite more chars than really needed, if src ends with a "/".
> + */
> +static const char* copy_dirname(char* dst, const char* src)
> +{
> +       char* lastslash = strrchr(src, '/');
> +       if (!lastslash)
> +               return strcpy(dst, "./");
> +       strncpy(dst, src, lastslash - src + 1);
> +       dst[lastslash - src + 1] = '\0';
> +
> +       // if src ends with a "/" strip the last component
> +       if (lastslash[1] == '\0') {
> +               lastslash = strrchr(dst, '/');
> +               if (!lastslash)
> +                       return strcpy(dst, ".");
> +               lastslash[1] = '\0';
> +       }
> +
> +       return dst;
> +}
> +
> +/*
> + * FIXME: we could optimize the 100%-rename case by preventing
> + * recursion to unfold what we know we would refold here.
> + * FIXME: do we want to replace linked list with sorted array ?
> + * FIXME: this prototype only handles renaming of dirs without
> + * a subdir.
> + * FIXME: leaks like hell.
> + * FIXME: ideas to evaluate a similarity score, anyone ?
> + *  10% * tree similarity + 90% * moved files similarity ?
> + */
> +static struct diff_dir_rename* factorization_candidates = NULL;
> +static void diffcore_factorize_renames(void)
> +{
> +       char one_parent_path[PATH_MAX], two_parent_path[PATH_MAX];
> +       int i;
> +
> +       for (i = 0; i < rename_dst_nr; i++) {
> +               // FIXME: what are those ?
> +               if (!rename_dst[i].pair)
> +                       continue;
> +               // dummy renames used by copy detection
> +               if (!strcmp(rename_dst[i].pair->one->path, rename_dst[i].pair->two->path))
> +                       continue;
> +
> +               copy_dirname(one_parent_path, rename_dst[i].pair->one->path);
> +
> +               struct diff_filespec* one_parent = alloc_filespec(one_parent_path);
> +               fill_filespec(one_parent, null_sha1 /*FIXME*/, S_IFDIR);
> +
> +               if (!locate_rename_dst_dir(one_parent)) {
> +                       // one_parent_path is empty in result tree
> +
> +                       // already considered ?
> +                       struct diff_dir_rename* seen;
> +                       for (seen=factorization_candidates; seen; seen = seen->next)
> +                               if (!strcmp(seen->one->path, one_parent_path)) break;
> +                       if (!seen) {
> +                               // record potential dir rename
> +                               copy_dirname(two_parent_path, rename_dst[i].pair->two->path);
> +
> +                               seen = xmalloc(sizeof(*seen));
> +                               seen->one = one_parent;
> +                               seen->two = alloc_filespec(two_parent_path);
> +                               fill_filespec(seen->two, null_sha1 /*FIXME*/, S_IFDIR);
> +                               seen->discarded = 0;
> +                               seen->next = factorization_candidates;
> +                               factorization_candidates = seen;
> +                               fprintf (stderr, "[DBG] %s -> %s suggests possible rename from %s to %s\n",
> +                                      rename_dst[i].pair->one->path,
> +                                      rename_dst[i].pair->two->path,
> +                                      one_parent_path, two_parent_path);
> +                               fflush(stdout);
> +                               continue;
> +                       }
> +                       if (seen->discarded)
> +                               continue;
> +                       // check that seen entry matches this rename
> +                       copy_dirname(two_parent_path, rename_dst[i].pair->two->path);
> +                       if (strcmp(two_parent_path, seen->two->path)) {
> +                               fprintf (stderr, "[DBG] discarding dir split of %s from renames (into %s and %s)\n",
> +                                      one_parent_path, two_parent_path, seen->two->path);
> +                               seen->discarded = 1;
> +                       }
> +
> +                       /* all checks ok, we keep that entry */
> +               }
> +       }
> +
> +       // turn candidates into real renames
> +       struct diff_dir_rename* candidate;
> +       for (candidate=factorization_candidates; candidate; candidate = candidate->next) {
> +               int two_idx, i, one_len, two_len;
> +               if (candidate->discarded)
> +                       continue;
> +
> +               if (!locate_rename_dst_dir(candidate->two)) {
> +                       fprintf (stderr, "PANIC: %s candidate of rename not in target tree (from %s)\n",
> +                               candidate->two->path, candidate->one->path);
> +               }
> +               // bisect to an entry within candidate dst dir
> +               two_idx = locate_rename_dst_dir(candidate->two) - rename_dst;
> +
> +               // now remove extraneous 100% files inside.
> +               one_len = strlen(candidate->one->path);
> +               two_len = strlen(candidate->two->path);
> +               for (i = two_idx; i < rename_dst_nr; i++)
> +                       if (maybe_mark_uninteresting (rename_dst+i, candidate,
> +                                                     one_len, two_len) < 0)
> +                               break;
> +               for (i = two_idx-1; i >= 0; i--)
> +                       if (maybe_mark_uninteresting (rename_dst+i, candidate,
> +                                                     one_len, two_len) < 0)
> +                               break;
> +       }
> +
> +       return;
> +}
> +
>  void diffcore_rename(struct diff_options *options)
>  {
>        int detect_rename = options->detect_rename;
> @@ -446,13 +631,22 @@ void diffcore_rename(struct diff_options *options)
>                                p->one->rename_used++;
>                        register_rename_src(p->one, p->score);
>                }
> -               else if (detect_rename == DIFF_DETECT_COPY) {
> -                       /*
> -                        * Increment the "rename_used" score by
> -                        * one, to indicate ourselves as a user.
> -                        */
> -                       p->one->rename_used++;
> -                       register_rename_src(p->one, p->score);
> +               else {
> +                       if (detect_rename == DIFF_DETECT_COPY) {
> +                               /*
> +                                * Increment the "rename_used" score by
> +                                * one, to indicate ourselves as a user.
> +                                */
> +                               p->one->rename_used++;
> +                               register_rename_src(p->one, p->score);
> +                       }
> +                       if (DIFF_OPT_TST(options, FACTORIZE_RENAMES)) {
> +                               /* similarly, rename factorization needs to
> +                                * see all files from second tree
> +                                */
> +                               //p->two->rename_used++; // FIXME: would we need that ?
> +                               locate_rename_dst(p->two, 1);
> +                       }
>                }
>        }
>        if (rename_dst_nr == 0 || rename_src_nr == 0)
> @@ -561,8 +755,24 @@ void diffcore_rename(struct diff_options *options)
>        /* At this point, we have found some renames and copies and they
>         * are recorded in rename_dst.  The original list is still in *q.
>         */
> +
> +       /* Now possibly factorize those renames and copies. */
> +       if (DIFF_OPT_TST(options, FACTORIZE_RENAMES))
> +               diffcore_factorize_renames();
> +
>        outq.queue = NULL;
>        outq.nr = outq.alloc = 0;
> +
> +       // first, turn factorization_candidates into real renames
> +       struct diff_dir_rename* candidate;
> +       for (candidate=factorization_candidates; candidate; candidate = candidate->next) {
> +               struct diff_filepair* pair;
> +               if (candidate->discarded) continue;
> +               pair = diff_queue(&outq, candidate->one, candidate->two);
> +               pair->score = MAX_SCORE;
> +               pair->renamed_pair = 1;
> +       }
> +
>        for (i = 0; i < q->nr; i++) {
>                struct diff_filepair *p = q->queue[i];
>                struct diff_filepair *pair_to_free = NULL;
> @@ -577,7 +787,8 @@ void diffcore_rename(struct diff_options *options)
>                        struct diff_rename_dst *dst =
>                                locate_rename_dst(p->two, 0);
>                        if (dst && dst->pair) {
> -                               diff_q(&outq, dst->pair);
> +                               if (!dst->pair->uninteresting_rename)
> +                                       diff_q(&outq, dst->pair);
>                                pair_to_free = p;
>                        }
>                        else
> diff --git a/diffcore.h b/diffcore.h
> index 713cca7..6d2e65b 100644
> --- a/diffcore.h
> +++ b/diffcore.h
> @@ -66,6 +66,7 @@ struct diff_filepair {
>        unsigned broken_pair : 1;
>        unsigned renamed_pair : 1;
>        unsigned is_unmerged : 1;
> +       unsigned uninteresting_rename : 1;
>  };
>  #define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged)
>
> diff --git a/tree-diff.c b/tree-diff.c
> index 9f67af6..872f757 100644
> --- a/tree-diff.c
> +++ b/tree-diff.c
> @@ -49,7 +49,9 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
>                show_entry(opt, "+", t2, base, baselen);
>                return 1;
>        }
> -       if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) && !hashcmp(sha1, sha2) && mode1 == mode2)
> +       if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) &&
> +           !DIFF_OPT_TST(opt, FACTORIZE_RENAMES) &&
> +           !hashcmp(sha1, sha2) && mode1 == mode2)
>                return 0;
>
>        /*
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: multiple-commit cherry-pick?
From: Björn Steinbrink @ 2008-11-07 11:03 UTC (permalink / raw)
  To: Miles Bader; +Cc: Deskin Miller, git
In-Reply-To: <buozlkcqg0c.fsf@dhapc248.dev.necel.com>

On 2008.11.07 14:09:07 +0900, Miles Bader wrote:
> Björn Steinbrink <B.Steinbrink@gmx.de> writes:
> >> > git reset --hard C
> >> > git rebase --onto ORIG_HEAD A^
> >> 
> >> Is that safe...?  Doesn't git-rebase also set ORIG_HEAD?
> >
> > One of the first things rebase does is validating and resolving its
> > arguments. And that's happening before any actions that would touch
> > ORIG_HEAD.
> 
> Ah, I see.
> 
> Hmm, I guess using rebase --abort isn't a very good idea in this case
> though... :-/

Why not? I mean, ok, you end up at C, and not where you have been before
the reset --hard, but there's the reflog to help you get back to
whatever previous state of the branch it is that you want.

Björn

^ permalink raw reply

* Re: multiple-commit cherry-pick?
From: Michael Radziej @ 2008-11-07 10:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, Alex Riesen, Miles Bader, git
In-Reply-To: <7vskq4gmf5.fsf@gitster.siamese.dyndns.org>

On Thu, Nov 06, Junio C Hamano wrote:
> Or "git show --pretty=email $commit1 $commit2" ... piped to "am"?

Or make git show write shell commands.

I often have commits that later need to be cherry-picked into other
branches. For these, I use a commit message that starts with the name of the
branch, like "implement-foo: make foo barfy". Later when I want to do the
cherry-picking, I use this:

git log t/whatever..master --reverse --pretty=tformat:'git cherry-pick %h #
%s' | sed 's/^\([^:]*\) \([^:]*\):/git checkout \2 \&\& \1/'

giving me output like:

git checkout implement-foo && git cherry-pick 90ce727 # make foo barfy
git checkout ...

... and I'm ready for cut'n'paste.



Michael


-- 
noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg -
Tel +49-911-9352-0 - Fax +49-911-9352-100
http://www.noris.de - The IT-Outsourcing Company
 
Vorstand: Ingo Kraupa (Vorsitzender), Joachim Astel, Hansjochen Klenk - 
Vorsitzender des Aufsichtsrats: Stefan Schnabel - AG Nürnberg HRB 17689

^ permalink raw reply

* Re: [PATCH] Documentation: Mention that 'bisect' is reserved branch name
From: Abhijit Bhopatkar @ 2008-11-07 10:23 UTC (permalink / raw)
  To: Teemu Likonen; +Cc: git, Junio C Hamano
In-Reply-To: <87wsff269h.fsf@iki.fi>

>> "git bisect" uses 'bisect' branch to carry out it's operations.
>> However "git branch" documentation does mention it.
>> Add a note that 'bisect' can not be used as generic branch
>> name by the user.
> Hmm...
>    commit 634f246444e6a1675e351f31362e6a375dc44f70
>    Author: Christian Couder <chriscool@tuxfamily.org>
>    Date:   2008-05-23 01:28:57 +0200
>
>        bisect: use a detached HEAD to bisect
Cool, didn't know that ...

Submitted patch must be ignored
Thanks

Abhijit

^ permalink raw reply

* Re: [PATCH] Documentation: Mention that 'bisect' is reserved branch name
From: Teemu Likonen @ 2008-11-07 10:13 UTC (permalink / raw)
  To: Abhijit Bhopatkar; +Cc: git, Junio C Hamano
In-Reply-To: <2fcfa6df0811070201g75bfe659x38a4f14b1cf793c6@mail.gmail.com>

Abhijit Bhopatkar (2008-11-07 15:31 +0530) wrote:

> "git bisect" uses 'bisect' branch to carry out it's operations.
> However "git branch" documentation does mention it.
> Add a note that 'bisect' can not be used as generic branch
> name by the user.

Hmm...

    commit 634f246444e6a1675e351f31362e6a375dc44f70
    Author: Christian Couder <chriscool@tuxfamily.org>
    Date:   2008-05-23 01:28:57 +0200

        bisect: use a detached HEAD to bisect

^ permalink raw reply

* [PATCH] Documentation: Mention that 'bisect' is reserved branch name
From: Abhijit Bhopatkar @ 2008-11-07 10:01 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

"git bisect" uses 'bisect' branch to carry out it's operations.
However "git branch" documentation does mention it.
Add a note that 'bisect' can not be used as generic branch
name by the user.

Signed-off-by: Abhijit Bhopatkar <bain@devslashzero.com>

---
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 6103d62..2ea99fd 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -203,6 +203,9 @@ but different purposes:
 - `--no-merged` is used to find branches which are candidates for merging
   into HEAD, since those branches are not fully contained by HEAD.

+The branch name 'bisect' is reserved for use by "git-bisect" and can not be
+used as a generic branch name.
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org> and Junio C Hamano
<gitster@pobox.com>

^ permalink raw reply related

* [minor usability suggestion] git rebase <upstream> --onto <newbase> ?
From: Ingo Molnar @ 2008-11-07  9:20 UTC (permalink / raw)
  To: git


I use git rebase rarely, but i just had one of those exceptions where 
it's OK to use it: wanted to zap an unsafe commit [685aebb below] from 
a short-lifetime topic branch. With that i had this small usability 
incident:

 earth4:~/tip> tc
 tip/core/urgent 82d4e6e: xen: make sure stray alias mappings are gone

 earth4:~/tip> git rebase 685aebb --onto linus
 Current branch core/urgent is up to date.

 earth4:~/tip> glll
 82d4e6e: xen: make sure stray alias mappings are gone before pinning
 f6ab176: vmap: cope with vm_unmap_aliases before vmalloc_init()
 685aebb: kernel/cpu.c: section mismatch warning fix

 earth4:~/tip> git rebase --onto linus 685aebb
 First, rewinding head to replay your work on top of it...
 Applying: vmap: cope with vm_unmap_aliases before vmalloc_init()
 Applying: xen: make sure stray alias mappings are gone before pinning

 earth4:~/tip> glll
 d05fdf3: xen: make sure stray alias mappings are gone before pinning
 9b46333: vmap: cope with vm_unmap_aliases before vmalloc_init()

 earth4:~/tip> tc
 tip/core/urgent d05fdf3: xen: make sure stray alias mappings are gone 

 earth4:~/tip> git version
 git version 1.6.0.2.GIT

What i tried to achieve was to zap a single commit that was applied 
first, and preserve the other two commits - without having to go via 
the longer "git rebase -i" path.

It took me some time to figure out that while the principle i applied 
was correct, the first rebase command didnt work because i mistakenly 
flipped around the "--onto <newbase> <upstream>" arguments to 
"<upstream> --onto <newbase>".

Unless the reverse order is meaningful and important, it might make 
sense to flip it back implicitly and thus accept that order as well 
transparently.

For example "git log" is exemplary in this area as it accepts just 
about any permutation of parameters thrown at it, and i love that 
aspect of Git commands in general, it's a really nice property.

Or at least we should print some sort of warning/error? The "Current 
branch core/urgent is up to date." message definitely did not help me 
in noticing my mistake.

	Ingo

^ permalink raw reply

* git-push and $GIT_DIR/branches
From: Martin Koegler @ 2008-11-07  8:26 UTC (permalink / raw)
  To: git

I think, that the git-push behaviour is a bit unlogical in conjunction
with $GIT_DIR/branches.

If $GIT_DIR/branches/name1 contains "<repository>#name2":
- git-fetch name1
  will fetch refs/heads/name2 from <repository> and store it in refs/heads/name1
- git-push name1
  will push refs/heads/master to refs/heads/master in <repository>

I would expect, that git-push would somehow honour #name2. As far as I remember,
cg-push name1 would have pushed HEAD to refs/heads/name2 in <repository>.

In remote.c, function read_branches_file the following code
would implement a similar behaviour:
        strbuf_init(&push, 0);
        strbuf_addstr(&push, "HEAD");
        if (frag) {
                strbuf_addf(&push, ":refs/heads/%s", frag);
        } else
                strbuf_addstr(&push, ":refs/heads/master");
        add_push_refspec(remote, strbuf_detach(&push, 0));

Options about this?

mfg Martin Kögler

^ permalink raw reply

* Re: Issue updating files during a checkout from a remote push
From: Andreas Ericsson @ 2008-11-07  8:21 UTC (permalink / raw)
  To: Steve Walker; +Cc: git
In-Reply-To: <334B3AB1-125A-4163-BEBC-9A73C4F569B5@idibu.com>

Steve Walker wrote:
> Hi there,
> 
> Hoping someone could point me in the right direction here.
> 
> The overall issue is that with files that have been pushed into our repo 
> on our server, when we then check out into local working copy the new 
> files appear, but the updated files dont update even though the output 
> suggests it has. The flow I'm doing:
> 
> 1. The file I'm testing an update to is this:
> 
> -rw-r--r--   1 root    www-data       0 2008-11-06 16:13 
> steve-git-test3.txt
> 
> 2. On my local box I change file, add it, commit, then push it from my 
> local box to our server repo:
> 
> StevePoota:public_html steve$ vi steve-git-test3.txt
> StevePoota:public_html steve$ git add steve-git-test3.txt
> StevePoota:public_html steve$ git commit
> Created commit e29b724: testing only
>  1 files changed, 1 insertions(+), 0 deletions(-)
> StevePoota:public_html steve$ git push 
> ssh://idibu.com/home/beta_idibu/public_html master:master
> Counting objects: 5, done.
> Compressing objects: 100% (2/2), done.
> Writing objects: 100% (3/3), 272 bytes, done.
> Total 3 (delta 1), reused 0 (delta 0)
> To ssh://idibu.com/home/beta_idibu/public_html
>    a28332a..e29b724  master -> master
> 
> 3. It all looks good, on my server if i do a 'git log' I can see in the 
> latest update:
> 
> oneworld:/home/beta_idibu/public_html# git log
> commit e29b7246beab458d6a7b53cb245a5596adc8c198
> Author: Steve <steve@StevePoota.local>
> Date:   Thu Nov 6 17:55:21 2008 +0100
> 
>     testing only
> 
> 4. So I check out:
> 
> oneworld:/home/beta_idibu/public_html# git checkout master
> M    .gitignore
> M    steve-git-test.txt
> M    steve-git-test2.txt
> M    steve-git-test3.txt
> Already on branch "master"
> oneworld:/home/beta_idibu/public_html#
> 
> and its telling me that file has been modified
> 
> but checking my file it hasnt changed by date stamp, and looking insie 
> the file my changes arent there :((
> 
> -rw-r--r--   1 root    www-data       0 2008-11-06 16:13 
> steve-git-test3.txt
> 
> I'm stumped. I tried 777'ing that file temporarily in case git couldnt 
> write to that file on checkout. What is strange is that when I add new 
> files to the system it works - for example this file I'm testing no was 
> originally added to the server via an external push.
> 
> If anyone could give me some help I'd be very grateful.
> 

git reset --hard master

Note that it's definitely not a good idea to push into a non-bare repo
where you modify the worktree, as the workflow requires that you simply
clobber them (or work on a separate branch and then merge with master,
but then you'll have to know *why* things happen and how to fix them).

You'd probably be better off pushing to another repository and fetching
from that other repo into the non-bare one you're using now.

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

^ permalink raw reply

* Re: [PATCH 2/4] repack: don't repack local objects in packs with .keep file
From: Andreas Ericsson @ 2008-11-07  8:14 UTC (permalink / raw)
  To: Brandon Casey
  Cc: Junio C Hamano, Git Mailing List, Shawn O. Pearce, Nicolas Pitre
In-Reply-To: <P5afFyDEMjF9ynd9dfSfGeRo_GFY_K6ZAn2nIYo8_xGgSl4LapbSOA@cipher.nrlssc.navy.mil>

Brandon Casey wrote:
> If the user created a .keep file for a local pack, then it can be inferred
> that the user does not want those objects repacked.
> 

I disagree. It can be inferred that the user doesn't want those packfiles
*removed*.

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

^ permalink raw reply

* Re: [PATCH 1/4] pack-objects: new option --honor-pack-keep
From: Andreas Ericsson @ 2008-11-07  8:13 UTC (permalink / raw)
  To: Brandon Casey
  Cc: Junio C Hamano, Git Mailing List, Shawn O. Pearce, Nicolas Pitre
In-Reply-To: <oDevG_2ETMLvy6rfSqvxfmFqABeVqlDUcU6FjP07E5IzqLaopWkQbQ@cipher.nrlssc.navy.mil>

Brandon Casey wrote:
> This adds a new option to pack-objects which will cause it to ignore an
> object which appears in a local pack which has a .keep file, even if it
> was specified for packing.
> 
> This option will be used by the porcelain repack.
> 
> Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil>
> ---
> 
> 
> This series replaces the previous series starting at
> 6ee726bc "pack-objects: honor '.keep' files"
> 
> It should be applied on top of
> f34cf12d "packed_git: convert pack_local flag into a bitfield and add pack_keep"
> 
> I created the series on top of f34cf12d rebased on top of master.
> 
> Suggestions for a more appropriate name for --honor-pack-keep are very welcome.
> 
> -brandon
> 
> 
>  Documentation/git-pack-objects.txt |    5 +++++
>  builtin-pack-objects.c             |    7 +++++++
>  2 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
> index 8c354bd..f9fac2c 100644
> --- a/Documentation/git-pack-objects.txt
> +++ b/Documentation/git-pack-objects.txt
> @@ -109,6 +109,11 @@ base-name::
>  	The default is unlimited, unless the config variable
>  	`pack.packSizeLimit` is set.
>  
> +--honor-pack-keep::
> +	This flag causes an object already in a local pack that
> +	has a .keep file to be ignored, even if it appears in the
> +	standard input.
> +

Keep-files are *always* honored. Make this option "--ignore-kept" or
something instead, otherwise people will see the synopsis and think
they need to always pass it to not remove .keep-protected packs,
which is stupid.

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

^ permalink raw reply

* Re: [PATCH v2 3/3] pack-objects: honor '.keep' files
From: Andreas Ericsson @ 2008-11-07  8:12 UTC (permalink / raw)
  To: Brandon Casey
  Cc: Junio C Hamano, Git Mailing List, Shawn O. Pearce, Nicolas Pitre
In-Reply-To: <BgEXN35P6wpio928OZi_34hs22vqUQxIAIGxR5hR8LqmfPIyw565Mg@cipher.nrlssc.navy.mil>

Brandon Casey wrote:
> Junio C Hamano wrote:
>> Brandon Casey <casey@nrlssc.navy.mil> writes:
>>
>>>   <-a>
>>>     -create a new pack containing all objects required by the repository
>>>      including those accessible through alternates, but excluding objects
>>>      in _local_ packs with .keep
>> I have a feeling that it is debatable if this "fattening to dissociate
>> from alternates" is what people want.
> 
> I'm not sure I understand you here.
> 
> Andreas has suggested previously that 'repack -a' should pack everything,
> including objects in packs with .keep. Is that what you mean?
> 
> With my current understanding it seems that that would muddy the semantics
> of repack. If -a does not honor packs with .keep, then would it be intuitive
> to expect that adding -l (i.e. exclude alternate packed objects) _would_
> honor .keep?
> 

Only -d should honor .keep, imo. .keep-files is nothing about "don't copy
objects from this file" and all about "never delete this file".

The only muddying comes from you, who decided that .keep-files should
have impact on anything else than deleting the protected pack. Before that,
.keep files had a clear semantic, and repack's documentation was correct.

How do you explain .keep-files now? "protects pack-files that will forever
be used"? Then why the hell is it called ".keep" instead of "eternal"?

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

^ permalink raw reply

* Re: Setting Up a GIT Repository Mirror
From: Yaser Raja @ 2008-11-07  7:17 UTC (permalink / raw)
  To: Santi Béjar; +Cc: git
In-Reply-To: <adf1fd3d0811060733t28008f0cld1a3b3c5bf4ff4d8@mail.gmail.com>

On Thu, Nov 6, 2008 at 8:33 PM, Santi Béjar <santi@agolina.net> wrote:
> On Thu, Nov 6, 2008 at 4:08 PM, Yaser Raja <yrraja@gmail.com> wrote:
>> Hi
> [...]
>
>> I came to know about --mirror option of git-clone and used it to make
>> a bare repository replica of the MainRep. Now i am not sure how to
>> keep it in sync with the MainRep.
>
> $ git fetch
>
> as it is bare you cannot merge, so you cannot pull.
>
> HTH,
> Santi
>

Here is what i get when i try to use git-fetch:

# git fetch
ssh: : Name or service not known
fatal: The remote end hung up unexpectedly

Following is the current content of my config file:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true
[remote "origin"]
        url = ssh://gituser@<addr removed>
        fetch = +refs/*:refs/*
        mirror = yes

I also tried git-fetch with the url as argument but that also gave the
same error. Do i need to do some additional configurations to make
fetch work?

Thanks
Yaser

^ permalink raw reply

* Re: multiple-commit cherry-pick?
From: Alex Riesen @ 2008-11-07  7:13 UTC (permalink / raw)
  To: Miles Bader; +Cc: Linus Torvalds, git
In-Reply-To: <fc339e4a0811062038x22e7a3co503f09678f9ff5aa@mail.gmail.com>

Miles Bader, Fri, Nov 07, 2008 05:38:16 +0100:
> [git-am seems to have some similar features, but I don't know how well
> they work.]

They work well.

^ 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