Git development
 help / color / mirror / Atom feed
* [PATCH 2/9] rev-list documentation: add "--bisect-all".
From: Christian Couder @ 2007-10-22  5:48 UTC (permalink / raw)
  To: Junio Hamano, Shawn O. Pearce, Johannes Schindelin; +Cc: git

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 Documentation/git-rev-list.txt |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 7cd0e89..4852804 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -34,6 +34,7 @@ SYNOPSIS
 	     [ \--pretty | \--header ]
 	     [ \--bisect ]
 	     [ \--bisect-vars ]
+	     [ \--bisect-all ]
 	     [ \--merge ]
 	     [ \--reverse ]
 	     [ \--walk-reflogs ]
@@ -354,6 +355,21 @@ the expected number of commits to be tested if `bisect_rev`
 turns out to be bad to `bisect_bad`, and the number of commits
 we are bisecting right now to `bisect_all`.
 
+--bisect-all::
+
+This outputs all the commit objects between the included and excluded
+commits, ordered by their distance to the included and excluded
+commits. The farthest from them is displayed first. (This is the only
+one displayed by `--bisect`.)
+
+This is useful because it makes it easy to choose a good commit to
+test when you want to avoid to test some of them for some reason (they
+may not compile for example).
+
+This option can be used along with `--bisect-vars`, in this case,
+after all the sorted commit objects, there will be the same text as if
+`--bisect-vars` had been used alone.
+
 --
 
 Commit Ordering
-- 
1.5.3.3.136.g591d1-dirty

^ permalink raw reply related

* [PATCH 1/9] rev-list: implement --bisect-all
From: Christian Couder @ 2007-10-22  5:47 UTC (permalink / raw)
  To: Junio Hamano, Shawn O. Pearce, Johannes Schindelin; +Cc: git

This is Junio's patch with some stuff to make --bisect-all
compatible with --bisect-vars.

This option makes it possible to see all the potential
bisection points. The best ones are displayed first.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-rev-list.c |  100 ++++++++++++++++++++++++++++++++++++++++++++-------
 log-tree.c         |    2 +-
 log-tree.h         |    1 +
 3 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 33726b8..4439332 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -9,6 +9,7 @@
 #include "revision.h"
 #include "list-objects.h"
 #include "builtin.h"
+#include "log-tree.h"
 
 /* bits #0-15 in revision.h */
 
@@ -38,7 +39,8 @@ static const char rev_list_usage[] =
 "    --left-right\n"
 "  special purpose:\n"
 "    --bisect\n"
-"    --bisect-vars"
+"    --bisect-vars\n"
+"    --bisect-all"
 ;
 
 static struct rev_info revs;
@@ -74,6 +76,7 @@ static void show_commit(struct commit *commit)
 			parents = parents->next;
 		}
 	}
+	show_decorations(commit);
 	if (revs.commit_format == CMIT_FMT_ONELINE)
 		putchar(' ');
 	else
@@ -278,6 +281,57 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)
 	return best;
 }
 
+struct commit_dist {
+	struct commit *commit;
+	int distance;
+};
+
+static int compare_commit_dist(const void *a_, const void *b_)
+{
+	struct commit_dist *a, *b;
+
+	a = (struct commit_dist *)a_;
+	b = (struct commit_dist *)b_;
+	if (a->distance != b->distance)
+		return b->distance - a->distance; /* desc sort */
+	return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
+}
+
+static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
+{
+	struct commit_list *p;
+	struct commit_dist *array = xcalloc(nr, sizeof(*array));
+	int cnt, i;
+
+	for (p = list, cnt = 0; p; p = p->next) {
+		int distance;
+		unsigned flags = p->item->object.flags;
+
+		if (revs.prune_fn && !(flags & TREECHANGE))
+			continue;
+		distance = weight(p);
+		if (nr - distance < distance)
+			distance = nr - distance;
+		array[cnt].commit = p->item;
+		array[cnt].distance = distance;
+		cnt++;
+	}
+	qsort(array, cnt, sizeof(*array), compare_commit_dist);
+	for (p = list, i = 0; i < cnt; i++) {
+		struct name_decoration *r = xmalloc(sizeof(*r) + 100);
+		struct object *obj = &(array[i].commit->object);
+
+		sprintf(r->name, "dist=%d", array[i].distance);
+		r->next = add_decoration(&name_decoration, obj, r);
+		p->item = array[i].commit;
+		p = p->next;
+	}
+	if (p)
+		p->next = NULL;
+	free(array);
+	return list;
+}
+
 /*
  * zero or positive weight is the number of interesting commits it can
  * reach, including itself.  Especially, weight = 0 means it does not
@@ -292,7 +346,8 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)
  * or positive distance.
  */
 static struct commit_list *do_find_bisection(struct commit_list *list,
-					     int nr, int *weights)
+					     int nr, int *weights,
+					     int find_all)
 {
 	int n, counted;
 	struct commit_list *p;
@@ -351,7 +406,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
 		clear_distance(list);
 
 		/* Does it happen to be at exactly half-way? */
-		if (halfway(p, nr))
+		if (!find_all && halfway(p, nr))
 			return p;
 		counted++;
 	}
@@ -389,19 +444,22 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
 				weight_set(p, weight(q));
 
 			/* Does it happen to be at exactly half-way? */
-			if (halfway(p, nr))
+			if (!find_all && halfway(p, nr))
 				return p;
 		}
 	}
 
 	show_list("bisection 2 counted all", counted, nr, list);
 
-	/* Then find the best one */
-	return best_bisection(list, nr);
+	if (!find_all)
+		return best_bisection(list, nr);
+	else
+		return best_bisection_sorted(list, nr);
 }
 
 static struct commit_list *find_bisection(struct commit_list *list,
-					  int *reaches, int *all)
+					  int *reaches, int *all,
+					  int find_all)
 {
 	int nr, on_list;
 	struct commit_list *p, *best, *next, *last;
@@ -434,14 +492,13 @@ static struct commit_list *find_bisection(struct commit_list *list,
 	weights = xcalloc(on_list, sizeof(*weights));
 
 	/* Do the real work of finding bisection commit. */
-	best = do_find_bisection(list, nr, weights);
-
+	best = do_find_bisection(list, nr, weights, find_all);
 	if (best) {
-		best->next = NULL;
+		if (!find_all)
+			best->next = NULL;
 		*reaches = weight(best);
 	}
 	free(weights);
-
 	return best;
 }
 
@@ -468,6 +525,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	int i;
 	int read_from_stdin = 0;
 	int bisect_show_vars = 0;
+	int bisect_find_all = 0;
 
 	git_config(git_default_config);
 	init_revisions(&revs, prefix);
@@ -490,6 +548,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			bisect_list = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--bisect-all")) {
+			bisect_list = 1;
+			bisect_find_all = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--bisect-vars")) {
 			bisect_list = 1;
 			bisect_show_vars = 1;
@@ -536,9 +599,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (bisect_list) {
 		int reaches = reaches, all = all;
 
-		revs.commits = find_bisection(revs.commits, &reaches, &all);
+		revs.commits = find_bisection(revs.commits, &reaches, &all,
+					      bisect_find_all);
 		if (bisect_show_vars) {
 			int cnt;
+			char hex[41];
 			if (!revs.commits)
 				return 1;
 			/*
@@ -550,15 +615,22 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			 * A bisect set of size N has (N-1) commits further
 			 * to test, as we already know one bad one.
 			 */
-			cnt = all-reaches;
+			cnt = all - reaches;
 			if (cnt < reaches)
 				cnt = reaches;
+			strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));
+
+			if (bisect_find_all) {
+				traverse_commit_list(&revs, show_commit, show_object);
+				printf("------\n");
+			}
+
 			printf("bisect_rev=%s\n"
 			       "bisect_nr=%d\n"
 			       "bisect_good=%d\n"
 			       "bisect_bad=%d\n"
 			       "bisect_all=%d\n",
-			       sha1_to_hex(revs.commits->item->object.sha1),
+			       hex,
 			       cnt - 1,
 			       all - reaches - 1,
 			       reaches - 1,
diff --git a/log-tree.c b/log-tree.c
index 62edd34..3763ce9 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -15,7 +15,7 @@ static void show_parents(struct commit *commit, int abbrev)
 	}
 }
 
-static void show_decorations(struct commit *commit)
+void show_decorations(struct commit *commit)
 {
 	const char *prefix;
 	struct name_decoration *decoration;
diff --git a/log-tree.h b/log-tree.h
index e82b56a..b33f7cd 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -12,5 +12,6 @@ int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
 int log_tree_opt_parse(struct rev_info *, const char **, int);
 void show_log(struct rev_info *opt, const char *sep);
+void show_decorations(struct commit *commit);
 
 #endif
-- 
1.5.3.3.136.g591d1-dirty

^ permalink raw reply related

* [PATCH 0/9] Bisect skip
From: Christian Couder @ 2007-10-22  5:47 UTC (permalink / raw)
  To: Junio Hamano, Shawn O. Pearce, Johannes Schindelin; +Cc: git

Hi all,

Here is the "bisect skip" patch series.
It's just a rename from "dunno" to "skip" compared to the previous "dunno" 
patch series that was in Shawn's pu branch.

In fact there is no change in the first 3 patches and trivial changes in the 
other patches.

Thanks,
Christian.

^ permalink raw reply

* Re: .gittattributes handling has deficiencies
From: Steffen Prohaska @ 2007-10-22  5:38 UTC (permalink / raw)
  To: david; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0710211703060.12998@asgard.lang.hm>


On Oct 22, 2007, at 2:05 AM, david@lang.hm wrote:

>
> by the way, I am not saying that my suggestion is the right way for  
> things to be (especially long term), but I'm trying to figure out a  
> work-around for the short term.

And I'm saying your proposed workaround is dangerous and doesn't
work reliably.

> I'm very interested to see the logn-term suggestions, becouse I  
> suspect that modt of them could be leveraged for the metastore jobs.

I'd prefer this, too.
	
	Steffen

^ permalink raw reply

* Re: [PATCH] "git help -a" should search all exec_paths and PATH
From: Shawn O. Pearce @ 2007-10-22  5:30 UTC (permalink / raw)
  To: Scott R Parish; +Cc: git
In-Reply-To: <20071021214846.GI16291@srparish.net>

Scott R Parish <srp@srparish.net> wrote:
> Currently "git help -a" only searches in the highest priority exec_path,
> meaning at worst, nothing is listed if the git commands are only available
> from the PATH. It also makes git slightly less extensible.
...
>  extern char **environ;
>  static const char *builtin_exec_path = GIT_EXEC_PATH;
> -static const char *current_exec_path;
> +static const char *argv_exec_path;
>  
> -void git_set_exec_path(const char *exec_path)
> +void git_set_argv_exec_path(const char *exec_path)
>  {
> -	current_exec_path = exec_path;
> +	argv_exec_path = exec_path;
>  }

I'd rather see a rename isolated from a logic change.  I find
it easier to review.
  
> +const char *git_argv_exec_path(void)
> +const char *git_builtin_exec_path(void)
> +const char *git_env_exec_path(void)

And yet later you then build the same priority array as already used
by execv_git_cmd().  Why not just make a function that builds the
array for the caller, so both execv_git_cmd() and list_commands()
can both use the same array?

> +static unsigned int list_commands_in_dir(const char *dir, const char *prefix)
>  {
> +	int start_dir = open(".", O_RDONLY, 0);
...
> +	if (!dirp || chdir(dir)) {
> +		fchdir(start_dir);

fchdir() isn't as portable as Git currently is.  Thus far we have
avoided using fchdir().  Requiring it here for something as "simple"
as listing help is not a good improvement as it will limit who can
run git-help.  Why can't you stat the individual entries by joining
the paths together?

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] git-cherry-pick: improve description of -x.
From: Ralf Wildenhues @ 2007-10-22  5:19 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Frank Lichtenheld, git
In-Reply-To: <20071022051453.GM14735@spearce.org>

* Shawn O. Pearce wrote on Mon, Oct 22, 2007 at 07:14:53AM CEST:
> 
> I think you are right that the current behavior of -x *not*
> including the prior commit SHA-1 in the case of a conflict is wrong.
> The problem however is that git-commit.sh doesn't get the data
> necessary to preseve the original author name/email/date/tz unless
> you use the "-c $id" option.

But the note added by -x is even missing when I add "-c $id" to
the git-commit command!  That's the point I was trying to make,
and really the only thing that seemed weird to me.

Cheers,
Ralf

^ permalink raw reply

* Re: [PATCH] git-cherry-pick: improve description of -x.
From: Shawn O. Pearce @ 2007-10-22  5:14 UTC (permalink / raw)
  To: Ralf Wildenhues; +Cc: Frank Lichtenheld, git
In-Reply-To: <20071021093618.GC12794@ins.uni-bonn.de>

Ralf Wildenhues <Ralf.Wildenhues@gmx.de> wrote:
> * Shawn O. Pearce wrote on Sat, Oct 20, 2007 at 05:19:17AM CEST:
> > Frank Lichtenheld <frank@lichtenheld.de> wrote:
> > > On Fri, Oct 19, 2007 at 07:41:34PM +0200, Ralf Wildenhues wrote:
> > > > 
> > > > Is that by design (because there were conflicts) or an omission?
> > > > In case of the former, maybe the description of -x should mention this.
> > > 
> > > git commit currently doesn't know that you commit a cherry-pick. The -c
> > > only says to use the commit message of the original commit. So this is
> > > currently by design.
> > 
> > Ralf, can you submit an updated version of this patch that describes
> > the current behavior better, given the "by design" remark above
> > from Frank?
> 
> Here it goes.  Still makes me wonder whether that is the ideal mode of
> operation or not.

Thanks.

I think you are right that the current behavior of -x *not*
including the prior commit SHA-1 in the case of a conflict is wrong.
The problem however is that git-commit.sh doesn't get the data
necessary to preseve the original author name/email/date/tz unless
you use the "-c $id" option.  There's some work here to store the
necessary information into a file that git-commit.sh could pickup,
and then making sure stale versions of those files get cleaned up
properly, etc.

At least the current behavior is now documented.  Maybe someone
will be bothered enough by it to try and submit a patch that changes
the behavior.
 
-- 
Shawn.

^ permalink raw reply

* Re: .gittattributes handling has deficiencies
From: Shawn O. Pearce @ 2007-10-22  5:01 UTC (permalink / raw)
  To: david; +Cc: Steffen Prohaska, git
In-Reply-To: <Pine.LNX.4.64.0710210204580.4818@asgard>

david@lang.hm wrote:
> On Sun, 21 Oct 2007, Steffen Prohaska wrote:
> >If a .gitattributes is in the work tree and we checkout a
> >different head, the .gitattributes of the head we are switching
> >to must have precedence.
> >
> >Maybe the gitattributes of a file should be part of the per-file
> >flags in the index. Thus we could verify if the flags changed and
> >if so, adjust the work tree accordig to the new flags.  I'm
> >lacking a deeper insight into the git internals.  Therefore, I
> >can't really say if the index is the right place.  But it looks
> >to me as if changing an attribute should be treated similar to a
> >changing sha1, as far as the work tree is concerned.
> 
> the problem with this is that each attribute ends up needing it's own 
> flag, which severely limits extending things (see the discussions on file 
> permissions for examples). it's also much harder to manipulate them then 
> in a file.

Yea, you really don't want to copy .gitattributes into the per-file
records in the index.  That's not going to scale as more types of
attributes are defined.

Fortunately the .gitattributes file format was designed to be
readable even when there's merge conflicts; that is it is a
very simple line-oriented record format.  One could difference
the old .gitattributes currently found in the index against the
.gitattributes we are switching to (from the target tree-ish),
scan the lines removed/added, find which files those match against
in the target tree-ish, and just add those files to the list of
things we need to checkout.

If any of those files is dirty then we just refuse the checkout,
just as if the file was modified and we were switching branches.
The user then needs to decide how to continue (probably stash the
file and then restart the checkout).

Rather simple IMHO.  Of course I haven't gone into that part of
read-tree recently, and the .gitattribute parser reads from the
working directory, so you need to make sure you checkout the target
.gitattributes file before anything else in the "to process list".

-- 
Shawn.

^ permalink raw reply

* Re: how to deal with conflicts after "git stash apply"?
From: Scott Parish @ 2007-10-22  4:39 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0710212338200.25221@racer.site>

> You should have a look into Documentation/diff-format.txt (section 
> "combined diff format") to learn more.

Ah, thanks for the pointer; i hadn't realized that this wasn't
standard diff format. With this and what Shawn said, it all makes
sense now.

sRp

-- 
Scott Parish
http://srparish.net/

^ permalink raw reply

* Re: how to deal with conflicts after "git stash apply"?
From: Shawn O. Pearce @ 2007-10-22  4:26 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Scott Parish, git
In-Reply-To: <Pine.LNX.4.64.0710212338200.25221@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> On Sun, 21 Oct 2007, Scott Parish wrote:
> 
> > How is the intended way to deal with "git stash apply" conflicts?
> > If i just edit the file and remove the conflict, "git diff" gives
> > some really messed up output. Documentation for other commands and
> > conflicts suggest "git commit" after cleaning up the conflict, or
> > "git add", but in the case of "stash apply" i'm not ready for a
> > commit yet, and "git add" keeps "git diff" from showing any output.
> 
> You are probably seeing combined diffs.
> 
> This show not only the differences of the working tree relative to HEAD, 
> but also of the changes stored in the stash.

The reason Scott is seeing a combined diff here is merge-recursive
left the different versions of the file in the higher order stages
of the index when it found conflicts during the apply.  You need
to use git-add to stage the resolved file and replace the higher
order stages with just the normal stage 0.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] execv_git_cmd(): also try PATH if everything else fails.
From: Shawn O. Pearce @ 2007-10-22  4:21 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Scott Parish, git
In-Reply-To: <Pine.LNX.4.64.0710212256270.25221@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Earlier, we tried to find the git commands in several possible exec
> dirs.  Now, if all of these failed, try to find the git command in
> PATH.
...
> diff --git a/exec_cmd.c b/exec_cmd.c
> index 9b74ed2..70b84b0 100644
> --- a/exec_cmd.c
> +++ b/exec_cmd.c
> @@ -36,7 +36,8 @@ int execv_git_cmd(const char **argv)
>  	int i;
>  	const char *paths[] = { current_exec_path,
>  				getenv(EXEC_PATH_ENVIRONMENT),
> -				builtin_exec_path };
> +				builtin_exec_path,
> +				"" };

So if the user sets GIT_EXEC_PATH="" and exports it we'll search
$PATH before the builtin exec path that Git was compiled with?
Are we sure we want to do that?

I'm going to throw this into pu tonight just so I don't lose it,
but I have a feeling we want to amend it before merging.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 2/2] Correct some sizeof(size_t) != sizeof(unsigned long)  typing errors
From: Shawn O. Pearce @ 2007-10-22  4:00 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: René Scharfe, git
In-Reply-To: <20071021103132.GA25741@artemis.corp>

Pierre Habouzit <madcoder@debian.org> wrote:
> On Sun, Oct 21, 2007 at 09:23:49AM +0000, René Scharfe wrote:
> > > Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
> > > ---
> > >  builtin-apply.c   |    2 +-
> > >  builtin-archive.c |    2 +-
> > >  diff.c            |    4 ++--
> > >  entry.c           |    2 +-
> > >  strbuf.h          |    8 +++++++-
> > >  test-delta.c      |    3 ++-
> > >  6 files changed, 14 insertions(+), 7 deletions(-)
> > 
> > I have a feeling this is going in then wrong direction.  Shouldn't
> > we rather use size_t everywhere?  malloc() takes a size_t, and it's
> > the basis of strbuf and also of the file content functions.
> 
>   I agree, Junio was working on a patch that generalized use of size_t's
> when unsigned long where used and size_t meant, I suppose he didn't had
> the time to push it.

Yea, you guys convinced me to go with René's patch.  I'm
replacing mine and will put it into next tonight.

I actually had started with what René wrote but changed it to
what you saw before posting it to the list.  :-)

-- 
Shawn.

^ permalink raw reply

* Re: On Tabs and Spaces
From: Miles Bader @ 2007-10-22  3:39 UTC (permalink / raw)
  To: Nikolai Weibull; +Cc: Petr Baudis, Jari Aalto, git
In-Reply-To: <dbfc82860710180439j6d02651foff9c0c84623a9cf1@mail.gmail.com>

"Nikolai Weibull" <now@bitwi.se> writes:
> To change the subject, let me point out that the percent symbol should
> be juxtaposed with the number, that is, write "99%", not "99 %", in
> English.

Hmm, but what if one uses a tab?

-miles

-- 
My books focus on timeless truths.  -- Donald Knuth

^ permalink raw reply

* [PATCH] gitweb: Provide title attributes for abbreviated author names.
From: David Symonds @ 2007-10-22  0:28 UTC (permalink / raw)
  To: pasky, spearce; +Cc: git, David Symonds

Signed-off-by: David Symonds <dsymonds@gmail.com>
---
 gitweb/gitweb.perl |   34 +++++++++++++++++++++++++++++-----
 1 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index b2bae1b..119ad55 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -3461,9 +3461,15 @@ sub git_shortlog_body {
 			print "<tr class=\"light\">\n";
 		}
 		$alternate ^= 1;
+		my $author = chop_str($co{'author_name'}, 10);
+		if ($author ne $co{'author_name'}) {
+			$author = "<span title=\"" . esc_html($co{'author_name'}) . "\">" . esc_html($author) . "</span>";
+		} else {
+			$author = esc_html($author);
+		}
 		# git_summary() used print "<td><i>$co{'age_string'}</i></td>\n" .
 		print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-		      "<td><i>" . esc_html(chop_str($co{'author_name'}, 10)) . "</i></td>\n" .
+		      "<td><i>" . $author . "</i></td>\n" .
 		      "<td>";
 		print format_subject_html($co{'title'}, $co{'title_short'},
 		                          href(action=>"commit", hash=>$commit), $ref);
@@ -3511,9 +3517,15 @@ sub git_history_body {
 			print "<tr class=\"light\">\n";
 		}
 		$alternate ^= 1;
+	# shortlog uses      chop_str($co{'author_name'}, 10)
+		my $author = chop_str($co{'author_name'}, 15, 3);
+		if ($author ne $co{'author_name'}) {
+			"<span title=\"" . esc_html($co{'author_name'}) . "\">" . esc_html($author) . "</span>";
+		} else {
+			$author = esc_html($author);
+		}
 		print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-		      # shortlog uses      chop_str($co{'author_name'}, 10)
-		      "<td><i>" . esc_html(chop_str($co{'author_name'}, 15, 3)) . "</i></td>\n" .
+		      "<td><i>" . $author . "</i></td>\n" .
 		      "<td>";
 		# originally git_history used chop_str($co{'title'}, 50)
 		print format_subject_html($co{'title'}, $co{'title_short'},
@@ -3667,8 +3679,14 @@ sub git_search_grep_body {
 			print "<tr class=\"light\">\n";
 		}
 		$alternate ^= 1;
+		my $author = chop_str($co{'author_name'}, 15, 5);
+		if ($author ne $co{'author_name'}) {
+			$author = "<span title=\"" . esc_html($co{'author_name'}) . "\">" . esc_html($author) . "</span>";
+		} else {
+			$author = esc_html($author);
+		}
 		print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-		      "<td><i>" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "</i></td>\n" .
+		      "<td><i>" . $author . "</i></td>\n" .
 		      "<td>" .
 		      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"},
 			       esc_html(chop_str($co{'title'}, 50)) . "<br/>");
@@ -5181,8 +5199,14 @@ sub git_search {
 						print "<tr class=\"light\">\n";
 					}
 					$alternate ^= 1;
+					my $author = chop_str($co{'author_name'}, 15, 5);
+					if ($author ne $co{'author_name'}) {
+						$author = "<span title=\"" . esc_html($co{'author_name'}) . "\">" . esc_html($author) . "</span>";
+					} else {
+						$author = esc_html($author);
+					}
 					print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-					      "<td><i>" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "</i></td>\n" .
+					      "<td><i>" . $author . "</i></td>\n" .
 					      "<td>" .
 					      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
 					              -class => "list subject"},
-- 
1.5.3.1

^ permalink raw reply related

* Re: [PATCH] "git help -a" should search all exec_paths and PATH
From: Scott Parish @ 2007-10-22  0:54 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0710212323580.25221@racer.site>

On Sun, Oct 21, 2007 at 11:25:29PM +0100, Johannes Schindelin wrote:

> > To fix this, help.c is modified to search in all the exec_paths and PATH
> > for potential git commands.
> 
> With this explanation, I would have expected that you add a loop just like 
> in exec-cmd.c.  Not anything more.  And certainly not the removal of a 
> sanity check for the length of the path name.

Well, i took a slightly different approach where that sanity check
wasn't nessisary. Instead of building up a string of the path of
each file, i'm saving the original directory in a file descriptor,
and "cd"ing to the exec_path currently being listed. Because of
that i can just stat() the names returned by readdir. Much simpler
imho

sRp

-- 
Scott Parish
http://srparish.net/

^ permalink raw reply

* Re: [PATCH, take 1] Linear-time/space rename logic (exact renames only)
From: David Symonds @ 2007-10-22  0:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Git Mailing List, Junio C Hamano, Shawn O. Pearce, David Kastrup,
	Jeff King
In-Reply-To: <alpine.LFD.0.999.0710211603200.10525@woody.linux-foundation.org>

On 22/10/2007, Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
> diff --git a/Makefile b/Makefile
> index 8db4dbe..17c31ba 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -291,7 +291,7 @@ LIB_H = \
>         run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
>         tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
>         utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
> -       mailmap.h remote.h
> +       mailmap.h remote.h hash.o

I assume that should be "hash.h", not "hash.o"?


Dave.

^ permalink raw reply

* Re: .gittattributes handling has deficiencies
From: david @ 2007-10-22  0:05 UTC (permalink / raw)
  To: Steffen Prohaska; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0710211645210.12998@asgard.lang.hm>

On Sun, 21 Oct 2007, david@lang.hm wrote:

>>>> 
>>>> What do you mean by "checking out everything"?
>>>> Which command do you propose?
>>> 
>>> something like git checkout -f
>> 
>> I suspected this. I see two problems:
>> 
>> 1) it's too dangerous: I throws away _all_ changes, not only
>> changes that are related to gitattributes.
>
> this is true, the question of if this is 'too dangerous' depends on what 
> workflow you teach as safe. if you teach that checking out a new version will 
> loose any modifications you have made (which is useually the sane thing to do 
> by default anyway) then this is just more of the same
>
>> 2) it doesn't work reliably. git checkout -f will only update
>> files that git detects as changed. But you could have files that
>> should have crlf in the working copy but actually have only lf.
>> Those would not be updated.
>
> ok, you could do rm -r * before doing the checkout -f (or there's probably a 
> option to git to tell it not to preserve changes to the working area, I am 
> not a git guru.
>
>> I'll not recommend this. Not using .gitattributes is the only
>> sane solution.
>
> it may be the best thing to do for you and your users, that's not the same 
> thing as saying that it's the only sane solution.

by the way, I am not saying that my suggestion is the right way for things 
to be (especially long term), but I'm trying to figure out a work-around 
for the short term.

I'm very interested to see the logn-term suggestions, becouse I suspect 
that modt of them could be leveraged for the metastore jobs.

David Lang

^ permalink raw reply

* [PATCH, take 1] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-21 23:59 UTC (permalink / raw)
  To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
  Cc: David Kastrup, Jeff King


This is a first effort at avoiding various O(n*m) effects in the rename 
detection. Right now it does so only for the exact renames, which is 
admittedly a rather easier case to handle, but having emailed a bit with 
Andy Chu, I think it's possible to do even the non-exact renames using a 
similar approach.

This depends on the previous diffcore-rename() cleanup, and introduces a 
new set of helpers for doing hash tables (hash.[ch]). We could probably 
move some of the other of our hash table users over to this (it's designed 
to be fairly generic), but that's a separate issue.

What it does is to rather than iterate over all sources and destinations 
and checking if they are identical (which is O(src*dst)), it hashes each 
of the sources and destinations into a hash table, using the SHA1 hash of 
the contents as the hash. That's O(n+m). It then walks the hash table 
(which is also O(m+n) in size), and only pairs up files for comparison 
that hashed to the same spot.

Doing this for more than just the exact same contents would be basically 
the same thing, except it starts hashing up fingerprints of the contents 
and linking up file pairs that get linked up by those fingerprints. More 
involved, but not impossible.

I tried a trivial case where I moved 100,000 files from one directory to 
another, and this patch speeds that up from ~13s to just under 2s for me.

However! Please note:
 - it looks ok, and I've tested it some, but this needs more people 
   looking at it.
 - because it only helps the exact rename case, it by no means "solves" 
   the rename cost issue. It just makes one particular case go much 
   faster.
 - in fact, the big optimization isn't the actual hash table, but the 
   independent and much simpler "diff_filespec->used" optimization for a 
   deleted filename that was used for a rename/copy.

But I'd like to have people give it a look,

		Linus

---

 Makefile          |    4 +-
 diffcore-rename.c |  214 ++++++++++++++++++++++++++++++++++------------------
 diffcore.h        |    1 +
 hash.c            |  110 +++++++++++++++++++++++++++
 hash.h            |   43 +++++++++++
 5 files changed, 296 insertions(+), 76 deletions(-)

diff --git a/Makefile b/Makefile
index 8db4dbe..17c31ba 100644
--- a/Makefile
+++ b/Makefile
@@ -291,7 +291,7 @@ LIB_H = \
 	run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
 	tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
 	utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
-	mailmap.h remote.h
+	mailmap.h remote.h hash.o
 
 DIFF_OBJS = \
 	diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -301,7 +301,7 @@ DIFF_OBJS = \
 LIB_OBJS = \
 	blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
 	date.o diff-delta.o entry.o exec_cmd.o ident.o \
-	interpolate.o \
+	interpolate.o hash.o \
 	lockfile.o \
 	patch-ids.o \
 	object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 2077a9b..05d39db 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -4,6 +4,7 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "hash.h"
 
 /* Table of rename/copy destinations */
 
@@ -96,29 +97,6 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one,
 	return &(rename_src[first]);
 }
 
-static int is_exact_match(struct diff_filespec *src,
-			  struct diff_filespec *dst,
-			  int contents_too)
-{
-	if (src->sha1_valid && dst->sha1_valid &&
-	    !hashcmp(src->sha1, dst->sha1))
-		return 1;
-	if (!contents_too)
-		return 0;
-	if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
-		return 0;
-	if (src->size != dst->size)
-		return 0;
-	if (src->sha1_valid && dst->sha1_valid)
-	    return !hashcmp(src->sha1, dst->sha1);
-	if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
-		return 0;
-	if (src->size == dst->size &&
-	    !memcmp(src->data, dst->data, src->size))
-		return 1;
-	return 0;
-}
-
 static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)
 {
 	int src_len = strlen(src->path), dst_len = strlen(dst->path);
@@ -216,6 +194,7 @@ static void record_rename_pair(int dst_index, int src_index, int score)
 		die("internal error: dst already matched.");
 
 	src = rename_src[src_index].one;
+	src->used = 1;
 	one = alloc_filespec(src->path);
 	fill_filespec(one, src->sha1, src->mode);
 
@@ -262,56 +241,152 @@ static int compute_stays(struct diff_queue_struct *q,
 	return 1;
 }
 
+struct file_similarity {
+	int src_dst, index;
+	struct diff_filespec *filespec;
+	struct file_similarity *next;
+};
+
+static int find_identical_files(struct file_similarity *src,
+				struct file_similarity *dst)
+{
+	int renames = 0;
+	do {
+		struct diff_filespec *one = src->filespec;
+		struct file_similarity *p, *best;
+		int i = 100;
+
+		best = NULL;
+		for (p = dst; p; p = p->next) {
+			struct diff_filespec *two = p->filespec;
+
+			/* Already picked as a destination? */
+			if (!p->src_dst)
+				continue;
+			/* False hash collission? */
+			if (hashcmp(one->sha1, two->sha1))
+				continue;
+			best = p;
+			if (basename_same(one, two))
+				break;
+
+			/* Too many identical alternatives? Pick one */
+			if (!--i)
+				break;
+		}
+		if (best) {
+			best->src_dst = 0;
+			record_rename_pair(best->index, src->index, MAX_SCORE);
+			renames++;
+		}
+	} while ((src = src->next) != NULL);
+	return renames;
+}
+
+static int find_same_files(void *ptr)
+{
+	struct file_similarity *p = ptr;
+	struct file_similarity *src = NULL, *dst = NULL;
+
+	/* Split the hash list up into sources and destinations */
+	do {
+		struct file_similarity *entry = p;
+		p = p->next;
+		if (entry->src_dst < 0) {
+			entry->next = src;
+			src = entry;
+		} else {
+			entry->next = dst;
+			dst = entry;
+		}
+	} while (p);
+
+	/*
+	 * If we have both sources *and* destinations, see if
+	 * we can match them up
+	 */
+	return (src && dst) ? find_identical_files(src, dst) : 0;
+}
+
+/*
+ * Note: the rest of the rename logic depends on this
+ * phase also populating all the filespecs for any
+ * entry that isn't matched up with an exact rename.
+ */
+static int free_file_table(void *ptr)
+{
+	struct file_similarity *p = ptr;
+	do {
+		struct file_similarity *entry = p;
+		p = p->next;
+
+		/* Stupid special case, see note above! */
+		diff_populate_filespec(entry->filespec, 0);
+		free(entry);
+	} while (p);
+	return 0;
+}
+
+static unsigned int hash_filespec(struct diff_filespec *filespec)
+{
+	unsigned int hash;
+	if (!filespec->sha1_valid) {
+		if (diff_populate_filespec(filespec, 0))
+			return 0;
+		hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1);
+	}
+	memcpy(&hash, filespec->sha1, sizeof(hash));
+	return hash;
+}
+
+static void insert_file_table(struct hash_table *table, int src_dst, int index, struct diff_filespec *filespec)
+{
+	void **pos;
+	unsigned int hash;
+	struct file_similarity *entry = xmalloc(sizeof(*entry));
+
+	entry->src_dst = src_dst;
+	entry->index = index;
+	entry->filespec = filespec;
+	entry->next = NULL;
+
+	hash = hash_filespec(filespec);
+	pos = insert_hash(hash, entry, table);
+
+	/* We already had an entry there? */
+	if (pos) {
+		entry->next = *pos;
+		*pos = entry;
+	}
+}
+
 /*
  * Find exact renames first.
  *
  * The first round matches up the up-to-date entries,
  * and then during the second round we try to match
  * cache-dirty entries as well.
- *
- * Note: the rest of the rename logic depends on this
- * phase also populating all the filespecs for any
- * entry that isn't matched up with an exact rename,
- * see "is_exact_match()".
  */
 static int find_exact_renames(void)
 {
-	int rename_count = 0;
-	int contents_too;
-
-	for (contents_too = 0; contents_too < 2; contents_too++) {
-		int i;
-
-		for (i = 0; i < rename_dst_nr; i++) {
-			struct diff_filespec *two = rename_dst[i].two;
-			int j;
-
-			if (rename_dst[i].pair)
-				continue; /* dealt with an earlier round */
-			for (j = 0; j < rename_src_nr; j++) {
-				int k;
-				struct diff_filespec *one = rename_src[j].one;
-				if (!is_exact_match(one, two, contents_too))
-					continue;
-
-				/* see if there is a basename match, too */
-				for (k = j; k < rename_src_nr; k++) {
-					one = rename_src[k].one;
-					if (basename_same(one, two) &&
-						is_exact_match(one, two,
-							contents_too)) {
-						j = k;
-						break;
-					}
-				}
-
-				record_rename_pair(i, j, (int)MAX_SCORE);
-				rename_count++;
-				break; /* we are done with this entry */
-			}
-		}
-	}
-	return rename_count;
+	int i;
+	struct hash_table file_table;
+
+	init_hash(&file_table);
+	for (i = 0; i < rename_src_nr; i++)
+		insert_file_table(&file_table, -1, i, rename_src[i].one);
+
+	for (i = 0; i < rename_dst_nr; i++)
+		insert_file_table(&file_table, 1, i, rename_dst[i].two);
+
+	/* Find the renames */
+	i = for_each_hash(&file_table, find_same_files);
+
+	/* .. and free the hash data structures */
+	for_each_hash(&file_table, free_file_table);
+	free_hash(&file_table);
+
+	return i;
 }
 
 void diffcore_rename(struct diff_options *options)
@@ -474,16 +549,7 @@ void diffcore_rename(struct diff_options *options)
 					pair_to_free = p;
 			}
 			else {
-				for (j = 0; j < rename_dst_nr; j++) {
-					if (!rename_dst[j].pair)
-						continue;
-					if (strcmp(rename_dst[j].pair->
-						   one->path,
-						   p->one->path))
-						continue;
-					break;
-				}
-				if (j < rename_dst_nr)
+				if (p->one->used)
 					/* this path remains */
 					pair_to_free = p;
 			}
diff --git a/diffcore.h b/diffcore.h
index eb618b1..a58d345 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -40,6 +40,7 @@ struct diff_filespec {
 	unsigned should_munmap : 1; /* data should be munmap()'ed */
 	unsigned checked_attr : 1;
 	unsigned is_binary : 1; /* data should be considered "binary" */
+	unsigned used : 1;	/* this pathspec was used for copy/delete */
 };
 
 extern struct diff_filespec *alloc_filespec(const char *);
diff --git a/hash.c b/hash.c
new file mode 100644
index 0000000..7b492d4
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,110 @@
+/*
+ * Some generic hashing helpers.
+ */
+#include "cache.h"
+#include "hash.h"
+
+/*
+ * Look up a hash entry in the hash table. Return the pointer to
+ * the existing entry, or the empty slot if none existed. The caller
+ * can then look at the (*ptr) to see whether it existed or not.
+ */
+static struct hash_table_entry *lookup_hash_entry(unsigned int hash, struct hash_table *table)
+{
+	unsigned int size = table->size, nr = hash % size;
+	struct hash_table_entry *array = table->array;
+
+	while (array[nr].ptr) {
+		if (array[nr].hash == hash)
+			break;
+		nr++;
+		if (nr >= size)
+			nr = 0;
+	}
+	return array + nr;
+}
+
+
+/*
+ * Insert a new hash entry pointer into the table.
+ *
+ * If that hash entry already existed, return the pointer to
+ * the existing entry (and the caller can create a list of the
+ * pointers or do anything else). If it didn't exist, return
+ * NULL (and the caller knows the pointer has been inserted).
+ */
+static void **insert_hash_entry(unsigned int hash, void *ptr, struct hash_table *table)
+{
+	struct hash_table_entry *entry = lookup_hash_entry(hash, table);
+
+	if (!entry->ptr) {
+		entry->ptr = ptr;
+		entry->hash = hash;
+		table->nr++;
+		return NULL;
+	}
+	return &entry->ptr;
+}
+
+static void grow_hash_table(struct hash_table *table)
+{
+	unsigned int i;
+	unsigned int old_size = table->size, new_size;
+	struct hash_table_entry *old_array = table->array, *new_array;
+
+	new_size = alloc_nr(old_size);
+	new_array = xcalloc(sizeof(struct hash_table_entry), new_size);
+	table->size = new_size;
+	table->array = new_array;
+	table->nr = 0;
+	for (i = 0; i < old_size; i++) {
+		unsigned int hash = old_array[i].hash;
+		void *ptr = old_array[i].ptr;
+		if (ptr)
+			insert_hash_entry(hash, ptr, table);
+	}
+	free(old_array);
+}
+
+void *lookup_hash(unsigned int hash, struct hash_table *table)
+{
+	if (!table->array)
+		return NULL;
+	return &lookup_hash_entry(hash, table)->ptr;
+}
+
+void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table)
+{
+	unsigned int nr = table->nr;
+	if (nr >= table->size/2)
+		grow_hash_table(table);
+	return insert_hash_entry(hash, ptr, table);
+}
+
+int for_each_hash(struct hash_table *table, int (*fn)(void *))
+{
+	int sum = 0;
+	unsigned int i;
+	unsigned int size = table->size;
+	struct hash_table_entry *array = table->array;
+
+	for (i = 0; i < size; i++) {
+		void *ptr = array->ptr;
+		array++;
+		if (ptr) {
+			int val = fn(ptr);
+			if (val < 0)
+				return val;
+			sum += val;
+		}
+	}
+	return sum;
+}
+
+void free_hash(struct hash_table *table)
+{
+	free(table->array);
+	table->array = NULL;
+	table->size = 0;
+	table->nr = 0;
+}
diff --git a/hash.h b/hash.h
new file mode 100644
index 0000000..5056c9a
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,43 @@
+#ifndef HASH_H
+#define HASH_H
+
+/*
+ * These are some simple generic hash table helper functions.
+ * Not necessarily suitable for all users, but good for things
+ * where you want to just keep track of a list of things, and
+ * have a good hash to use on them.
+ *
+ * It keeps the hash table at roughly 50-75% free, so the memory
+ * cost of the hash table itself is roughly
+ *
+ *	3 * 2*sizeof(void *) * nr_of_objects
+ *
+ * bytes. 
+ *
+ * FIXME: on 64-bit architectures, we waste memory. It would be
+ * good to have just 32-bit pointers, requiring a special allocator
+ * for hashed entries or something.
+ */
+struct hash_table_entry {
+	unsigned int hash;
+	void *ptr;
+};
+
+struct hash_table {
+	unsigned int size, nr;
+	struct hash_table_entry *array;
+};
+
+extern void *lookup_hash(unsigned int hash, struct hash_table *table);
+extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table);
+extern int for_each_hash(struct hash_table *table, int (*fn)(void *));
+extern void free_hash(struct hash_table *table);
+
+static inline void init_hash(struct hash_table *table)
+{
+	table->size = 0;
+	table->nr = 0;
+	table->array = NULL;
+}
+
+#endif

^ permalink raw reply related

* Re: .gittattributes handling has deficiencies
From: david @ 2007-10-21 23:49 UTC (permalink / raw)
  To: Steffen Prohaska; +Cc: git
In-Reply-To: <C7F59DFB-D4E4-4F75-88F7-F1A90C7D41E8@zib.de>

On Sun, 21 Oct 2007, Steffen Prohaska wrote:

> On Oct 21, 2007, at 7:57 PM, david@lang.hm wrote:
>
>> On Sun, 21 Oct 2007, Steffen Prohaska wrote:
>> 
>>> On Oct 21, 2007, at 7:09 PM, david@lang.hm wrote:
>>> 
>>>> On Sun, 21 Oct 2007, Steffen Prohaska wrote:
>>>>> On Oct 21, 2007, at 11:19 AM, david@lang.hm wrote:
>>>>>>> But this is really hard to solve. We would need to compare
>>>>>>> attributes before and after for _all_ files that have attributes
>>>>>>> in one of the two commits and check if they changed. If so, we
>>>>>>> need to do a fresh checkout according to the new attributes.
>>>>>> if you know that you will get the new .gitattributes if it changes, 
>>>>>> setup a post-checkout hook to checkout everything if it has changed. 
>>>>>> it's far from ideal, but it should be a good, safe, first 
>>>>>> approximation.
>>>>> That's not good enough. I'll stop using .gitattributes. I
>>>>> need to teach >40 devs how to use git on Windows. I only use
>>>>> features that work flawlessly. .gitattributes doesn't. It bit
>>>>> me twice now.
>>>> why would checking everything out if .gitattributes has changed not work? 
>>>> I can see why _not_ doing so would cause problems, and I freely 
>>>> acknowledge that this approach imposes a performance hit by checking 
>>>> everything out twice, but I don't see how it would not be reliable.
>>> 
>>> What do you mean by "checking out everything"?
>>> Which command do you propose?
>> 
>> something like git checkout -f
>
> I suspected this. I see two problems:
>
> 1) it's too dangerous: I throws away _all_ changes, not only
> changes that are related to gitattributes.

this is true, the question of if this is 'too dangerous' depends on what 
workflow you teach as safe. if you teach that checking out a new version 
will loose any modifications you have made (which is useually the sane 
thing to do by default anyway) then this is just more of the same

> 2) it doesn't work reliably. git checkout -f will only update
> files that git detects as changed. But you could have files that
> should have crlf in the working copy but actually have only lf.
> Those would not be updated.

ok, you could do rm -r * before doing the checkout -f (or there's probably 
a option to git to tell it not to preserve changes to the working area, I 
am not a git guru.

> I'll not recommend this. Not using .gitattributes is the only
> sane solution.

it may be the best thing to do for you and your users, that's not the same 
thing as saying that it's the only sane solution.

David Lang

^ permalink raw reply

* Re: how to deal with conflicts after "git stash apply"?
From: Johannes Schindelin @ 2007-10-21 22:40 UTC (permalink / raw)
  To: Scott Parish; +Cc: git
In-Reply-To: <20071021223206.GJ16291@srparish.net>

Hi,

On Sun, 21 Oct 2007, Scott Parish wrote:

> How is the intended way to deal with "git stash apply" conflicts?
> If i just edit the file and remove the conflict, "git diff" gives
> some really messed up output. Documentation for other commands and
> conflicts suggest "git commit" after cleaning up the conflict, or
> "git add", but in the case of "stash apply" i'm not ready for a
> commit yet, and "git add" keeps "git diff" from showing any output.

You are probably seeing combined diffs.

This show not only the differences of the working tree relative to HEAD, 
but also of the changes stored in the stash.

You should have a look into Documentation/diff-format.txt (section 
"combined diff format") to learn more.

Hth,
Dscho

^ permalink raw reply

* how to deal with conflicts after "git stash apply"?
From: Scott Parish @ 2007-10-21 22:32 UTC (permalink / raw)
  To: git

How is the intended way to deal with "git stash apply" conflicts?
If i just edit the file and remove the conflict, "git diff" gives
some really messed up output. Documentation for other commands and
conflicts suggest "git commit" after cleaning up the conflict, or
"git add", but in the case of "stash apply" i'm not ready for a
commit yet, and "git add" keeps "git diff" from showing any output.

Thanks for any clarification
sRp

-- 
Scott Parish
http://srparish.net/

^ permalink raw reply

* Re: [PATCH] "git help -a" should search all exec_paths and PATH
From: Johannes Schindelin @ 2007-10-21 22:25 UTC (permalink / raw)
  To: Scott R Parish; +Cc: git
In-Reply-To: <20071021214846.GI16291@srparish.net>

Hi,

On Sun, 21 Oct 2007, Scott R Parish wrote:

> Currently "git help -a" only searches in the highest priority exec_path, 
> meaning at worst, nothing is listed if the git commands are only 
> available from the PATH. It also makes git slightly less extensible.
> 
> To fix this, help.c is modified to search in all the exec_paths and PATH
> for potential git commands.

With this explanation, I would have expected that you add a loop just like 
in exec-cmd.c.  Not anything more.  And certainly not the removal of a 
sanity check for the length of the path name.

Ciao,
Dscho

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: Johannes Schindelin @ 2007-10-21 22:15 UTC (permalink / raw)
  To: Andreas Ericsson
  Cc: Jakub Narebski, Steffen Prohaska, Federico Mena Quintero, git
In-Reply-To: <471AFD07.4040606@op5.se>

Hi,

On Sun, 21 Oct 2007, Andreas Ericsson wrote:

> Johannes Schindelin wrote:
> 
> > On Sun, 21 Oct 2007, Jakub Narebski wrote:
> > 
> > > On 10/20/07, Steffen Prohaska <prohaska@zib.de> wrote:
> > > 
> > > > Maybe we could group commands into more categories?
> > > > 
> > > > plumbing: should be hidden from the 'normal' user. Porcelain
> > > >    should be sufficient for every standard task.
> > >
> > > The problem is division between what is porcelain and what is 
> > > plumbing. Some commands are right on border (git-fsck, 
> > > git-update-index, git-rev-parse comes to mind).
> > 
> > Sorry, but my impression from the latest mails was that the commands 
> > are fine.  What is lacking is a nice, _small_ collection of 
> > recommended workflows.  And when we have agreed on such a set of 
> > workflows, we optimize the hell out of them.  Only this time it is not 
> > performance, but user-friendliness.
> 
> http://www.kernel.org/pub/software/scm/git/docs/everyday.html would be a 
> good starting point, I think.

I don't think so.  Way too few authors were involved in writing this 
document, so it is not "typical" in and of itself.

I'd really like people to respond not so much with broad and general 
statements to my mail (those statements tend to be rather useless to find 
how to make git more suitable to newbies), but rather with concrete top 
ten lists of what they do daily.

My top ten list:

- git diff
- git commit
- git status
- git fetch
- git rebase
- git pull
- git cherry-pick
- git bisect
- git push
- git add

Of course, my list is somewhat skewed (because I am quite comfortable with 
the commands git provided; otherwise I would have provided -- unlike 
others, probably -- patches, and would have fought -- also unlike others 
-- to get them in, such as --color-words).

So again, I'd like people who did _not_ tweak git to their likings to tell 
the most common steps they do.  My hope is that we see things that are 
good practices, but could use an easier user interface.

Ciao,
Dscho

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: J. Bruce Fields @ 2007-10-21 22:12 UTC (permalink / raw)
  To: Steffen Prohaska
  Cc: Andreas Ericsson, Federico Mena Quintero, Johannes Schindelin,
	Jakub Narebski, git
In-Reply-To: <DE4FB702-24E8-421F-8447-04A5C7F7B5D2@zib.de>

On Sat, Oct 20, 2007 at 12:19:45PM +0200, Steffen Prohaska wrote:
> mail porcelain: the list will probably hate me for this, but
>   I think all commands needed to create and send patches per
>   mail are not essential. I suspect that I'll _never_ ask
>   my colleagues at work to send me a patch by mail. They'll
>   always push it to a shared repo.

That's not going to fly.  There are too many projects for which email is
the preferred way to submit patches (especially for new or occasional
developers).

--b.

^ permalink raw reply

* Re: [PATCH] Define compat version of mkdtemp for systems lacking it
From: Johannes Schindelin @ 2007-10-21 22:03 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20071021053015.GA31995@spearce.org>

Hi,

On Sun, 21 Oct 2007, Shawn O. Pearce wrote:

> Solaris 9 doesn't have mkdtemp() so we need to emulate it for the
> rsync transport implementation.

Thanks.  I've been meaning to do it for msysGit, but I never came around 
to do it...

Ciao,
Dscho

^ 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