Git development
 help / color / mirror / Atom feed
* Re: Bizarre missing changes (git bug?)
From: Roman Zippel @ 2008-07-30  0:16 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Linus Torvalds, Tim Harper, git
In-Reply-To: <46a038f90807282015m7ce3da10h71dfee221c960332@mail.gmail.com>

Hi,

On Tue, 29 Jul 2008, Martin Langhoff wrote:

> On Tue, Jul 29, 2008 at 2:59 PM, Roman Zippel <zippel@linux-m68k.org> wrote:
> > Can we please get past this and look at what is required to produce the
> > correct history?
> 
> Roman - correct is --full-history -- any simplification that makes it
> easy on your eyes *is* a simplification. And consumers that want to do
> nice user-friendly simplification like gitk does can hang off the data
> stream.

I don't quite understand what you're trying to say.
To avoid further confusion it maybe helps to specify a few of the terms:

- full history graph: produced by "git-log --full-history --parents"
- compact history graph: the full history graph without without any 
  repeated merges, this is what my example script produces.
- full simplified history: output of "git-log --full-history"
- short simplified history: standard output of "git-log"

The important part about the history graphs is that all commits are 
properly connected in it (i.e. all except the head commit have a child), 
This is needed to know if you don't just what want to know what happened, 
but also how it got merged, also any graphical interface needs it to 
produce a useful history graph.

What the short simplified history is more pure laziness, it's fast and 
gets the most common cases right, but in order to do this it has to ignore 
part of the history. The full simplified history at least produces 
produces the full change history, but it lacks part of the merge history 
and it stills takes longer to generate.

The point I'm trying to make is that the compact history graph has the 
potential to completely replace the simplified history. The only problem 
is that it needs a bit of cached extra information, then it can be as fast 
the short simplified history for the common case and it still can produce 
as much information as the full simplified history, thus you can still 
apply as much simplification as you want on top of it.

Keep in mind that e.g. git-web is using the full simplified history, so 
what I'm offering also has the potential to improve git-web performance...

> > it's also possible to update it when merging/pulling new data.
> 
> If that's what you want to do, you can prototype it with a hook on
> fetch and commit. That is definitely an area that hasn't been explored
> - what nicer (but expensive) views on the history we have can be
> afforded by pre-computing things on fetch and commit hooks.

I already did the prototype, I know how to generate that information, the 
problem is to get that information to the various graphical interfaces.

bye, Roman

^ permalink raw reply

* [PATCH] format-patch: Produce better output with --inline or --attach
From: Kevin Ballard @ 2008-07-29 23:49 UTC (permalink / raw)
  To: git; +Cc: Kevin Ballard, Junio C Hamano

This patch makes two small changes to improve the output of --inline and --attach.

The first is to write a newline preceding the boundary. This is needed because
MIME defines the encapsulation boundary as including the preceding CRLF (or in
this case, just LF), so we should be writing one. Without this, the last newline
in the pre-diff content is consumed instead.

The second change is to always write the line termination character (default: newline)
even when using --inline or --attach. This is simply to improve the aesthetics of
the resulting message. When using --inline an email client should render the
resulting message identically to the non-inline version. And when using --attach
this adds a blank line preceding the attachment in the email, which is visually
attractive.

Signed-off-by: Kevin Ballard <kevin@sb.org>
---
 diff.c                                             |    3 +--
 log-tree.c                                         |    2 +-
 ....format-patch_--attach_--stdout_initial..master |    6 ++++++
 ...format-patch_--attach_--stdout_initial..master^ |    4 ++++
 ...ff.format-patch_--attach_--stdout_initial..side |    2 ++
 ...tdout_--subject-prefix=TESTCASE_initial..master |    6 ++++++
 ....format-patch_--inline_--stdout_initial..master |    6 ++++++
 ...format-patch_--inline_--stdout_initial..master^ |    4 ++++
 ...ormat-patch_--inline_--stdout_initial..master^^ |    2 ++
 ...ff.format-patch_--inline_--stdout_initial..side |    2 ++
 10 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/diff.c b/diff.c
index a07812c..cbf2547 100644
--- a/diff.c
+++ b/diff.c
@@ -3223,11 +3223,10 @@ void diff_flush(struct diff_options *options)
 
 	if (output_format & DIFF_FORMAT_PATCH) {
 		if (separator) {
+			putc(options->line_termination, options->file);
 			if (options->stat_sep) {
 				/* attach patch instead of inline */
 				fputs(options->stat_sep, options->file);
-			} else {
-				putc(options->line_termination, options->file);
 			}
 		}
 
diff --git a/log-tree.c b/log-tree.c
index 5505606..bd8b9e4 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -198,7 +198,7 @@ void log_write_email_headers(struct rev_info *opt, const char *name,
 		extra_headers = subject_buffer;
 
 		snprintf(buffer, sizeof(buffer) - 1,
-			 "--%s%s\n"
+			 "\n--%s%s\n"
 			 "Content-Type: text/x-patch;"
 			 " name=\"%s.diff\"\n"
 			 "Content-Transfer-Encoding: 8bit\n"
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
index cf6891f..43346b9 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
@@ -19,6 +19,8 @@ This is the second commit.
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
@@ -122,6 +126,8 @@ Content-Transfer-Encoding: 8bit
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
index fe02587..d7490a9 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
@@ -19,6 +19,8 @@ This is the second commit.
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
index 9ff828e..38f7902 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
@@ -17,6 +17,8 @@ Content-Transfer-Encoding: 8bit
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
index a8093be..fca5cce 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
@@ -19,6 +19,8 @@ This is the second commit.
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
@@ -122,6 +126,8 @@ Content-Transfer-Encoding: 8bit
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
index aa110c0..6d6fac3 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
@@ -19,6 +19,8 @@ This is the second commit.
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
@@ -122,6 +126,8 @@ Content-Transfer-Encoding: 8bit
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
index 95e9ea4..18a1110 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
@@ -19,6 +19,8 @@ This is the second commit.
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
index b8e81e1..4f258b8 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
@@ -19,6 +19,8 @@ This is the second commit.
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
index 86ae923..e86dce6 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
@@ -17,6 +17,8 @@ Content-Transfer-Encoding: 8bit
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
-- 
1.6.0.rc1.166.gbbfa8.dirty

^ permalink raw reply related

* Re: What is 'git BRANCH'?
From: Eric Raible @ 2008-07-29 23:45 UTC (permalink / raw)
  To: git
In-Reply-To: <7v63qob9hz.fsf@gitster.siamese.dyndns.org>

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

> diff --git a/git.c b/git.c
> index 37b1d76..c99e769 100644
> --- a/git.c
> +++ b/git.c
> @@ -448,7 +448,7 @@ int main(int argc, const char **argv)
>  		cmd += 4;
>  		argv[0] = cmd;
>  		handle_internal_command(argc, argv);
> -		die("cannot handle %s internally", cmd);
> +		help_unknown_cmd(cmd);
>  	}

Which on windows leads to the less-than-friendly:

git BRANCH =>
git: 'BRANCH.exe' is not a git-command. See 'git --help'.

I wonder if it wouldn't be better to simply to a case-insensitive
comparison when comparing against the builtin array.  Alternatively,
at least the the extension (if any) ought to be stripped.

I'd be glad to come up with the patch for either given the word...

- Eric

^ permalink raw reply

* Re: [PATCH 3/4] Add a new test for using a custom merge strategy
From: Junio C Hamano @ 2008-07-29 23:43 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: git
In-Reply-To: <ee13073cd83ff4a3cffb926b21cc54583e67f869.1217372486.git.vmiklos@frugalware.org>

Miklos Vajna <vmiklos@frugalware.org> writes:

> +cat > git-merge-theirs << EOF
> +#!/bin/sh
> +eval git read-tree --reset -u \\\$\$#
> +EOF

This should be $SHELL_PATH, instead of hardcoded /bin/sh, to be easy on
people on Solaris and other systems.

Other than that, the patch is good and there is no need to resend it.
Thanks.

By the way, this eval shows why "theirs" cannot be a symmetric operation
of "ours".  You are taking the last remote HEAD even when you are merging
more than one remote into the current branch at once.  "ours" can be
sensibly defined for an octopus, but "theirs" has this "which theirs"
problem ;-)

^ permalink raw reply

* Re: [PATCH 4/4] Add a second testcase for handling invalid strategies in git-merge
From: Junio C Hamano @ 2008-07-29 23:42 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: git
In-Reply-To: <f8e5afe347c194013ffd104b196a19a37d762f9b.1217372486.git.vmiklos@frugalware.org>

Miklos Vajna <vmiklos@frugalware.org> writes:

> This one tests '-s index' which is interesting because git-merge-index
> is an existing git command but it is not a valid strategy.
>
> Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
> ---
>  t/t7600-merge.sh |    4 ++++
>  1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
> index 5eeb6c2..0329aee 100755
> --- a/t/t7600-merge.sh
> +++ b/t/t7600-merge.sh
> @@ -230,6 +230,10 @@ test_expect_success 'test option parsing' '
>  	test_must_fail git merge
>  '
>  
> +test_expect_success 'reject non-strategy with a git-merge-foo name' '
> +	test_must_fail git merge -s index c1
> +'
> +

True, but with the old code that might blindly have executed
git-merge-index the test would also have failed, and you would want to
tell two cases apart, wouldn't you?

^ permalink raw reply

* Re: [PATCH] Make it clear that push can take multiple refspecs
From: Junio C Hamano @ 2008-07-29 23:20 UTC (permalink / raw)
  To: Abhijit Menon-Sen; +Cc: git
In-Reply-To: <20080729231338.GA30717@toroid.org>

Abhijit Menon-Sen <ams@toroid.org> writes:

> At 2008-07-29 15:06:57 -0700, gitster@pobox.com wrote:
>>
>> If you saw the question asked many times in the real world, that
>> would be a good indication that this patch falls into the "helpful"
>> category, not "noise". Will queue.
>
> Thanks.
>
> You may find the appended patch less noisy still. I certainly like being
> able to get rid of the "any number of..." sentence; and I also think the
> example is clearer, though I merged it into an existing one.
> ...
> -<refspec>::
> -	The canonical format of a <refspec> parameter is
> +<refspec>...::
> +	The canonical format of each <refspec> parameter is
>  	`+?<src>:<dst>`; that is, an optional plus `+`, followed

After re-reading this, prompted by your comment about "both synopsis
syntax and regex in the same sentence, I actually do not see a problem
with the original one.  The synopsis talks about the ability for you to
specify zero or more of whatever is called <refspec>, and here we define
what _A_ refspec is.

Somehow I thought the issue was that we said "<refspec>...::" in the
heading of the description without saying zero-or-more, but that is not
the case here.

^ permalink raw reply

* [PATCH 1/4] builtin-help: make some internal functions available to other builtins
From: Miklos Vajna @ 2008-07-29 23:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <cover.1217372486.git.vmiklos@frugalware.org>

Make load_command_list() capable of filtering for a given prefix and
loading into a pair of "struct cmdnames" supplied by the caller.

Make the static add_cmdname(), exclude_cmds() and is_in_cmdlist()
functions non-static.

Make list_commands() accept a custom title, and work from a pair of
"struct cmdnames" supplied by the caller.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 Makefile |    1 +
 help.c   |   77 +++++++++++++++++++++++++++++++------------------------------
 help.h   |   23 ++++++++++++++++++
 3 files changed, 63 insertions(+), 38 deletions(-)
 create mode 100644 help.h

diff --git a/Makefile b/Makefile
index 52c67c1..83d79af 100644
--- a/Makefile
+++ b/Makefile
@@ -355,6 +355,7 @@ LIB_H += git-compat-util.h
 LIB_H += graph.h
 LIB_H += grep.h
 LIB_H += hash.h
+LIB_H += help.h
 LIB_H += list-objects.h
 LIB_H += ll-merge.h
 LIB_H += log-tree.h
diff --git a/help.c b/help.c
index 3cb1962..88c0d5b 100644
--- a/help.c
+++ b/help.c
@@ -9,6 +9,7 @@
 #include "common-cmds.h"
 #include "parse-options.h"
 #include "run-command.h"
+#include "help.h"
 
 static struct man_viewer_list {
 	struct man_viewer_list *next;
@@ -300,18 +301,11 @@ static inline void mput_char(char c, unsigned int num)
 		putchar(c);
 }
 
-static struct cmdnames {
-	int alloc;
-	int cnt;
-	struct cmdname {
-		size_t len;
-		char name[1];
-	} **names;
-} main_cmds, other_cmds;
+struct cmdnames main_cmds, other_cmds;
 
-static void add_cmdname(struct cmdnames *cmds, const char *name, int len)
+void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
-	struct cmdname *ent = xmalloc(sizeof(*ent) + len);
+	struct cmdname *ent = xmalloc(sizeof(*ent) + len + 1);
 
 	ent->len = len;
 	memcpy(ent->name, name, len);
@@ -342,7 +336,7 @@ static void uniq(struct cmdnames *cmds)
 	cmds->cnt = j;
 }
 
-static void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
+void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
 {
 	int ci, cj, ei;
 	int cmp;
@@ -418,11 +412,11 @@ static int is_executable(const char *name)
 }
 
 static unsigned int list_commands_in_dir(struct cmdnames *cmds,
-					 const char *path)
+					 const char *path,
+					 const char *prefix)
 {
 	unsigned int longest = 0;
-	const char *prefix = "git-";
-	int prefix_len = strlen(prefix);
+	int prefix_len;
 	DIR *dir = opendir(path);
 	struct dirent *de;
 	struct strbuf buf = STRBUF_INIT;
@@ -430,6 +424,9 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds,
 
 	if (!dir)
 		return 0;
+	if (!prefix)
+		prefix = "git-";
+	prefix_len = strlen(prefix);
 
 	strbuf_addf(&buf, "%s/", path);
 	len = buf.len;
@@ -460,7 +457,9 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds,
 	return longest;
 }
 
-static unsigned int load_command_list(void)
+unsigned int load_command_list(const char *prefix,
+		struct cmdnames *main_cmds,
+		struct cmdnames *other_cmds)
 {
 	unsigned int longest = 0;
 	unsigned int len;
@@ -469,7 +468,7 @@ static unsigned int load_command_list(void)
 	const char *exec_path = git_exec_path();
 
 	if (exec_path)
-		longest = list_commands_in_dir(&main_cmds, exec_path);
+		longest = list_commands_in_dir(main_cmds, exec_path, prefix);
 
 	if (!env_path) {
 		fprintf(stderr, "PATH not set\n");
@@ -481,7 +480,7 @@ static unsigned int load_command_list(void)
 		if ((colon = strchr(path, PATH_SEP)))
 			*colon = 0;
 
-		len = list_commands_in_dir(&other_cmds, path);
+		len = list_commands_in_dir(other_cmds, path, prefix);
 		if (len > longest)
 			longest = len;
 
@@ -491,36 +490,38 @@ static unsigned int load_command_list(void)
 	}
 	free(paths);
 
-	qsort(main_cmds.names, main_cmds.cnt,
-	      sizeof(*main_cmds.names), cmdname_compare);
-	uniq(&main_cmds);
+	qsort(main_cmds->names, main_cmds->cnt,
+	      sizeof(*main_cmds->names), cmdname_compare);
+	uniq(main_cmds);
 
-	qsort(other_cmds.names, other_cmds.cnt,
-	      sizeof(*other_cmds.names), cmdname_compare);
-	uniq(&other_cmds);
-	exclude_cmds(&other_cmds, &main_cmds);
+	qsort(other_cmds->names, other_cmds->cnt,
+	      sizeof(*other_cmds->names), cmdname_compare);
+	uniq(other_cmds);
+	exclude_cmds(other_cmds, main_cmds);
 
 	return longest;
 }
 
-static void list_commands(void)
+void list_commands(const char *title, unsigned int longest,
+		struct cmdnames *main_cmds, struct cmdnames *other_cmds)
 {
-	unsigned int longest = load_command_list();
 	const char *exec_path = git_exec_path();
 
-	if (main_cmds.cnt) {
-		printf("available git commands in '%s'\n", exec_path);
-		printf("----------------------------");
-		mput_char('-', strlen(exec_path));
+	if (main_cmds->cnt) {
+		printf("available %s in '%s'\n", title, exec_path);
+		printf("----------------");
+		mput_char('-', strlen(title) + strlen(exec_path));
 		putchar('\n');
-		pretty_print_string_list(&main_cmds, longest);
+		pretty_print_string_list(main_cmds, longest);
 		putchar('\n');
 	}
 
-	if (other_cmds.cnt) {
-		printf("git commands available from elsewhere on your $PATH\n");
-		printf("---------------------------------------------------\n");
-		pretty_print_string_list(&other_cmds, longest);
+	if (other_cmds->cnt) {
+		printf("%s available from elsewhere on your $PATH\n", title);
+		printf("---------------------------------------");
+		mput_char('-', strlen(title));
+		putchar('\n');
+		pretty_print_string_list(other_cmds, longest);
 		putchar('\n');
 	}
 }
@@ -542,7 +543,7 @@ void list_common_cmds_help(void)
 	}
 }
 
-static int is_in_cmdlist(struct cmdnames *c, const char *s)
+int is_in_cmdlist(struct cmdnames *c, const char *s)
 {
 	int i;
 	for (i = 0; i < c->cnt; i++)
@@ -553,7 +554,6 @@ static int is_in_cmdlist(struct cmdnames *c, const char *s)
 
 static int is_git_command(const char *s)
 {
-	load_command_list();
 	return is_in_cmdlist(&main_cmds, s) ||
 		is_in_cmdlist(&other_cmds, s);
 }
@@ -698,8 +698,9 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 			builtin_help_usage, 0);
 
 	if (show_all) {
+		unsigned int longest = load_command_list("git-", &main_cmds, &other_cmds);
 		printf("usage: %s\n\n", git_usage_string);
-		list_commands();
+		list_commands("git commands", longest, &main_cmds, &other_cmds);
 		printf("%s\n", git_more_info_string);
 		return 0;
 	}
diff --git a/help.h b/help.h
new file mode 100644
index 0000000..d614e54
--- /dev/null
+++ b/help.h
@@ -0,0 +1,23 @@
+#ifndef HELP_H
+#define HELP_H
+
+struct cmdnames {
+	int alloc;
+	int cnt;
+	struct cmdname {
+		size_t len;
+		char name[FLEX_ARRAY];
+	} **names;
+};
+
+unsigned int load_command_list(const char *prefix,
+		struct cmdnames *main_cmds,
+		struct cmdnames *other_cmds);
+void add_cmdname(struct cmdnames *cmds, const char *name, int len);
+/* Here we require that excludes is a sorted list. */
+void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
+int is_in_cmdlist(struct cmdnames *c, const char *s);
+void list_commands(const char *title, unsigned int longest,
+		struct cmdnames *main_cmds, struct cmdnames *other_cmds);
+
+#endif /* HELP_H */
-- 
1.6.0.rc0.14.g95f8.dirty

^ permalink raw reply related

* [PATCH 2/4] builtin-merge: allow using a custom strategy
From: Miklos Vajna @ 2008-07-29 23:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <cover.1217372486.git.vmiklos@frugalware.org>

Allow using a custom strategy, as long as it's named git-merge-foo. The
error handling is now done using is_git_command(). The list of available
strategies is now shown by list_commands().

If an invalid strategy is supplied, like -s foobar, then git-merge would
list all git-merge-* commands. This is not perfect, since for example
git-merge-index is not a valid strategy.

These are removed from the output by scanning the list of main commands;
if the git-merge-foo command is listed in the all_strategy list, then
it's shown, otherwise excluded. This does not exclude commands somewhere
else in the PATH, where custom strategies are expected.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 builtin-merge.c |   42 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/builtin-merge.c b/builtin-merge.c
index e78fa18..99b307a 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -22,6 +22,7 @@
 #include "log-tree.h"
 #include "color.h"
 #include "rerere.h"
+#include "help.h"
 
 #define DEFAULT_TWOHEAD (1<<0)
 #define DEFAULT_OCTOPUS (1<<1)
@@ -77,7 +78,9 @@ static int option_parse_message(const struct option *opt,
 static struct strategy *get_strategy(const char *name)
 {
 	int i;
-	struct strbuf err;
+	struct strategy *ret;
+	static struct cmdnames main_cmds, other_cmds;
+	static int longest = 0;
 
 	if (!name)
 		return NULL;
@@ -86,12 +89,37 @@ static struct strategy *get_strategy(const char *name)
 		if (!strcmp(name, all_strategy[i].name))
 			return &all_strategy[i];
 
-	strbuf_init(&err, 0);
-	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
-		strbuf_addf(&err, " %s", all_strategy[i].name);
-	fprintf(stderr, "Could not find merge strategy '%s'.\n", name);
-	fprintf(stderr, "Available strategies are:%s.\n", err.buf);
-	exit(1);
+	if (!longest) {
+		struct cmdnames not_strategies;
+
+		memset(&main_cmds, 0, sizeof(struct cmdnames));
+		memset(&other_cmds, 0, sizeof(struct cmdnames));
+		memset(&not_strategies, 0, sizeof(struct cmdnames));
+		longest = load_command_list("git-merge-", &main_cmds,
+				&other_cmds);
+		for (i = 0; i < main_cmds.cnt; i++) {
+			int j, found = 0;
+			struct cmdname *ent = main_cmds.names[i];
+			for (j = 0; j < ARRAY_SIZE(all_strategy); j++)
+				if (!strncmp(ent->name, all_strategy[j].name, ent->len)
+						&& !all_strategy[j].name[ent->len])
+					found = 1;
+			if (!found)
+				add_cmdname(&not_strategies, ent->name, ent->len);
+			exclude_cmds(&main_cmds, &not_strategies);
+		}
+	}
+	if (!is_in_cmdlist(&main_cmds, name) && !is_in_cmdlist(&other_cmds, name)) {
+
+		fprintf(stderr, "Could not find merge strategy '%s'.\n\n", name);
+		list_commands("strategies", longest, &main_cmds, &other_cmds);
+		exit(1);
+	}
+
+	ret = xmalloc(sizeof(struct strategy));
+	memset(ret, 0, sizeof(struct strategy));
+	ret->name = xstrdup(name);
+	return ret;
 }
 
 static void append_strategy(struct strategy *s)
-- 
1.6.0.rc0.14.g95f8.dirty

^ permalink raw reply related

* [PATCH 0/4] Allow custom merge strategies, take 4
From: Miklos Vajna @ 2008-07-29 23:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v4p68eame.fsf@gitster.siamese.dyndns.org>

On Tue, Jul 29, 2008 at 12:47:05PM -0700, Junio C Hamano <gitster@pobox.com> wrote:
> This feels overly wasteful.  Granted, this is not a performance critical
> codepath, but you list all commands that begin with "git-merge-" in
> is_git_command(), only to discard it and then iterate over 140+ main_cmds
> list only to cull the ones whose name do not appear in the strategies
> list.
>
> Perhaps this shows that changing the function is_git_command() is a wrong
> approach (for one thing, with the custom prefix, it is not about "Is it a
> git command" anymore).  Wouldn't it be easier to read if you did this part
> like this instead?
>
>  * make load_command_list capable of loading into a "struct cmdnames" (or
>    pair if you want) supplied by the caller;
>
>  * use it to grab all commands whose name begin with "git-merge-" here;
>
>  * Check if name appears in that list; if it doesn't, you already have the
>    list of commands that could be merge strategy for error reporting.
>
> If you also update list_commands() not to run load_command_list() itself
> but take caller-supplied list of commands, then the API would become much
> cleaner.  The caller would not be limited to "filter with prefix" anymore.
>
> Hmm?

I like the idea. ;-)

Here is what I did:

- I changed only load_command_list() and list_commands().
  load_command_list() still supports filtering, but the result is loaded
  to a pair of "struct cmdnames", supplied by the caller.

- list_commands() works from this pair, additionally supporting the
  custom title.

- export add_cmdname(), exclude_cmds() and is_in_cmdlist() without any
  modification in help.h

The rest is done in builtin-merge.c, as you suggested.

The nice thing is that before this change builtin-merge accepted for
example '-s index' (because git-merge-index was a valid command), but
now this is no longer true.

Miklos Vajna (4):
  builtin-help: make some internal functions available to other
    builtins
  builtin-merge: allow using a custom strategy
  Add a new test for using a custom merge strategy
  Add a second testcase for handling invalid strategies in git-merge

 Makefile                |    1 +
 builtin-merge.c         |   42 +++++++++++++++++++++----
 help.c                  |   77 ++++++++++++++++++++++++-----------------------
 help.h                  |   23 ++++++++++++++
 t/t7600-merge.sh        |    5 +++
 t/t7606-merge-custom.sh |   46 ++++++++++++++++++++++++++++
 6 files changed, 149 insertions(+), 45 deletions(-)
 create mode 100644 help.h
 create mode 100755 t/t7606-merge-custom.sh

^ permalink raw reply

* [PATCH 4/4] Add a second testcase for handling invalid strategies in git-merge
From: Miklos Vajna @ 2008-07-29 23:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <cover.1217372486.git.vmiklos@frugalware.org>

This one tests '-s index' which is interesting because git-merge-index
is an existing git command but it is not a valid strategy.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 t/t7600-merge.sh |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 5eeb6c2..0329aee 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -230,6 +230,10 @@ test_expect_success 'test option parsing' '
 	test_must_fail git merge
 '
 
+test_expect_success 'reject non-strategy with a git-merge-foo name' '
+	test_must_fail git merge -s index c1
+'
+
 test_expect_success 'merge c0 with c1' '
 	git reset --hard c0 &&
 	git merge c1 &&
-- 
1.6.0.rc0.14.g95f8.dirty

^ permalink raw reply related

* [PATCH 3/4] Add a new test for using a custom merge strategy
From: Miklos Vajna @ 2008-07-29 23:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <cover.1217372486.git.vmiklos@frugalware.org>

Testing is done by creating a simple git-merge-theirs strategy which is
the opposite of ours. Using this in real merges is not recommended but
it's perfect for our testing needs.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 t/t7606-merge-custom.sh |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 46 insertions(+), 0 deletions(-)
 create mode 100755 t/t7606-merge-custom.sh

diff --git a/t/t7606-merge-custom.sh b/t/t7606-merge-custom.sh
new file mode 100755
index 0000000..13e8ff5
--- /dev/null
+++ b/t/t7606-merge-custom.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='git-merge
+
+Testing a custom strategy.'
+
+. ./test-lib.sh
+
+cat > git-merge-theirs << EOF
+#!/bin/sh
+eval git read-tree --reset -u \\\$\$#
+EOF
+chmod +x git-merge-theirs
+PATH=.:$PATH
+export PATH
+
+test_expect_success 'setup' '
+	echo c0 > c0.c &&
+	git add c0.c &&
+	git commit -m c0 &&
+	git tag c0 &&
+	echo c1 > c1.c &&
+	git add c1.c &&
+	git commit -m c1 &&
+	git tag c1 &&
+	git reset --hard c0 &&
+	echo c2 > c2.c &&
+	git add c2.c &&
+	git commit -m c2 &&
+	git tag c2
+'
+
+test_expect_success 'merge c2 with a custom strategy' '
+	git reset --hard c1 &&
+	git merge -s theirs c2 &&
+	test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+	test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+	test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+	test "$(git rev-parse c2^{tree})" = "$(git rev-parse HEAD^{tree})" &&
+	git diff --exit-code &&
+	test -f c0.c &&
+	test ! -f c1.c &&
+	test -f c2.c
+'
+
+test_done
-- 
1.6.0.rc0.14.g95f8.dirty

^ permalink raw reply related

* Re: [PATCH] Make it clear that push can take multiple refspecs
From: Abhijit Menon-Sen @ 2008-07-29 23:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7viquobb0e.fsf@gitster.siamese.dyndns.org>

At 2008-07-29 15:06:57 -0700, gitster@pobox.com wrote:
>
> If you saw the question asked many times in the real world, that
> would be a good indication that this patch falls into the "helpful"
> category, not "noise". Will queue.

Thanks.

You may find the appended patch less noisy still. I certainly like being
able to get rid of the "any number of..." sentence; and I also think the
example is clearer, though I merged it into an existing one.

(I would also change the '+?<src>:<dst>' to '[+]<src>:<dst>'. It's a bit
weird to use BOTH regex format and SYNOPSIS format in the same string.)

> I wonder if there are other manual pages with <thing>... notation that
> benefits from similar changes, though.

Yes, I see now that there are several that could use minor changes.
Often nothing more than the following is needed:

-<committish>::
-       The object name of the committish.
+<committish>...::
+       A list of committish object names to describe.

(For git-describe, whose SYNOPSIS already mentions '<committish>...')

I'll submit another patch for those later.

-- ams

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 94d07ab..7f28ea6 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -10,7 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
-           [--repo=all] [-f | --force] [-v | --verbose] [<repository> <refspec>...]
+           [--repo=all] [-f | --force] [-v | --verbose]
+           [<repository> <refspec>...]
 
 DESCRIPTION
 -----------
@@ -29,8 +30,8 @@ OPTIONS
 	The "remote" repository that is destination of a push
 	operation.  See the section <<URLS,GIT URLS>> below.
 
-<refspec>::
-	The canonical format of a <refspec> parameter is
+<refspec>...::
+	The canonical format of each <refspec> parameter is
 	`+?<src>:<dst>`; that is, an optional plus `+`, followed
 	by the source ref, followed by a colon `:`, followed by
 	the destination ref.
@@ -180,11 +181,11 @@ git push origin :experimental::
 	Find a ref that matches `experimental` in the `origin` repository
 	(e.g. `refs/heads/experimental`), and delete it.
 
-git push origin master:satellite/master::
-	Find a ref that matches `master` in the source repository
-	(most likely, it would find `refs/heads/master`), and update
-	the ref that matches `satellite/master` (most likely, it would
-	be `refs/remotes/satellite/master`) in `origin` repository with it.
+git push origin master:satellite/master dev:satellite/dev::
+	Use the source ref that matches `master` (e.g. `refs/heads/master`)
+	to update the ref that matches `satellite/master` (most probably
+	`refs/remotes/satellite/master`) in the `origin` repository, then
+	do the same for `dev` and `satellite/dev`.
 
 git push origin master:refs/heads/experimental::
 	Create the branch `experimental` in the `origin` repository

^ permalink raw reply related

* git svn documentation
From: Jurko Gospodnetić @ 2008-07-29 22:45 UTC (permalink / raw)
  To: git

   Hi.

   git svn documentation should be updated so it no longer references 
the no longer supported 'git svnimport' command. Currently this causes 
an invalid link to be added to the git svn html documentation.

   Hope this helps.

   Best regards,
     Jurko Gospodnetić

^ permalink raw reply

* Re: What is 'git BRANCH'?
From: Sverre Rabbelier @ 2008-07-29 22:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jurko Gospodnetić, git
In-Reply-To: <7v63qob9hz.fsf@gitster.siamese.dyndns.org>

On Wed, Jul 30, 2008 at 00:39, Junio C Hamano <gitster@pobox.com> wrote:
> diff --git a/git.c b/git.c
> index 37b1d76..c99e769 100644
> --- a/git.c
> +++ b/git.c
> @@ -448,7 +448,7 @@ int main(int argc, const char **argv)
>                cmd += 4;
>                argv[0] = cmd;
>                handle_internal_command(argc, argv);
> -               die("cannot handle %s internally", cmd);
> +               help_unknown_cmd(cmd);
>        }
>
>        /* Look for flags.. */

Why does handle_internal_command not complain after the "	for (i = 0;
i < ARRAY_SIZE(commands); i++) {" that no matching commands were
found? Is that not an implicit assertion that would do well with being
asserted here?

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: Git Community Book
From: Junio C Hamano @ 2008-07-29 22:47 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: Scott Chacon, git list
In-Reply-To: <alpine.LNX.1.00.0807291716460.19665@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> In particular, I think it's really useful to show a commit graph with 
> branching and merging, and introduce refs as movable pointers to commits 
> in the graph, and local branches as refs that you move and tracking refs 
> as refs that copy values in other repositories.

I'd very strongly second this.  If somebody is really into screencasts
(and especially from the Ruby circle, I would guess), this may be worth
a look:

    http://excess.org/article/2008/07/ogre-git-tutorial/

I saw a couple of technical inaccuracies in the presentation (I do not
expect any presentation or screencast to be perfect; I've never seen one
without any technical error anyway, perhaps other than my own at OLS a few
years ago), but otherwise it was very well done.  Espcially the part that
builds the commit ancestry chains I was very happy to see it taught like
so.

^ permalink raw reply

* Re: What is 'git BRANCH'?
From: Jurko Gospodnetić @ 2008-07-29 22:43 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <DEBF93FC-BA8D-4513-B4EE-A8648DA1D591@sb.org>

   Hi all.

> On Jul 29, 2008, at 3:24 PM, Junio C Hamano wrote:
> 
>> Jurko Gospodnetić <jurko.gospodnetic@docte.hr> writes:
>>
>>>  Hi.
>>>
>>>  I typed in "git BRANCH" by accident and got the error message:
>>> "fatal: cannot handle BRANCH internally".
>>>
>>>  What does that mean?
>>>
>>>  It is different from the usual "git: 'yada-yada' is not a
>>> git-command. See 'git --help'." message you get when you type in an
>>> incorrect command name.
>>
>> Just a guess; your git is installed on a case-challenged filesystem?

   Thank you all for explaining this, and yes - this was detected on 
Windows with a NTFS drive set to case-insensitive.

   But, if something is running git-branch here... why does this 
script/executable/whatever try to check the name it got called with? Why 
does it not simply do its work no matter the name it got called with?

   If I'm asking something to obvious here - feel free to send me back 
to read the code... :-)

   Best regards,
     Jurko Gospodnetić

^ permalink raw reply

* Re: What is 'git BRANCH'?
From: Junio C Hamano @ 2008-07-29 22:39 UTC (permalink / raw)
  To: Jurko Gospodnetić; +Cc: git
In-Reply-To: <7vej5cba6z.fsf@gitster.siamese.dyndns.org>

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

> Jurko Gospodnetić <jurko.gospodnetic@docte.hr> writes:
>
>>   Hi.
>>
>>   I typed in "git BRANCH" by accident and got the error message:
>> "fatal: cannot handle BRANCH internally".
>>
>>   What does that mean?
>>
>>   It is different from the usual "git: 'yada-yada' is not a
>> git-command. See 'git --help'." message you get when you type in an
>> incorrect command name.
>
> Just a guess; your git is installed on a case-challenged filesystem?

Yeah, that must be it.  This can happen on MacOS and Windows, I would
imagine.

-- >8 --
[PATCH] Fail on unknown command sensibly on case-challenged filesystems

The callchain on a case-challenged filesystem when the user runs "git
BRANCH" looks like this:

  - main(): git BRANCH
   - execv_dashed_external("BRANCH")
    - execvp("git-BRANCH")

     - main(): git-BRANCH
      - prefixcmp("git-BRANCH", "git-")
       - handle_internal_command()
         struct cmd_struct commands[] does not have "BRANCH"
         so it returns, instead of exiting.

When the "git wrapper" execs "git-BRANCH", if your filesystem knows
"branch" and "BRANCH" are different, execvp() would fail and we will see
the familiar error message from the git.c::main().

However, if execvp() succeeds, we feed an unknown command name to
handle_internal_command() and it triggers a different error message.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 git.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git.c b/git.c
index 37b1d76..c99e769 100644
--- a/git.c
+++ b/git.c
@@ -448,7 +448,7 @@ int main(int argc, const char **argv)
 		cmd += 4;
 		argv[0] = cmd;
 		handle_internal_command(argc, argv);
-		die("cannot handle %s internally", cmd);
+		help_unknown_cmd(cmd);
 	}
 
 	/* Look for flags.. */

^ permalink raw reply related

* Re: Git Community Book
From: Daniel Barkalow @ 2008-07-29 22:34 UTC (permalink / raw)
  To: Scott Chacon; +Cc: git list
In-Reply-To: <d411cc4a0807290920p62f5d7e1r727a62ef2b4611fc@mail.gmail.com>

On Tue, 29 Jul 2008, Scott Chacon wrote:

> So I wanted to develop a really nice, easy to follow book for Git
> newcomers to learn git quickly and easily.  One of the issues I
> remember having when learning Git is that there is a lot of great
> material in the User Guide, Tutorial, Tutorial 2, Everyday Git, etc -
> but they're all huge long documents that are sometimes difficult to
> come back to and remember where you were, and I didn't know which one
> to start with or where to find what I was looking for, etc.

It would be good to include stuff from 
http://eagain.net/articles/git-for-computer-scientists/

Maybe only in inspiration, since it doesn't have an obvious license and 
it's stylisticly more technical. But it would be nice to have diagrams of 
"this is what git thinks of as history", possibly even arranging them like 
gitk shows things (older downward, refs pointing in from the side).

In particular, I think it's really useful to show a commit graph with 
branching and merging, and introduce refs as movable pointers to commits 
in the graph, and local branches as refs that you move and tracking refs 
as refs that copy values in other repositories.

I think you can even gloss of details of blobs and trees because they 
pretty much work just like files and directories in a filesystem (except 
that they take up much less storage in large quantities than you'd think). 
The only potentially interesting things are (1) a blob names the inode, 
not the dentry, so it's the file contents, not the name, mode, etc; and 
(2) the permission bits are just 'x', we've got symlinks, there are no 
owner/group or other attributes and "see also Submodules".

But I think that the section:
  http://eagain.net/articles/git-for-computer-scientists/#history
should have an equivalent in any git documentation that can have diagrams, 
and introducing a history diagram style early means that you can do a 
bunch of simple pictures to explain operations like "git checkout -b foo" 
or "git reset --hard HEAD^^" or "git checkout origin/master".

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: What is 'git BRANCH'?
From: Kevin Ballard @ 2008-07-29 22:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jurko Gospodnetić, git
In-Reply-To: <7vej5cba6z.fsf@gitster.siamese.dyndns.org>

On Jul 29, 2008, at 3:24 PM, Junio C Hamano wrote:

> Jurko Gospodnetić <jurko.gospodnetic@docte.hr> writes:
>
>>  Hi.
>>
>>  I typed in "git BRANCH" by accident and got the error message:
>> "fatal: cannot handle BRANCH internally".
>>
>>  What does that mean?
>>
>>  It is different from the usual "git: 'yada-yada' is not a
>> git-command. See 'git --help'." message you get when you type in an
>> incorrect command name.
>
> Just a guess; your git is installed on a case-challenged filesystem?

 From what I can tell, this happens when you execute one of the git-*  
builtin binaries using a name that doesn't actually match the binary,  
case-sensitively. When you type `git BRANCH` on OS X, git matches that  
against the git-branch binary and executes it, but argv[0] contains  
"git-BRANCH". When this is compared by the git-branch binary to the  
list of internal commands, it comes up empty, and the fallback code  
(to die with "fatal: cannot handle BRANCH internally") gets executed  
instead.

In other words, this is identical to running `/usr/local/libexec/git- 
core/git-BRANCH` or to doing something like `exec -a git-BRANCH /usr/ 
local/libexec/git-core/git-branch` (this example should work on any  
filesystem).

-Kevin Ballard

-- 
Kevin Ballard
http://kevin.sb.org
kevin@sb.org
http://www.tildesoft.com

^ permalink raw reply

* Re: short log and email address
From: René Scharfe @ 2008-07-29 22:30 UTC (permalink / raw)
  To: Jon Smirl; +Cc: Johannes Schindelin, Git Mailing List
In-Reply-To: <9e4733910807281157u44c08a59ld3bdc0416e8a1d03@mail.gmail.com>

Jon Smirl schrieb:
> On 7/28/08, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>> Hi,
>>
>>
>>  On Mon, 28 Jul 2008, Jon Smirl wrote:
>>
>>  > Using the -e option in shortlog changes the results by spitting things
>>  > out by email address instead of leaving them combined by name. That's
>>  > probably not what you want. Instead you want everything combined by name
>>  > and then display the most recent email address used.
>>
>>
>> What is so wrong with _not_ using -e (since you do not want to see the
>>  email address stored in the commit message, and -e would be asking for
>>  that _exactly_)?
> 
> I wanted -e to give me the most recent email so that I would know how
> to sort the mailmap alias list.

<snip>

> If the name isn't in mailmap, tell them to make a patch adding their
> name or to change their name.

That makes sense if you want to list all contributors in .mailmap...

> If the name is there but the email is not the last one in the list,
> tell them to make a patch rearranging mailmap to reflect their current
> name/email.

... but why would you want to check if they used their respective email
entry that is sorted last in the file?  A person might have multiple
current email addresses, e.g. someone could send patches for one
subsystem from work and patches for something else from home, as a hobby.

René

^ permalink raw reply

* Re: What is 'git BRANCH'?
From: Junio C Hamano @ 2008-07-29 22:24 UTC (permalink / raw)
  To: Jurko Gospodnetić; +Cc: git
In-Reply-To: <g6o4vi$rap$1@ger.gmane.org>

Jurko Gospodnetić <jurko.gospodnetic@docte.hr> writes:

>   Hi.
>
>   I typed in "git BRANCH" by accident and got the error message:
> "fatal: cannot handle BRANCH internally".
>
>   What does that mean?
>
>   It is different from the usual "git: 'yada-yada' is not a
> git-command. See 'git --help'." message you get when you type in an
> incorrect command name.

Just a guess; your git is installed on a case-challenged filesystem?

^ permalink raw reply

* What is 'git BRANCH'?
From: Jurko Gospodnetić @ 2008-07-29 22:18 UTC (permalink / raw)
  To: git

   Hi.

   I typed in "git BRANCH" by accident and got the error message: 
"fatal: cannot handle BRANCH internally".

   What does that mean?

   It is different from the usual "git: 'yada-yada' is not a 
git-command. See 'git --help'." message you get when you type in an 
incorrect command name.

   Just curious...

   Best regards,
     Jurko Gospodnetić

^ permalink raw reply

* [ANNOUNCE] GitStats development finished (WRT GSoC)
From: Sverre Rabbelier @ 2008-07-29 22:11 UTC (permalink / raw)
  To: Git Mailinglist
  Cc: Johannes Schindelin, Jakub Narebski, Junio C Hamano,
	David Symonds, Shawn O. Pearce, Sam Vilain

Heya,

I leave to the USA this Friday, and because of US tax laws I would
have to pay an insane amount of tax for just 2 weeks of development. I
have agreed with my mentor a while a go that I would finish up GSoC
before I left, that way avoiding having to pay US taxes. (Over here in
the Netherlands I don't have to pay tax over the $4500 because I
didn't make >6000 euro this year, the joys of being a student.) As a
result it is quite clear what GitStats will look like at the end of my
GSoC. I am going to continue working on it though, I am especially
interested in getting the '--follow' part of 'git log' working in such
a way that it can be incorporated into GitStats. As such, here is a
summary of what GitStat is at the moment. From the documentation:

$ cat gitstats-*
syntax: stats.py author <options>

The purpose of the author module is to gather statistics
about authors, and to aggregate this information to provide
information about all the authors of a repo.

Currently the available metrics in the author module are
the following:
* Determine how many changes an author made (making a
  distinction between lines added and lines deleted), and
  record this per author, for all files in the repository.
  It is possible to get this data for one specific author,
  (although data for all authors will still be gathered,)
  because the result is stored per author.

* Determine how many commits an author made that affected
  a specific file. This metric is less granular, but a lot
  faster. To retreive the more granular result, one could
  simply iterate over the result of the above metric for
  each author, and take only the data for the file one is
  interested in.

* Aggregate the information from the first metric, adding
  up the statistics from each author. This provides a more
  general 'file activity' metric and is a nice example of
  how an existing metric can be modified to do something
  seemingly unrelated.

This module does not define any auxillery functions.

syntax: stats.py branch <options>

The purpose of the branch module is to gather statistics
about branches, or related to branches.

Currently the available metrics in the branch module are
the following:
* Which of the branch head does a commit belong to
  What this metric does is walk down the ancestry of the
  target commit and increase the 'dilution' by one or each
  merge it finds. The exception applies that when following
  the 'primary' parent of the merge (e.g., the branch
  recorded as the one the merge commit was made on), the
  dilution is not increased. As such, if the target commit
  is made on a branch, and then later on it's dilution
  is calculated, it will have 0 dilution for that branch.
  The branch with the lowest dilution is deemed to be the
  branch that the commit belongs to most.
  Note: In git there is no 'main' branch, as such any and
  all branches branches that 'branched off' after the
  target commit will also have dilution 0.

It also defines the following auxillery functions:
* Retreive the name of a commit if it is a the head of a
  branch. This can be seen as the reverse of 'rev-parse'
  for branch heads. This is used internally to provide the
  user with a sensible name when telling them which branch
  a commit belongs to.

* List all the branches that contain a specific commit,
  optionally searching through remote branches as well as
  optionally not filtering at all. This is used internally
  to not search through branches that do not contain the
  target commit.

syntax: stats.py bug <options>

The purpose of the bug module is to gather statistics on
bugfixes within the content, and to aggregate this
information to provide with a report of the last N commits.

Currently the available metrics in the bug module are the
following:
* Determine whether a specific commit is a bugfix based on
  other metrics. When one of the metrics is 'positive',
  that is, it's return value indicates that the examined
  commit is a bugfix, the 'bugfix rating' is increased by
  a pre-configured amount. This amount can be specified per
  metric, and can be set to '0' to ignore it.

* Aggregate the above metric over the past N commits. Also,
  when running the above metric on more than one commit,
  cache the result of calls to the git binary so that the
  execution time is reduced. This means that the execution
  time is not directly proportional to the size of the
  repository. (Instead, there is a fixed 'start up' cost,
  after which there is a 'per commit' cost, which is
  relatively low.)

This module does not define any auxillery functions.

syntax: stats.py commit <options>

The purpose of the commit module is to gather statistics
about commits, or related to commits, with the exception
of things related to diffs (only retrieving the raw diff is
in this module).

Currently the available metrics in the author module are
the following:
* Find all the commits that touched the same paths as the
  specified commit. This is implemented by passing the
  result of the 'paths touched' auxillary function to the
  'commits that touched' auxillary function. See below.

* Retrieve the diff of a commit, either with or without
  context, and optionally ignoring whitespace changes. This
  method also works for the root commit (by making use of
  the '--root' option to 'diff tree'.

* Show only commits of which the commit message, and/or the
  commit diff, match a specific regexp.  This is a simple
  reimplementation of 'git log -S' and 'git log --grep'. It
  is preferable to instead use the options native to
  'git log', than to use this slower version.
  Note: the regexps for the 'commit message' and the
  'commit diff' may be different.

It also defines the following auxillary functions:
* Print a commit in a 'readable' way, this is by default
  'git log -1 --name-only'. By the way of an environmental
  variable ('GIT_STATS_PRETTY_PRINT'), it can be made to
  instead use 'git log -1 --prety=oneline' by setting the
  variable to 'online'.

* Retrieve all the paths that a specific commit touches,
  this is used internally to limit the commits that have
  to be searched when looking for a merge. That is done by
  passing the output of this method to the one described
  below.

* Find all commits that touched a list of files, optionally
  treating the paths as relative to the current working
  directory.

syntax: stats.py diff <options>

The purpose of the diff module is to gather statistics
about diffs, or related to diffs.

Currently the available metrics in the diff module are the
following:
* Determine whether two commit diffs are equal, optionally
  checking whether they are reverts instead. It is also
  possible to just look at what lines were changed (and
  ignore the actual changes).

* Find all commits that are reverted by the specified
  commit by first retrieving the touched files, and then
  examining all the commits that that touch the same files.

It also defines the following auxillery functions:
* Parse a raw commit diff and store it on a hunk-by-hunk
  basis so that later on it can be examined more carefully
  by other tools. Line numbers are optionally included so
  that one can use those. For example, by comparing all the
  added hunks with the deleted hunks of a second commit,
  and vise versa, one can check for (partial) reverts.

syntax: stats.py index <options>

The purpose of the index module is to gather statistics
about the index, or related to the index.

Currently the available metrics in the index module are the
following:
* List all the commits that touch the same files as the
  staged files. This can be useful to find out which commit
  introduced the bug fixed in this commit (by piping the
  output of this method to one that looks at which lines
  were touched for example).

It also defines the following auxillery functions:
* Get all the staged changes (optionally ignoring newly
  added files). This is used internally to find all the
  commits that touched the same files as those that are
  currently staged.

syntax: stats.py matcher <options>

The purpose of the matcher module is to compare hunks
within one diff to one another, and determine whether there
is any code being moved around.

Currently the available metrics in the index module are the
following:
* Try to find a match between the hunks in one diff, so
  that code moves can be detected. This makes use of the
  'diff size calculation' described below.

It also defines the following auxillery functions:
* Calculate the size of a diff, only counting the amount
  of lines added, and the amount of lines deleted. This can
  be used to determine a best 'interdiff' (the shortest one
  is the best one), when searching for two hunks that are
  moved around.

syntax: stats.py <subcommand> <arguments>

Available commands:
  author  Activity for one author, file, or project
  branch  In how far a commit belongs to a branch
  bug     Determine whether a commitis a bugfix
  commit  Basic functionality already present in git
  diff    Compare two diffs and find reverts
  index   Find which commits touched the staged files
  matcher Try to match hunks in a diff to find moves
  test    Run the unittests for GitStats

The stats.py module is the main entry point of GitStats,
it dispatches to the commands listed above. When no
arguments are passed, it automatically runs the command
with '--help' so that a usage message is shown for that
command.

Each of the modules it uses as subcommands defines a
'dispatch' function that is called with the users arguments
(with the exception of the first, which is the name of the
command executed). If anything should be returned to the
system, the dispatch method should return this value.

To run properly it requires the git_stats package to be
a subdirectory of the directory it resides in. That is,
your directory tree should be something like this:
.
|-- git_stats
|   `-- <listing of all installed modules>
|-- scripts
|   `-- <listing of all installed scripts>
|-- t
|   `-- <listing of all installed regression tests>
`-- stats.py

syntax: stats.py tests <options>

The purpose of the tests module is to make available the
unittests for GitStats to external programs. It may be
used to run the unittests for GitStats from for example
a shell script. It's output is made to match the git
regression test suite.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH] Make it clear that push can take multiple refspecs
From: Junio C Hamano @ 2008-07-29 22:06 UTC (permalink / raw)
  To: Abhijit Menon-Sen; +Cc: git
In-Reply-To: <20080729212808.GA27076@toroid.org>

Abhijit Menon-Sen <ams@toroid.org> writes:

> At 2008-07-29 13:54:35 -0700, gitster@pobox.com wrote:
>>
>> Doesn't this already say you can have zero or more refspecs?
>
> It does, of course, but I've seen more than one question about how to do
> it now, even from people who looked at the manpage, and it seemed to me
> that adding an example wouldn't hurt.

Adding an example would help to certain point, but beyond that certain
point it becomes unnecessary noise that talks the obvious.  If you saw the
question asked many times in the real world, that would be a good
indication that this patch falls into the "helpful" category, not "noise".
Will queue.

I wonder if there are other manual pages with <thing>... notation that
benefits from similar changes, though.

Thanks.

^ permalink raw reply

* Re: GIT 1.6.0-rc1
From: Junio C Hamano @ 2008-07-29 22:03 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git
In-Reply-To: <20080729211745.GA3879@blimp.local>

Alex Riesen <raa.lkml@gmail.com> writes:

> Junio C Hamano, Tue, Jul 29, 2008 10:36:19 +0200:
>> Junio C Hamano <gitster@pobox.com> writes:
>> >
>> > Ok, I took a deeper look at the codepaths involved.  Although it does work
>> > around the issue, I do not think your patch alone is the "correct" one in
>> > the longer term.
>
> Thought so. I just didn't know the code around
>
>> > It needs a bit of explanation, and the explanation won't be exactly
>> > "plain, small and short", unfortunately.
>> 
>> Alex, I ran the full test with this, but only on Linux boxes; obviously
>> not on any flavor of Windows.  I think it is correct, and the "first line
>> of defence" fix is the same as your patch, so I'd assume it would work for
>> you as well.  But extra eyeballs are always appreciated.
>
> Well, it works on Cygwin too. And I had my eyeballs on the code
> (wondered first if it will cause more fs accesses than before: it
> will, in the racy check. Which is correct, AFAICT)

I thought racy check won't even trigger for gitlinks, no?

ce_modified_check_fs() has 3 call sites:

 - the call site in ie_match_stat() is protected with is_racy_timestamp()
   that is always false for gitlinks;

 - the call site in ie_modified() we just took care of in the current
   thread;

 - the other call site is in ce_smudge_racily_clean_entry(), which is
   called from write_index() but it also is protected with
   is_racy_timestamp() that is always false for gitlinks.

 

^ 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