Git development
 help / color / mirror / Atom feed
* Re: git submodules and commit
From: Nigel Magnay @ 2008-07-16 14:31 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Johannes Sixt, Git Mailing List
In-Reply-To: <20080716141738.GN32184@machine.or.cz>

> On Wed, Jul 16, 2008 at 03:03:41PM +0100, Nigel Magnay wrote:
>> - All the technical capability is there, it's just the porcelain
>> that's causing the friction.
>> then
>>  would this not seem to be an area that could be improved? Even if it
>> were an optional mode of working?
>
> So, were there already any patches posted to add such a functionality
> that were rejected? If not, apparently noone cared _enough_, yet. ;-)
> You may be the first!
>
> I don't know if there are any _present_ "free developers" willing to
> pick up this task now.  For many (most?) Git developers, submodules
> simply aren't a priority.  For me, they actually currently are, but I
> probably won't want to use them in your way either (even though I can
> agree that your sentiments are valid), so I will personally invest my
> time in doing other things than figuring out the precise semantics
> these operations should have etc.
>

That's cool. I was guessing it might be the case (or alternatively
that someone might say 'yeah, but it's 25% of the way there'); my
original query was also one of an offer of help ;-) My guess though is
that the core-devs have much more connected neural pathways at
thinking about the problems around the edge cases to be able to give
warnings of  'there be dragons'!


Nigel

^ permalink raw reply

* Re: [PATCH] Fix buffer overflow in git-grep
From: Dmitry Potapov @ 2008-07-16 14:33 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <20080716115420.GD2925@dpotapov.dyndns.org>

On Wed, Jul 16, 2008 at 3:54 PM, Dmitry Potapov <dpotapov@gmail.com> wrote:
>
> For instance, git show will show you nothing at all and exit with 0.
> The same problem with git whatchanged. The whole history mysteriously
> disappeared at that commit, and git whatchanged exited with 0 without
> any error or warning... Though git log will show you all history, but
> if you run it with -p then it will also exit with zero at this commit
> silently like previously history do not exist at all.

It turned out that git actually crashed while doing diff, but because it
was a forked process, the parent exited normally with code 0. I wonder
should not the parent process to exit with a non-zero code if the child
died by SIGSEG or another signal?

Dmitry

^ permalink raw reply

* Re: [PATCH] Fix buffer overflow in git-grep
From: Johannes Schindelin @ 2008-07-16 14:47 UTC (permalink / raw)
  To: Dmitry Potapov; +Cc: git
In-Reply-To: <37fcd2780807160733o156e49c6m51314ff18764ccd5@mail.gmail.com>

Hi,

On Wed, 16 Jul 2008, Dmitry Potapov wrote:

> On Wed, Jul 16, 2008 at 3:54 PM, Dmitry Potapov <dpotapov@gmail.com> wrote:
> >
> > For instance, git show will show you nothing at all and exit with 0.
> > The same problem with git whatchanged. The whole history mysteriously
> > disappeared at that commit, and git whatchanged exited with 0 without
> > any error or warning... Though git log will show you all history, but
> > if you run it with -p then it will also exit with zero at this commit
> > silently like previously history do not exist at all.
> 
> It turned out that git actually crashed while doing diff, but because it
> was a forked process, the parent exited normally with code 0. I wonder
> should not the parent process to exit with a non-zero code if the child
> died by SIGSEG or another signal?

We'll probably need to use the MinGW pager handling for Unix, too, and 
check for a died child.

Not overly trivial, though.

Ciao,
Dscho

^ permalink raw reply

* [PATCH] Fix buffer overflow in git diff
From: Dmitry Potapov @ 2008-07-16 14:54 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Dmitry Potapov
In-Reply-To: <37fcd2780807160733o156e49c6m51314ff18764ccd5@mail.gmail.com>

If PATH_MAX on your system is smaller than a path stored, it may cause
buffer overflow and stack corruption in diff_addremove() and diff_change()
functions when running git-diff

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
 diff-lib.c  |    8 ++++----
 diff.c      |   11 ++---------
 diff.h      |    9 ++++-----
 revision.c  |    4 ++--
 tree-diff.c |   26 ++++++++++++++++++++++----
 5 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/diff-lib.c b/diff-lib.c
index b17722d..e7eaff9 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 			if (silent_on_removed)
 				continue;
 			diff_addremove(&revs->diffopt, '-', ce->ce_mode,
-				       ce->sha1, ce->name, NULL);
+				       ce->sha1, ce->name);
 			continue;
 		}
 		changed = ce_match_stat(ce, &st, ce_option);
@@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 		newmode = ce_mode_from_stat(ce, st.st_mode);
 		diff_change(&revs->diffopt, oldmode, newmode,
 			    ce->sha1, (changed ? null_sha1 : ce->sha1),
-			    ce->name, NULL);
+			    ce->name);
 
 	}
 	diffcore_std(&revs->diffopt);
@@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs,
 				 const unsigned char *sha1, unsigned int mode)
 {
 	diff_addremove(&revs->diffopt, prefix[0], mode,
-		       sha1, ce->name, NULL);
+		       sha1, ce->name);
 }
 
 static int get_stat_data(struct cache_entry *ce,
@@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata,
 		return 0;
 
 	diff_change(&revs->diffopt, oldmode, mode,
-		    old->sha1, sha1, old->name, NULL);
+		    old->sha1, sha1, old->name);
 	return 0;
 }
 
diff --git a/diff.c b/diff.c
index 78c4d3a..386de82 100644
--- a/diff.c
+++ b/diff.c
@@ -3356,9 +3356,8 @@ int diff_result_code(struct diff_options *opt, int status)
 void diff_addremove(struct diff_options *options,
 		    int addremove, unsigned mode,
 		    const unsigned char *sha1,
-		    const char *base, const char *path)
+		    const char *concatpath)
 {
-	char concatpath[PATH_MAX];
 	struct diff_filespec *one, *two;
 
 	if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
@@ -3380,9 +3379,6 @@ void diff_addremove(struct diff_options *options,
 		addremove = (addremove == '+' ? '-' :
 			     addremove == '-' ? '+' : addremove);
 
-	if (!path) path = "";
-	sprintf(concatpath, "%s%s", base, path);
-
 	if (options->prefix &&
 	    strncmp(concatpath, options->prefix, options->prefix_length))
 		return;
@@ -3403,9 +3399,8 @@ void diff_change(struct diff_options *options,
 		 unsigned old_mode, unsigned new_mode,
 		 const unsigned char *old_sha1,
 		 const unsigned char *new_sha1,
-		 const char *base, const char *path)
+		 const char *concatpath)
 {
-	char concatpath[PATH_MAX];
 	struct diff_filespec *one, *two;
 
 	if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
@@ -3418,8 +3413,6 @@ void diff_change(struct diff_options *options,
 		tmp = old_mode; old_mode = new_mode; new_mode = tmp;
 		tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
 	}
-	if (!path) path = "";
-	sprintf(concatpath, "%s%s", base, path);
 
 	if (options->prefix &&
 	    strncmp(concatpath, options->prefix, options->prefix_length))
diff --git a/diff.h b/diff.h
index 5dc0cb5..50fb5dd 100644
--- a/diff.h
+++ b/diff.h
@@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options,
 		 unsigned old_mode, unsigned new_mode,
 		 const unsigned char *old_sha1,
 		 const unsigned char *new_sha1,
-		 const char *base, const char *path);
+		 const char *fullpath);
 
 typedef void (*add_remove_fn_t)(struct diff_options *options,
 		    int addremove, unsigned mode,
 		    const unsigned char *sha1,
-		    const char *base, const char *path);
+		    const char *fullpath);
 
 typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 		struct diff_options *options, void *data);
@@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *,
 			   int addremove,
 			   unsigned mode,
 			   const unsigned char *sha1,
-			   const char *base,
-			   const char *path);
+			   const char *fullpath);
 
 extern void diff_change(struct diff_options *,
 			unsigned mode1, unsigned mode2,
 			const unsigned char *sha1,
 			const unsigned char *sha2,
-			const char *base, const char *path);
+			const char *fullpath);
 
 extern void diff_unmerge(struct diff_options *,
 			 const char *path,
diff --git a/revision.c b/revision.c
index fc66755..8dc3ca7 100644
--- a/revision.c
+++ b/revision.c
@@ -259,7 +259,7 @@ static int tree_difference = REV_TREE_SAME;
 static void file_add_remove(struct diff_options *options,
 		    int addremove, unsigned mode,
 		    const unsigned char *sha1,
-		    const char *base, const char *path)
+		    const char *fullpath)
 {
 	int diff = REV_TREE_DIFFERENT;
 
@@ -285,7 +285,7 @@ static void file_change(struct diff_options *options,
 		 unsigned old_mode, unsigned new_mode,
 		 const unsigned char *old_sha1,
 		 const unsigned char *new_sha1,
-		 const char *base, const char *path)
+		 const char *fullpath)
 {
 	tree_difference = REV_TREE_DIFFERENT;
 	DIFF_OPT_SET(options, HAS_CHANGES);
diff --git a/tree-diff.c b/tree-diff.c
index e1e2e6c..4c67ea5 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa
 	return newbase;
 }
 
+static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen)
+{
+	char *fullname = xmalloc(baselen + pathlen + 1);
+	memcpy(fullname, base, baselen);
+	memcpy(fullname + baselen, path, pathlen);
+	fullname[baselen + pathlen] = 0;
+	return fullname;
+}
+
 static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
 		       const char *base, int baselen);
 
@@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
 	const char *path1, *path2;
 	const unsigned char *sha1, *sha2;
 	int cmp, pathlen1, pathlen2;
+	char *fullname;
 
 	sha1 = tree_entry_extract(t1, &path1, &mode1);
 	sha2 = tree_entry_extract(t2, &path2, &mode2);
@@ -56,14 +66,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
 		int retval;
 		char *newbase = malloc_base(base, baselen, path1, pathlen1);
 		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
+		{
+			newbase[baselen + pathlen1] = 0;
 			opt->change(opt, mode1, mode2,
-				    sha1, sha2, base, path1);
+				    sha1, sha2, newbase);
+			newbase[baselen + pathlen1] = '/';
+		}
 		retval = diff_tree_sha1(sha1, sha2, newbase, opt);
 		free(newbase);
 		return retval;
 	}
 
-	opt->change(opt, mode1, mode2, sha1, sha2, base, path1);
+	fullname = malloc_fullname(base, baselen, path1, pathlen1);
+	opt->change(opt, mode1, mode2, sha1, sha2, fullname);
+	free(fullname);
 	return 0;
 }
 
@@ -205,10 +221,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
 	unsigned mode;
 	const char *path;
 	const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);
+	int pathlen = tree_entry_len(path, sha1);
 
 	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) {
 		enum object_type type;
-		int pathlen = tree_entry_len(path, sha1);
 		char *newbase = malloc_base(base, baselen, path, pathlen);
 		struct tree_desc inner;
 		void *tree;
@@ -224,7 +240,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
 		free(tree);
 		free(newbase);
 	} else {
-		opt->add_remove(opt, prefix[0], mode, sha1, base, path);
+		char *fullname = malloc_fullname(base, baselen, path, pathlen);
+		opt->add_remove(opt, prefix[0], mode, sha1, fullname);
+		free(fullname);
 	}
 }
 
-- 
1.5.6.3.3.gfcafb

^ permalink raw reply related

* [PATCH] Fix buffer overflow in prepare_attr_stack
From: Dmitry Potapov @ 2008-07-16 14:54 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Dmitry Potapov
In-Reply-To: <1216220043-27678-1-git-send-email-dpotapov@gmail.com>

If PATH_MAX on your system is smaller than a path stored in the git repo,
it may cause the buffer overflow in prepare_attr_stack.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
 attr.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/attr.c b/attr.c
index 0fb47d3..73b6d6d 100644
--- a/attr.c
+++ b/attr.c
@@ -459,7 +459,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
 {
 	struct attr_stack *elem, *info;
 	int len;
-	char pathbuf[PATH_MAX];
+	struct strbuf pathbuf;
+
+	strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
 
 	/*
 	 * At the bottom of the attribute stack is the built-in
@@ -510,13 +512,14 @@ static void prepare_attr_stack(const char *path, int dirlen)
 			len = strlen(attr_stack->origin);
 			if (dirlen <= len)
 				break;
-			memcpy(pathbuf, path, dirlen);
-			memcpy(pathbuf + dirlen, "/", 2);
-			cp = strchr(pathbuf + len + 1, '/');
+			pathbuf.len = 0;
+			strbuf_add(&pathbuf, path, dirlen);
+			strbuf_addch(&pathbuf, '/');
+			cp = strchr(pathbuf.buf + len + 1, '/');
 			strcpy(cp + 1, GITATTRIBUTES_FILE);
-			elem = read_attr(pathbuf, 0);
+			elem = read_attr(pathbuf.buf, 0);
 			*cp = '\0';
-			elem->origin = strdup(pathbuf);
+			elem->origin = strdup(pathbuf.buf);
 			elem->prev = attr_stack;
 			attr_stack = elem;
 			debug_push(elem);
-- 
1.5.6.3.3.gfcafb

^ permalink raw reply related

* Re: MSysGit Stability
From: Pascal Obry @ 2008-07-16 14:59 UTC (permalink / raw)
  To: Joe Fiorini; +Cc: git
In-Reply-To: <73fd69b50807151458u22a383a3l343779e47f4161fa@mail.gmail.com>

Joe,

> I'm going to be working with a small dev shop in the near future and
> we would like to use Git for our project.  Two of us are on Macs, but
> the other is on Windows.  I know the options are MSysGit or Git
> through cygwin.  I'm curious which is better to use and if MSysGit is
> even stable yet.  Does anyone have experience running Git on Windows?

Yes, all the time on some quite large projects and since a year now. No 
problem, quite stable. I'm using Git on Cygwin that I build myself 
almost every day. I'm also working with git-svn as many projects I'm 
working on are based on Subversion. At least Git Cygwin is a perfect 
solution on Windows.

> Any experiences you can share?  Is MSysGit ready yet or should we
> wait?

I have never used MSysGit, so I won't comment.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|              http://www.obry.net
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595

^ permalink raw reply

* Re: [PATCH] Fix buffer overflow in prepare_attr_stack
From: Johannes Sixt @ 2008-07-16 15:21 UTC (permalink / raw)
  To: Dmitry Potapov; +Cc: git, Johannes Schindelin
In-Reply-To: <1216220043-27678-2-git-send-email-dpotapov@gmail.com>

Dmitry Potapov schrieb:
> +			pathbuf.len = 0;

+			strbuf_reset(&pathbuf);

-- Hannes

^ permalink raw reply

* [PATCH v2] Fix buffer overflow in git-grep
From: Dmitry Potapov @ 2008-07-16 15:33 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Dmitry Potapov
In-Reply-To: <alpine.DEB.1.00.0807161232110.8503@eeepc-johanness>

If PATH_MAX on your system is smaller than any path stored in the git
repository, that can cause memory corruption inside of the grep_tree
function used by git-grep.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
I have converted grep_tree code to use path_buf.

 builtin-grep.c |   26 ++++++++++++++------------
 1 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/builtin-grep.c b/builtin-grep.c
index ef29910..507bb95 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -427,33 +427,35 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
 	struct name_entry entry;
 	char *down;
 	int tn_len = strlen(tree_name);
-	char *path_buf = xmalloc(PATH_MAX + tn_len + 100);
+	struct strbuf pathbuf;
+
+	strbuf_init(&pathbuf, PATH_MAX + tn_len);
 
 	if (tn_len) {
-		tn_len = sprintf(path_buf, "%s:", tree_name);
-		down = path_buf + tn_len;
-		strcat(down, base);
-	}
-	else {
-		down = path_buf;
-		strcpy(down, base);
+		strbuf_add(&pathbuf, tree_name, tn_len);
+		strbuf_addch(&pathbuf, ':');
+		tn_len = pathbuf.len;
 	}
-	len = strlen(path_buf);
+	strbuf_addstr(&pathbuf, base);
+	len = pathbuf.len;
 
 	while (tree_entry(tree, &entry)) {
-		strcpy(path_buf + len, entry.path);
+		int te_len = tree_entry_len(entry.path, entry.sha1);
+		pathbuf.len = len;
+		strbuf_add(&pathbuf, entry.path, te_len);
 
 		if (S_ISDIR(entry.mode))
 			/* Match "abc/" against pathspec to
 			 * decide if we want to descend into "abc"
 			 * directory.
 			 */
-			strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/");
+			strbuf_addch(&pathbuf, '/');
 
+		down = pathbuf.buf + tn_len;
 		if (!pathspec_matches(paths, down))
 			;
 		else if (S_ISREG(entry.mode))
-			hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);
+			hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
 		else if (S_ISDIR(entry.mode)) {
 			enum object_type type;
 			struct tree_desc sub;
-- 
1.5.6.3.1.g4e6bb

^ permalink raw reply related

* [PATCH v2] Fix buffer overflow in prepare_attr_stack
From: Dmitry Potapov @ 2008-07-16 15:39 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, Johannes Schindelin
In-Reply-To: <487E11F7.60601@viscovery.net>

If PATH_MAX on your system is smaller than a path stored in the git repo,
it may cause the buffer overflow in prepare_attr_stack.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---

On Wed, Jul 16, 2008 at 05:21:27PM +0200, Johannes Sixt wrote:
> Dmitry Potapov schrieb:
> > +			pathbuf.len = 0;
> 
> +			strbuf_reset(&pathbuf);
> 
> -- Hannes

 attr.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/attr.c b/attr.c
index 0fb47d3..17f6a4d 100644
--- a/attr.c
+++ b/attr.c
@@ -459,7 +459,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
 {
 	struct attr_stack *elem, *info;
 	int len;
-	char pathbuf[PATH_MAX];
+	struct strbuf pathbuf;
+
+	strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
 
 	/*
 	 * At the bottom of the attribute stack is the built-in
@@ -510,13 +512,14 @@ static void prepare_attr_stack(const char *path, int dirlen)
 			len = strlen(attr_stack->origin);
 			if (dirlen <= len)
 				break;
-			memcpy(pathbuf, path, dirlen);
-			memcpy(pathbuf + dirlen, "/", 2);
-			cp = strchr(pathbuf + len + 1, '/');
+			strbuf_reset(&pathbuf);
+			strbuf_add(&pathbuf, path, dirlen);
+			strbuf_addch(&pathbuf, '/');
+			cp = strchr(pathbuf.buf + len + 1, '/');
 			strcpy(cp + 1, GITATTRIBUTES_FILE);
-			elem = read_attr(pathbuf, 0);
+			elem = read_attr(pathbuf.buf, 0);
 			*cp = '\0';
-			elem->origin = strdup(pathbuf);
+			elem->origin = strdup(pathbuf.buf);
 			elem->prev = attr_stack;
 			attr_stack = elem;
 			debug_push(elem);
-- 
1.5.6.3.3.geccd

^ permalink raw reply related

* Re: git submodules and commit
From: Avery Pennarun @ 2008-07-16 15:43 UTC (permalink / raw)
  To: Nigel Magnay; +Cc: Git Mailing List
In-Reply-To: <320075ff0807160332k5e49c256tb4191de628ecf41c@mail.gmail.com>

On 7/16/08, Nigel Magnay <nigel.magnay@gmail.com> wrote:
> I wonder if this is a fairly common pattern. We tend to have modules
>  as git repositories, and projects that tie together those git
>  repositories as submodules. [and submodules are necessary because they're
>  shared between multiple supermodules].

I have exactly the same problem as you, and have been working on
improving my own workflow so that someday I can offer patches that
might be generally applicable.

In the meantime, my solution is... some shell scripts checked in at
the top level of my project. :)

In one of my applications, I have a /wv submodule, which provides a
cross-platform build environment.  That environment respectively
contains a /wv/wvstreams submodule, which is a library that we use.

When I make a change to wvstreams that's needed for my application, I
need to check into wvstreams, then check that link into wv, then check
that link into the application.  Then, when I push, I have to make
sure to always push wvstreams first, then wv, then application, or
else other users can end up with "commit id xxxxxx not found" type
errors.

So basically, committing is always harmless, since I can do anything I
want in my own repo (and I want to be able to update wvstreams
*without* always updating wv, and so on).  The tricky part is pushing.
 Here's the script I wrote to make sure I don't screw up when pushing:


~/src/vx-lin $ cat push-git-modules
#!/bin/sh -x
set -e
test -e wv/wvstreams/Makefile
(cd wv/wvstreams && git push origin HEAD:master) &&
(cd wv && git push origin HEAD:master) &&
git push origin HEAD:master ||
echo "Failed!"


Now, this script is pretty flawed.  Notably, it always pushes to the
'master' branch, which is stupid.  However, it works in our particular
workflow, because wvstreams isn't being modified by too many
developers and it's okay if we all commit to master.  This is also
aided by the fact that people are trained to push only after they've
made all the unit tests pass, etc.  And further, individual apps don't
have to update their wvstreams to the latest anyway unless they really
need the latest changes, which is a wonderful feature of git
submodules.

Now, sometimes the above push script will fail.  In my experience,
this is only when someone else has pushed in something before you,
which means a fast-forward is not possible on at least one of the
repos.  When that happens, you have to pull first, using this script:

~/src/vx-lin $ cat newest-git-modules
#!/bin/sh -x
set -e
test -e wv/wvstreams/Makefile
git pull origin master &&
(cd wv && git pull origin master) &&
(cd wv/wvstreams && git pull origin master) ||
echo "Failed!"

This pulls in the latest version of application, wv, and wvstreams, in
that order, and stops in case of any merge conflicts so that you can
resolve them by hand.  It's safe to run the above script more than
once in case you're not sure if it's done or not.

After pulling the new modules, you may need to make new commits to
update to the latest submodule commits - if that's indeed what you
want.  And then you can run push-git-modules, and be reasonably
assured that it will work (unless someone made another push while you
were fixing conflicts).

Finally, I have another script that retrieves the *currently linked*
version of the git modules.  I wish git-checkout would do this
automatically, but it doesn't, for apparently-difficult-to-resolve
safety reasons.  Anyway, note that this script uses the existence of
submodule/Makefile as "proof" that the submodule was checked out
correctly.


~/src/vx-lin $ cat get-git-modules
#!/bin/sh -x
set -e
git submodule init
git submodule update
test -e wv/Makefile
(cd wv && git submodule init && git submodule update)
test -e wv/wvstreams/Makefile


>  I guess it probably gets sticky when there are merge conflicts. Is
>  anyone working on this kind of thing; I might be able to give some
>  time to help work on it?

So as you can see, my scripts are crappy.  However, they have already
drastically reduced the number of mistakes made by developers in my
group (especially commits lost due to 'git submodule update' at the
wrong time, and pushes of the supermodule before the submodule).

If you want to work with me on my new submodule workflow (and I'd
certainly appreciate it!) then I'd suggest one or more of the
following starting points:

- Take the recursive push, pull, and update operations described
above, make them general (ie. not referring to my submodules by name
:)), and add them as commands in the real git-submodule script.  The
trickiest part here will be figuring out which remote branch to
push/pull.

- Perhaps add a "recursive commit" operation that recursively
auto-commits submodule refs, for use after running the
newest-git-modules script.  The commit message could be auto-generated
using something like "git-whatchanged" on the submodule.

- See what can be done about making git-checkout automatically
git-submodule-update *if and only if* the currently checked-out commit
of the submodule exactly matches the one that was checked out last
time, *and* the desired commit is already available in the submodule
repo (which is not necessarily the case, if you haven't fetched it
yet).  That is, as with any file in git, if it hasn't changed from the
one in the repo, you know you won't lose any information if you just
auto-replace it with the new version.

- Fix git-submodule-update to not just switch submodule branches if
you've made checkins in that submodule.  Right now, commits to a
submodule by default don't go to any branch, so if you subsequently
run git-submodule-update, your commits are lost (except for the
reflog).  This is very un-git-like in general, and
git-submodule-update should be much more polite.

Note that git-submodule is only about 800 lines of shell.  It's
remarkably straightforward to make it do whatever you want.  The hard
part is figuring out what you want, and making sure you don't stomp on
*other* people's workflows while you're there.

Also note that even if you don't contribute any of the above, I'm
planning to someday make time to do it myself :)  But don't hold your
breath.  I've been busy.

Have fun,

Avery

^ permalink raw reply

* Re: [PATCH] Use SHELL_PATH
From: Junio C Hamano @ 2008-07-16 15:46 UTC (permalink / raw)
  To: sverre; +Cc: namsh, git
In-Reply-To: <bd6139dc0807160347n2ebcd64fy7a15fe94bfabe580@mail.gmail.com>

"Sverre Rabbelier" <alturin@gmail.com> writes:

> On Wed, Jul 16, 2008 at 3:31 AM, SungHyun Nam <goweol@gmail.com> wrote:
>>
>> Signed-off-by: SungHyun Nam <goweol@gmail.com>
>> ---
>>  t/Makefile |    2 +-
>>  1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/t/Makefile b/t/Makefile
>> index a778865..0d65ced 100644
>> --- a/t/Makefile
>> +++ b/t/Makefile
>> @@ -26,7 +26,7 @@ clean:
>>        $(RM) -r 'trash directory' test-results
>>
>>  aggregate-results:
>> -       ./aggregate-results.sh test-results/t*-*
>> +       '$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-*
>>
>>  # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
>>  full-svn-test:
>> --
>> 1.5.6.3.350.g6c11a
>
> It is not clear to me what this patch does, there is no justification
> in the commit msg either. Instead you say what is being done, which we
> can see from the commit diff. Please clarify?

It wants to make sure that the shell specified from the toplevel Makefile
(or from make command line) is used to run the aggregation script.  It is
often necessary when platform /bin/sh is not quite POSIX (e.g. the script
in question uses arithmetic expansion "$(( $var1 + $var2 ))").

Just saying "Use specified shell to run shell scripts" on the title line
would be sufficient, but I wonder if this is the only remaining place...

^ permalink raw reply

* Re: [PATCH] Documentation/git-cherry-pick.txt et al.: Fix misleading -n description
From: Junio C Hamano @ 2008-07-16 15:49 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20080716123344.5875.88693.stgit@localhost>

Petr Baudis <pasky@suse.cz> writes:

> The manual page of git-cherry-pick and git-revert asserts that -n works
> primarily on the working tree, while in fact the primary object it operates
> on is the index, and the changes only "accidentally" propagate to the
> working tree. This e.g. leads innocent #git IRC folks to believe that you
> can use -n to prepare changes for git-add -i staging.

True, and false ;-)  Just "unstage" first in your "git add -i" session and
then add only the necessary pieces back to the index (alternatively you
can "reset" before entering "git add -i" session).

The change is good; will apply.

^ permalink raw reply

* Re: [PATCH] Use SHELL_PATH
From: Junio C Hamano @ 2008-07-16 16:05 UTC (permalink / raw)
  To: sverre; +Cc: namsh, git
In-Reply-To: <7vr69tu91e.fsf@gitster.siamese.dyndns.org>

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

> It wants to make sure that the shell specified from the toplevel Makefile
> (or from make command line) is used to run the aggregation script.  It is
> often necessary when platform /bin/sh is not quite POSIX (e.g. the script
> in question uses arithmetic expansion "$(( $var1 + $var2 ))").
>
> Just saying "Use specified shell to run shell scripts" on the title line
> would be sufficient, but I wonder if this is the only remaining place...

People on funny platforms might find this one useful, which is consistent
with the way the patch under discussion called the shell.  This lets you
to say

	SHELL_PATH = /Program Files/GNU/Bash

or something silly like that ;-)

 Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile b/Makefile
index 9b52071..a2b2627 100644
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,7 @@ all::
 # broken, or spawning external process is slower than built-in grep git has).
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
-	@$(SHELL_PATH) ./GIT-VERSION-GEN
+	@'$(SHELL_PATH_SQ)' ./GIT-VERSION-GEN
 -include GIT-VERSION-FILE
 
 uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')

^ permalink raw reply related

* Re: [PATCH 0/5] add pack index v2 reading capability to git v1.4.4.4
From: Linus Torvalds @ 2008-07-16 16:25 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Junio C Hamano, git
In-Reply-To: <1216189899-14279-1-git-send-email-nico@cam.org>



On Wed, 16 Jul 2008, Nicolas Pitre wrote:
> 
> Junio: if you could just apply them, tag the result as v1.4.4.5 and
> push it out then at that point it simply will be up to Debian to make
> it available as a "major usability fix".

Actually, it fixes a crash. Didn't 1.4.4 SIGSEGV without this on pack-v2?

So you don't even have to sell it as a usability issue, but literally as a 
bugfix.

		Linus

^ permalink raw reply

* Re: [PATCH 0/5] add pack index v2 reading capability to git v1.4.4.4
From: Junio C Hamano @ 2008-07-16 17:04 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Nicolas Pitre, git, Gerrit Pape
In-Reply-To: <alpine.LFD.1.10.0807160924340.2835@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> writes:

> On Wed, 16 Jul 2008, Nicolas Pitre wrote:
>> 
>> Junio: if you could just apply them, tag the result as v1.4.4.5 and
>> push it out then at that point it simply will be up to Debian to make
>> it available as a "major usability fix".
>
> Actually, it fixes a crash. Didn't 1.4.4 SIGSEGV without this on pack-v2?
>
> So you don't even have to sell it as a usability issue, but literally as a 
> bugfix.

It's tagged and pushed out to both kernel.org and repo.or.cz.  Thanks, Nico.

I won't be doing my usual full release engineering on this one, but I did:

 - repack a copy of git.git to use pack idx version #2 for trial.

	Hint.  A handy way to tell which version of packfile you have is
	to run this:

	$ od -c .git/objects/pack/pack-$your_pack_id.idx | head -n 1
        
        If the output begins with "377 t 0 c", you have pack idx version
        #2.

 - check "git log" from v1.4.4.4 (fails) and v1.4.4.5 (reads ok)

 - repack this copy with "git repack" from 1.4.4.5.  This produced a
   repository usable by v1.4.4.4.

I also updated /pub/scm/git/git.git/config at kernel.org to use

	[pack]
        	indexVersion = 1

for now.  The repository is also repacked with pack idx version #1.

^ permalink raw reply

* Re: [PATCH 0/5] add pack index v2 reading capability to git v1.4.4.4
From: Junio C Hamano @ 2008-07-16 17:08 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Nicolas Pitre, git
In-Reply-To: <alpine.LFD.1.10.0807160924340.2835@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> writes:

> Actually, it fixes a crash. Didn't 1.4.4 SIGSEGV without this on pack-v2?

I do not think it should SEGV.  The pack-idx signature was chosen rather
carefully to allow older ones to die gracefully.

    error: non-monotonic index
    error: Could not read 4a588075c54cd5902e5f4d43b9d6b0c31d0f9769

But as I said in the other message, it's tagged and pushed out already.

^ permalink raw reply

* Considering teaching plumbing to users harmful
From: Johannes Schindelin @ 2008-07-16 17:21 UTC (permalink / raw)
  To: git

Hi,

there have been a number of occasions where I came across people trying to 
be helpful and teaching Git newbies a few tricks.

However, in quite a number of cases, which seem to surge over the last 
weeks, I see people suggesting the use of rev-parse, ls-tree, rev-list 
etc.

Their rationale is invariably "but I found it useful", and they seem to be 
unable to recognize the puzzlement in the faces of the people they are 
trying to help.

Instead they insist that they did nothing wrong.

I had the pleasure of introducing Git to a few users in the last months 
and in my opinion, restricting myself to teaching them these commands 
first helped tremendously:

- clone, pull, status, add, commit, push, log

All of these were presented without options, to keep things simple.

In particular, I refrained from giving them the "-a" option to commit.  
That seemed to help incredibly with their embracing the index as a natural 
concept (which it is).

Often I presented the "pull" and "push" commands _only_ with "origin 
master" ("origin is where the repository came from, and master is the 
branch; you will want to use other parameters here after you used Git for 
a while").

_After_ they grew comfortable with Git, I taught them a few options here 
and there, not hiding, but also not promoting the full range of options.

So the next tricks were

- log -p, rm, diff, diff --cached, show

The last one is "show", and with that command, I taught the 
"<commit>:" and "<commit>:<file>" syntax, too (which some Git old-timers 
did not know about ;-)

The pace needed to be adjusted to the users, in my experience, but not the 
order.

Now, it makes me really, really sad that Git has a reputation of being 
complicated, but I regularly hear from _my_ users that they do not 
understand how that came about.

Am I the only one who deems teaching plumbing to users ("I like it raw!  
So I teach it the same way!") harmful?

Ciao,
Dscho "who is sad"

^ permalink raw reply

* Re: [PATCH 0/5] add pack index v2 reading capability to git v1.4.4.4
From: Linus Torvalds @ 2008-07-16 17:34 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Pitre, git
In-Reply-To: <7vhcapsqoa.fsf@gitster.siamese.dyndns.org>



On Wed, 16 Jul 2008, Junio C Hamano wrote:
> 
> I do not think it should SEGV.  The pack-idx signature was chosen rather
> carefully to allow older ones to die gracefully.

Well, Pasky reported differently.

>     error: non-monotonic index
>     error: Could not read 4a588075c54cd5902e5f4d43b9d6b0c31d0f9769

Pasky's report was

	error: non-monotonic index
	/usr/bin/git-fetch: line 297: 30402 Segmentation fault git-http-fetch -v -a "$head" "$remote/"

but maybe that was something specific to his case.

		Linus

^ permalink raw reply

* Re: Considering teaching plumbing to users harmful
From: Avery Pennarun @ 2008-07-16 17:53 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0807161804400.8950@racer>

On 7/16/08, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>  Am I the only one who deems teaching plumbing to users ("I like it raw!
>  So I teach it the same way!") harmful?

I believe the only way you can get away with such a simple learning
sequence is if your workflow is as simple as that you seem to
describe: everyone has push access to the central 'master'.

That works (and mostly just as well as any other "supposedly easy"
VCS, like svn), but because git's power is so tempting, almost
nobody's real-life repository actually works like that.

At the very least, there will be branches.  And where there are
branches, there's merging.  And with merging comes merge conflicts.
And with merge conflicts comes the crazy (yes, very useful, but still
crazy) conflicted index features.  And so you suddenly need to find
out about things like

       git diff :{1,3}:path/to/filename

Which is a great command, but svn definitely makes it easier to do the
same thing.

Even if you have a repo with widespread push access, git's log looks
annoying compared to svn because of all the merge commits.  That's a
primary reason why rebase was invented, of course.   But teaching
people about rebase vs. merge is highly nontrivial.  "git pull
--rebase" helps a little, but it's still nontrivial, particularly when
local patch #3 of 5 has a conflict.

Also, inevitably, someone will ask "what happened to those simple svn
revision numbers?" or "when I do a merge, why are the patches from
branch #1 interspersed with the ones from branch #2 in git log?"  The
answers are "look at gitk to see the real merge history, that's way
more powerful than svn, and check out git-bisect!" and "use git log
--topo-order" respectively, but those are pretty nontrivial answers
too.

Submodules, which are critical to large-scale software development,
are also very complicated.  You can't explain how to use them without
knowing about .git/config, the difference between that and
.gitmodules, the concept of gitlinks (and therefore the concepts of
trees and blobs), the idea of a "disconnected HEAD" (which all
submodules check out by default), the idea that pushing submodules in
the wrong order can create references to non-existing commitids, and
so on.  In contrast, the lame svn:externals mechanism is far easier to
explain.

The "problem" with learning git is that it's so powerful.  A person
can feel like they've "learned all the svn there is to learn" in a
couple of days, because it really doesn't do all that much.  But with
git, if you want to make it *appear* simple, you have to artificially
restrict what you tell people, and because the git *developers* don't
work using that restricted subset of commands, the abstraction always
leaks.

Example: "git remote" didn't originally even have an "rm" subcommand.
Why?  Because real git developers knew they could delete a remote by
editing .git/config, and it never even occurred to anyone to do it any
other way.  I still do it by editing the file, because the file is in
a nice format and it's still easier than typing "git remote".

The svn developers have the same annoyingly small subset of commands
that their users do.  It means svn is much less powerful, but it also
means that subset is actually enough to somehow handle *all* the tasks
a user will run into.  After all, there's no other way.

That said, it's debatable if all this is actually a problem.  If I
wanted simple-minded, I'd use svn.  Ironically, the plumbing is the
only part of git that isn't supposed to ever change, so it's the most
valuable knowledge to have. Why *not* teach it?

Have fun,

Avery

^ permalink raw reply

* Hacks for AIX
From: Chris Cowan @ 2008-07-16 17:57 UTC (permalink / raw)
  To: git

I saw some earlier postings about this, so I thought I would share my
solution (I'm using xlc, BTW).   The following tests were broken for
me (using a pull from 2 days ago).

    * t0002-gitfile.sh
    * t1002-read-tree-m-u-2way.sh
    * t2201-add-update-typechange.sh
    * t4109-apply-multifrag.sh
    * t4110-apply-scan.sh
    * t7002-grep.sh


The problems all seem to be rooted in the default utilities shipped with AIX:

    * /usr/bin/grep - behaves badly in t7002.   I believe it is test
12 and related to the -n -w -e combination of options.
    * /usr/bin/diff - has problems with -u and -U.
                         I saw the $GIT_CMP_TEST env var, but this is
not used everywhere within the test scripts above.
    * /usr/bin/patch - really old version, doesn't do well with some
diff formats.   I avoid using it.
    * /usr/bin/install - doesn't behave the expected way either.

In some cases, the tests could have been made more portable by using a
plain "diff" rather than "diff -u", for example.

Fortunately, there are optional freeware versions that can be
installed for all of these (along with tar and wish too).   These
versions if installed, are all found in /usr/linux/bin (or
equivalently /opt/freeware/bin), I just wish they weren't optional.  I
have found that having these utilities installed and prepending
/usr/linux/bin to the PATH results in a clean make test and build.

I also saw one instance where the behavior of git-grep was affected by
the grep selected at build time.    I'm not sure if there's other
instances within the code base, but I'm wondering whether the
configure script can be changed to do the check for /usr/linux/bin and
use those versions?   I can imagine that similar problems may occur on
Solaris and HPUX.

Otherwise, I'm quite happy with git.
-- 
CC

^ permalink raw reply

* [PATCH,RFC] Implement 'git rm --if-missing'
From: Ciaran McCreesh @ 2008-07-16 18:00 UTC (permalink / raw)
  To: git; +Cc: Ciaran McCreesh

git rm --if-missing will only remove files if they've already been removed from
disk.

Signed-off-by: Ciaran McCreesh <ciaran.mccreesh@googlemail.com>
---

There's nothing here that can't be done using git update-index, but git rm
is less scary.

Regarding exit status: I'm not sure whether exit status should be based upon
whether any files were actually removed, or whether it should be based upon
whether or not all of the supplied patterns were matched. I've gone for the
latter, so that 'git rm --if-missing -r .' succeeds if there's nothing to
remove.

I'm not sure whether 'missing' is the best word. '--if-noent' might be more
appropriate, but less familiar to some. Or is this worth a short option?

 Documentation/git-rm.txt |    8 +++++++-
 builtin-rm.c             |    9 ++++++++-
 t/t3600-rm.sh            |   43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index 4d0c495..f9335f3 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -7,7 +7,8 @@ git-rm - Remove files from the working tree and from the index
 
 SYNOPSIS
 --------
-'git rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
+'git rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--if-missing]
+	  [--quiet] [--] <file>...
 
 DESCRIPTION
 -----------
@@ -61,6 +62,11 @@ OPTIONS
 --ignore-unmatch::
 	Exit with a zero status even if no files matched.
 
+--if-missing::
+	Only remove files if they have been removed from disk. Exit status
+	is still based upon whether matches succeed, not whether a remove
+	actually took place.
+
 -q::
 --quiet::
 	'git-rm' normally outputs one line (in the form of an "rm" command)
diff --git a/builtin-rm.c b/builtin-rm.c
index 22c9bd1..4b89705 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -125,7 +125,7 @@ static int check_local_mod(unsigned char *head, int index_only)
 static struct lock_file lock_file;
 
 static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
-static int ignore_unmatch = 0;
+static int ignore_unmatch = 0, if_missing = 0;
 
 static struct option builtin_rm_options[] = {
 	OPT__DRY_RUN(&show_only),
@@ -135,6 +135,7 @@ static struct option builtin_rm_options[] = {
 	OPT_BOOLEAN('r', NULL,             &recursive,  "allow recursive removal"),
 	OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
 				"exit with a zero status even if nothing matched"),
+	OPT_BOOLEAN( 0 , "if-missing",     &if_missing, "only remove missing files"),
 	OPT_END(),
 };
 
@@ -168,6 +169,12 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 		struct cache_entry *ce = active_cache[i];
 		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen))
 			continue;
+		if (if_missing)
+		{
+			struct stat st;
+			if ((lstat(ce->name, &st) == 0) || (errno != ENOENT))
+				continue;
+		}
 		add_list(ce->name);
 	}
 
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index f542f0a..c7c1810 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -143,6 +143,45 @@ test_expect_success '"rm" command suppressed with --quiet' '
 	git commit -m "remove file from rm --quiet test"
 '
 
+test_expect_success 'Test that "rm --if-missing" works' '
+	echo frotz > test-file &&
+	echo frotz > other-file &&
+	git add test-file other-file &&
+	git commit -m "add files from rm --if-missing test" &&
+	rm test-file &&
+	git rm --if-missing test-file other-file &&
+	! git ls-files --error-unmatch test-file &&
+	git ls-files --error-unmatch other-file &&
+	git rm other-file &&
+	git commit -m "remove file from rm --if-missing test"
+'
+
+test_expect_success 'Test that "rm --if-missing -r *" works' '
+	echo frotz > test-file &&
+	mkdir -p frotz &&
+	echo frotz > frotz/other-file &&
+	git add test-file frotz/other-file &&
+	git commit -m "add file from rm --if-missing -r * test" &&
+	rm frotz/other-file
+	git rm --if-missing --ignore-unmatch -r \* &&
+	git ls-files --error-unmatch test-file &&
+	git rm test-file &&
+	git commit -m "remove file from rm --missing -r * test &&
+	! test -d frotz"
+'
+
+test_expect_success 'Test that "rm --if-missing -r *" works even if nothing is removed' '
+	echo frotz > test-file &&
+	mkdir -p frotz &&
+	echo frotz > frotz/other-file &&
+	git add test-file frotz/other-file &&
+	git commit -m "add file from rm --if-missing -r * test" &&
+	git rm --if-missing --ignore-unmatch -r \* &&
+	git rm test-file frotz/other-file &&
+	git commit -m "remove file from rm --missing -r * test &&
+	! test -d frotz"
+'
+
 # Now, failure cases.
 test_expect_success 'Re-add foo and baz' '
 	git add foo baz &&
@@ -217,4 +256,8 @@ test_expect_success 'Remove nonexistent file returns nonzero exit status' '
 	! git rm nonexistent
 '
 
+test_expect_success 'Test that "rm --if-missing nonexistent" fails' '
+	! git rm --if-missing nonexistent
+'
+
 test_done
-- 
1.5.6.3.385.g7c3f1

^ permalink raw reply related

* Re: [PATCH,RFC] Implement 'git rm --if-missing'
From: Petr Baudis @ 2008-07-16 18:06 UTC (permalink / raw)
  To: Ciaran McCreesh; +Cc: git
In-Reply-To: <1216231250-21141-1-git-send-email-ciaran.mccreesh@googlemail.com>

  Hi,

On Wed, Jul 16, 2008 at 07:00:50PM +0100, Ciaran McCreesh wrote:
> git rm --if-missing will only remove files if they've already been removed from
> disk.
> 
> Signed-off-by: Ciaran McCreesh <ciaran.mccreesh@googlemail.com>

  what is the usage scenario? The porcelain options space is a precious
resource, so please explain why do you need this and who is going to use
it (especially with such a long name).


				Petr "Pasky" Baudis

^ permalink raw reply

* Re: Considering teaching plumbing to users harmful
From: Johannes Schindelin @ 2008-07-16 18:12 UTC (permalink / raw)
  To: Avery Pennarun; +Cc: git
In-Reply-To: <32541b130807161053w24a21d7bh1fa800a714ce75db@mail.gmail.com>

Hi,

On Wed, 16 Jul 2008, Avery Pennarun wrote:

> On 7/16/08, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> >  Am I the only one who deems teaching plumbing to users ("I like it raw!
> >  So I teach it the same way!") harmful?
> 
> I believe the only way you can get away with such a simple learning
> sequence is if your workflow is as simple as that you seem to
> describe: everyone has push access to the central 'master'.

That _is_ the most common form.

And with my way of not even bothering to tell users that "git pull" has a 
default remote and branch, it is easy to tell users about pulling from 
somewhere else:

	git pull that.big.machine:~gitte/git my-next

No problem.  After having worked with the first form a few time, this 
command line is surprisingly easy to teach.

> At the very least, there will be branches.

Oh.  And you have to teach plumbing for that?

Besides, you do not start with that.  Most users will be happy with one 
branch called master for the first day, if not week.

> And where there are branches, there's merging.  And with merging comes 
> merge conflicts.

Funny that you should say that: I had that case.  "git pull origin master" 
said something about conflicts.  Happily, this user was able to read, and 
edited the files mentioned to have conflicts.

After resolving the conflicts (the "<<< === >>>" was known from CVS), add 
and commit were again as encountered in the first 2 minutes of my course.

> And so you suddenly need to find out about things like
> 
>        git diff :{1,3}:path/to/filename

No.  Nobody needed that.  All except one user were content with "git 
diff".  That one wanted "git diff --ours".

So there was no use to teach some advanced concepts there, let alone in 
the first few lectures.

But back to the subject: what does this have to do with plumbing?

I will not even bother to reply to your mentioning rebase, submodules, and 
the "complicated" log due to merges for that very reason: all of this can 
be done, easily, with porcelain.

> Ironically, the plumbing is the only part of git that isn't supposed to 
> ever change, so it's the most valuable knowledge to have.

Aha.  So we changed porcelain recently, in a backwards-incompatible way?  
Now, that is news to me.

Ciao,
Dscho

^ permalink raw reply

* Re: Considering teaching plumbing to users harmful
From: Johannes Schindelin @ 2008-07-16 18:14 UTC (permalink / raw)
  To: Jesper Eskilson; +Cc: git
In-Reply-To: <487E34EC.40708@iar.se>

Hi,

On Wed, 16 Jul 2008, Jesper Eskilson wrote:

> Johannes Schindelin wrote:
> 
> > Now, it makes me really, really sad that Git has a reputation of being 
> > complicated, but I regularly hear from _my_ users that they do not 
> > understand how that came about.
> 
> Well, Git is not the easiest tool on the market to learn. For people 
> used to centralized systems such as RCS/CVS/Subversion, many concepts 
> are truly alien. I've recently experienced a transition at our company 
> from MKS/SI (a RCS derivative) to Subversion, and the mental gap was for 
> many users HUGE. Had we done the transition from MKS/SI to Git, I'm sure
>  several user's brains would have exploded.
> 
> From my perspective, the concept I found most difficult to grasp at the 
> very beginning was how the index worked, and many of the introductory 
> texts on Git that I looked through only very brielfy explained the 
> purpose of the index: Why is it there? Why is it called "index"? How 
> does it fit into a typical workflow? Having a CVS/Subversion background, 
> it took a while for me to really assimilate the concept.

What does your answer have to do with my mail, i.e. with plumbing?

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH,RFC] Implement 'git rm --if-missing'
From: Avery Pennarun @ 2008-07-16 18:17 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Ciaran McCreesh, git
In-Reply-To: <20080716180617.GO32184@machine.or.cz>

On 7/16/08, Petr Baudis <pasky@suse.cz> wrote:
>  On Wed, Jul 16, 2008 at 07:00:50PM +0100, Ciaran McCreesh wrote:
>  > git rm --if-missing will only remove files if they've already been removed from
>  > disk.
>  >
>  > Signed-off-by: Ciaran McCreesh <ciaran.mccreesh@googlemail.com>
>
>   what is the usage scenario? The porcelain options space is a precious
>  resource, so please explain why do you need this and who is going to use
>  it (especially with such a long name).

I see the idea here: right now you can do:

         touch a b c
         git add .

And have it auto-add all the new files, so "git commit" will work.
But there is no equivalent for rm, because for obvious reasons,

        rm b c
        git rm .

Doesn't do the same thing.  And "git add ." doesn't auto-recognize
deletions, which probably also makes sense.

"git commit -a", on the other hand, will automatically commit all
deletions for you.  But you don't always want to commit *all* your
changes just because you want to commit all your deletions.

That said, --if-missing is a bit unwieldy.  I don't have a better
suggestion though.

Have fun,

Avery

^ 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