Git development
 help / color / mirror / Atom feed
* Re: Bug: "git checkout -b" should be allowed in empty repo
From: Michael Haggerty @ 2012-01-31 16:32 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Junio C Hamano, git, demerphq
In-Reply-To: <m3k448che9.fsf@localhost.localdomain>

On 01/31/2012 11:09 AM, Jakub Narebski wrote:
> I don't see how this can be done in backward-compatibile way.

Yes, backwards compatibility would probably prevent the NULL commit idea
from ever being implemented in a literal way.

But it is conceivable that it could be faked with some strategic

    if sha1 == '0'*40:
        treat_as_special_null_commit
    elif len(parents) == 0:
        parents = ['0'*40]

In other words, include a little special case fakery in the data
structures near root commits (an O(1) amount of work) to avoid special
cases in all commands that can touch root commits (an O(number of
commands) amount of work).

Alternatively, the NULL commit could be a UI construct that has no
manifestation in the object model.  This would not save implementation
work, but would perhaps give a more consistent way to deal with root
commits in the UI than the current array of --orphan etc. options.

> Please note that in Git it is quite natural to have more than one root
> (parentless) commit, even without presence of disconnected / orphan
> branches.  They are result of joining originally separate projects.
> git.git has quite a few of them (more than 6, IIRC).

I don't see the problem, unless you mean that it would be difficult to
merge repositories that don't link back to a NULL commit with
hypothetical future repositories that do include a NULL commit.  But a
world in which two kinds of repositories have to be supported is
pointless anyway, because then the git code would have to include *both*
kinds of special cases and nothing would be gained.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: [BUG] git clean -X skips a directory containing only ignored files
From: Andrew Wong @ 2012-01-31 16:20 UTC (permalink / raw)
  To: Paul Berry; +Cc: git
In-Reply-To: <CA+yLL67J-7U9z7HVvq5wTc1g4_UCtqYfEyqdt7XR5zDqvQN5NA@mail.gmail.com>

I think there were a bit of discussions on this issues just while ago too:
http://thread.gmane.org/gmane.comp.version-control.git/188605


On 01/30/2012 06:36 PM, Paul Berry wrote:
> I am trying to use "git clean -X" to remove object files (which
> are gitignored) from my source tree, but it appears to miss
> object files that are in a subdirectory without any git-tracked
> files:
>
> $ git init test
> Initialized empty Git repository in /home/pberry/tmp/test/.git/
> $ cd test
> $ mkdir foo
> $ touch foo/bar.o
> $ echo '*.o' > .gitignore
> $ git add .gitignore
> $ git commit -mgitignore
> [master (root-commit) 6b5ffcb] gitignore
>  1 files changed, 1 insertions(+), 0 deletions(-)
>  create mode 100644 .gitignore
> $ git status
> # On branch master
> nothing to commit (working directory clean)
> $ git clean -d -X -f
> $ ls foo
> bar.o
>
> It seems to me that bar.o should have been removed, because
> according to the git-clean docs, -X means "Remove only files
> ignored by git", and bar.o is definitely being ignored by git.
>
>
> It looks like a very similar bug was reported back in 2010, but
> not fixed:
> http://git.661346.n2.nabble.com/BUG-git-clean-X-behaviour-when-gitignore-has-sub-directory-entries-td5575307.html.
> I've confirmed that the workaround mentioned by Jonathan Nieder
> in that thread fixes my problem too (removing "dir.flags |=
> DIR_SHOW_OTHER_DIRECTORIES;" from builtin/clean.c).  However I'm
> guessing from Jonathan's comments that it would be better to fix
> this bug elsewhere (somewhere in dir.c perhaps).
>
> Is anyone interested in following up on this old bug?
> Alternatively, if someone could give me some guidance as to the
> best way to go about fixing this bug, I would be glad to submit a
> patch.
>
> Thanks,
>
> Paul
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>   

^ permalink raw reply

* Re: [BUG] git clean -X skips a directory containing only ignored files
From: Paul Berry @ 2012-01-31 17:39 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git
In-Reply-To: <4F27FF01.6040706@elegosoft.com>

On 31 January 2012 06:47, Michael Schubert <mschub@elegosoft.com> wrote:
> On 01/31/2012 12:36 AM, Paul Berry wrote:
>> I am trying to use "git clean -X" to remove object files (which
>> are gitignored) from my source tree, but it appears to miss
>> object files that are in a subdirectory without any git-tracked
>> files:
>>
>> $ git init test
>> Initialized empty Git repository in /home/pberry/tmp/test/.git/
>> $ cd test
>> $ mkdir foo
>> $ touch foo/bar.o
>> $ echo '*.o' > .gitignore
>> $ git add .gitignore
>> $ git commit -mgitignore
>> [master (root-commit) 6b5ffcb] gitignore
>>  1 files changed, 1 insertions(+), 0 deletions(-)
>>  create mode 100644 .gitignore
>> $ git status
>> # On branch master
>> nothing to commit (working directory clean)
>> $ git clean -d -X -f
>> $ ls foo
>> bar.o
>>
>> It seems to me that bar.o should have been removed, because
>> according to the git-clean docs, -X means "Remove only files
>> ignored by git", and bar.o is definitely being ignored by git.
>>
>>
>> It looks like a very similar bug was reported back in 2010, but
>> not fixed:
>> http://git.661346.n2.nabble.com/BUG-git-clean-X-behaviour-when-gitignore-has-sub-directory-entries-td5575307.html.
>> I've confirmed that the workaround mentioned by Jonathan Nieder
>> in that thread fixes my problem too (removing "dir.flags |=
>> DIR_SHOW_OTHER_DIRECTORIES;" from builtin/clean.c).  However I'm
>> guessing from Jonathan's comments that it would be better to fix
>> this bug elsewhere (somewhere in dir.c perhaps).
>
> Removing DIR_SHOW_OTHER_DIRECTORIES just happens to not trigger
> this particular "bug" but breaks pretty much everything else.

Yeah, I had a feeling that might be the case.

>
> As a workaround, you could explicitly add the directory to your
> gitignore file.
>
> Here's a test:
>
> -- >8 --
>
> Subject: [PATCH] t7300-clean: show known breakage with "git clean -d -X"
>
> "git clean -d -X" fails for directories containing only untracked files.
> Example:
>
>        $ ls -R .
>        .:
>        foo
>        ./foo:
>        bar.o
>        $ cat .gitignore
>        *.o
>        $ git clean -d -X -f
>        $ ! test -d foo || echo fail
>
> Reported-by: Paul Berry <stereotype441@gmail.com>
> Signed-off-by: Michael Schubert <mschub@elegosoft.com>
> ---
>  t/t7300-clean.sh |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
> index 800b536..0b6d545 100755
> --- a/t/t7300-clean.sh
> +++ b/t/t7300-clean.sh
> @@ -332,6 +332,13 @@ test_expect_success 'git clean -d -X' '
>
>  '
>
> +test_expect_failure 'git clean -d -X' '
> +  mkdir -p a/b &&
> +  touch a/b/c.o &&
> +  git clean -d -X &&
> +  ! test -d a

Thanks for the test case.  BTW, you might consider changing this last
line to "! test -f a/b/c.o".  Reasoning: it is clear from the docs
that c.o should be removed by "git clean -X" (since c.o is an ignored
file).  It is less clear whether the directories a and a/b should be
removed by "git clean -X", since those directories are not in
themselves ignored, only their contents.

> +'
> +
>  test_expect_success 'clean.requireForce defaults to true' '
>
>        git config --unset clean.requireForce &&
> --
> 1.7.9.174.g356eff6

^ permalink raw reply

* Re: [PATCH] Correct singular form in diff summary line for human interaction
From: Junio C Hamano @ 2012-01-31 17:50 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Nguyễn Thái Ngọc Duy, git,
	Ævar Arnfjörð Bjarmason, Frederik Schwarzer,
	Brandon Casey, dickey
In-Reply-To: <20120131152028.GA10717@burratino>

Jonathan Nieder <jrnieder@gmail.com> writes:

> Nguyễn Thái Ngọc Duy wrote:
>
>> Convenient function interactive_use() is added for this purpose. The
>> command thinks it's in human hands when:
>
> I admit I really dislike this, especially:
>
>>  - GIT_SCRIPTING environment variable is not set

I would have to agree that it is horrible.

> But maybe I'm not the right person to ask, since I'd be okay with
> removing the "s"es (with an appropriate incubation time to discover
> whether we are introducing a regression) unconditionally.
>
> If there is an environment variable to say "I don't want to see
> variations on strings intended for humans", can it be spelled as
> LC_ALL=C?

I have been wondering if we should even care, for two reasons.

 * We have had --numstat forever which is exactly what we added for scripts'
   use. "I've been parsing that output meant for humans" is not an excuse.

 * 'diffstat', at least the recent versions of it (it is hard to track
   down historical versions and I gave up [*1*]), gives output like these:

        1 file changed, 1 insertion(+)
	2 files changed, 3 insertions(+), 1 deletion(-)
	0 files changed

   The first one does not have anything but a one-line addition to a file,
   and we do not even see "0 deletions(-)". The second one is a more
   typical example. The third one is "diffstat </dev/null" [*2*].

If we were to touch this, I would prefer to do so unconditionally without
"hrm, can we reliably guess this is meant for humans?" and release it
unceremoniously, perhaps as part of the next release that will have a much
bigger user-visible UI correction to 'merge'.


[Footnote]

*1* I can guess from http://invisible-island.net/diffstat/CHANGES that the
source is probably kept in RCS, but I couldn't find development histories
beyond what is in that file.

*2* We mistakenly applied a patch to make "git apply --stat </dev/null" to
error out recently, which we might want to fix. But that is a separate
topic.

^ permalink raw reply

* Re: [PATCH v2] find_pack_entry(): do not keep packed_git pointer locally
From: Junio C Hamano @ 2012-01-31 18:02 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, nico
In-Reply-To: <1328010239-29669-1-git-send-email-pclouds@gmail.com>

Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:

>  Changing INVALID_PACK to NULL breaks at least t1050.4. We may
>  restructure the p assignments at the end of find_pack_entry() to
>  allow setting INVALID_PACK to NULL.
>  
>  But I'm not really excited about that.

The patch to do so should be a trivial one on top of this anyway
(attached).

> -		if (p == last_found)
> +		if (p == find_pack_entry_last_found)
>  			p = packed_git;
>  		else
>  			p = p->next;
> -		if (p == last_found)
> +		/*
> +		 * p can be NULL from the else clause above, if initial
> +		 * f_p_e_last_found value (i.e. INVALID_PACK) is NULL, we may
> +		 * advance p again to an imaginary pack in invalid memory
> +		 */
> +		if (p == find_pack_entry_last_found)
>  			p = p->next;

But I think the real issue is that the original loop is written in an
obscure way.  The conversion in f7c22cc (always start looking up objects
in the last used pack first, 2007-05-30) wanted to turn the traversal that
always went from the tip of a linked list to instead first probe the
promising one, and then scan the list from the tip like it used to do,
except that it did not want to probe the one it thought promising again.

So perhaps restructuring the loop by making the logic to probe into a
single pack into a helper function, e.g.

static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
{
	if (last_found) {
		if (find_one(sha1, e, last_found))
			return 1;
	}
        for (p = packed_git; p; p = p->next) {
        	if (p == last_found || !find_one(sha1, e, p))
			continue;
		last_found = p;
		return 1;
	}
        return 0;
}

would make the resulting flow far easier to follow, no?


 sha1_file.c |   16 +++++-----------
 1 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 77512a3..2286789 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -54,9 +54,7 @@ static struct cached_object empty_tree = {
 	0
 };
 
-/* INVALID_PACK cannot be NULL, see comments in find_pack_entry */
-#define INVALID_PACK (struct packed_git *)1
-static struct packed_git *find_pack_entry_last_found = INVALID_PACK;
+static struct packed_git *find_pack_entry_last_found;
 
 static struct cached_object *find_cached_object(const unsigned char *sha1)
 {
@@ -725,7 +723,7 @@ void free_pack_by_name(const char *pack_name)
 			free(p->bad_object_sha1);
 			*pp = p->next;
 			if (find_pack_entry_last_found == p)
-				find_pack_entry_last_found = INVALID_PACK;
+				find_pack_entry_last_found = NULL;
 			free(p);
 			return;
 		}
@@ -2024,7 +2022,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
 	prepare_packed_git();
 	if (!packed_git)
 		return 0;
-	p = find_pack_entry_last_found == INVALID_PACK ? packed_git : find_pack_entry_last_found;
+	p = !find_pack_entry_last_found ? packed_git : find_pack_entry_last_found;
 
 	do {
 		if (p->num_bad_objects) {
@@ -2060,12 +2058,8 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
 			p = packed_git;
 		else
 			p = p->next;
-		/*
-		 * p can be NULL from the else clause above, if initial
-		 * f_p_e_last_found value (i.e. INVALID_PACK) is NULL, we may
-		 * advance p again to an imaginary pack in invalid memory
-		 */
-		if (p == find_pack_entry_last_found)
+
+		if (p && p == find_pack_entry_last_found)
 			p = p->next;
 	} while (p);
 	return 0;

^ permalink raw reply related

* Re: [PATCH] Fix an "variable might be used uninitialized" gcc warning
From: Ramsay Jones @ 2012-01-31 18:36 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: Junio C Hamano, GIT Mailing-list
In-Reply-To: <20111216235908.GA5858@elie.hsd1.il.comcast.net>

Jonathan Nieder wrote:
> Ramsay Jones wrote:
> 
>>         CC builtin/checkout.o
>>     builtin/checkout.c: In function `cmd_checkout':
>>     builtin/checkout.c:160: warning: 'mode' might be used uninitialized \
>>         in this function
> [...]
>> [Note that only 2 out of the 3 versions of gcc I use issues this
>> warning]
> 
> Which version of gcc is that?  Is gcc getting more sane, so we won't
> have to worry about this after a while, or is the false positive a
> new regression that should be reported to them?

[Sorry for the late reply, I've been away from email for several weeks...]

The versions which complain are 3.4.4 and 4.1.2, whereas 4.4.0 compiles
the code without complaint. So, gcc *may* be getting more sane, but I wouldn't
bet on it! :-P

I've had examples of this kind of warning, which relies heavily on the
analysis performed primarily for the optimizer, come-and-go in gcc before; so
don't hold your breath (this is the most volatile part of the compiler).

Having said that, unless you are going to decree that the project only
supports gcc (and presumably only some particular versions of gcc), then you
may well find similar warnings triggered when using other compilers anyway ...

ATB,
Ramsay Jones

^ permalink raw reply

* [PATCH] vcs-svn: Fix some compiler warnings
From: Ramsay Jones @ 2012-01-31 18:48 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: david.barr, Junio C Hamano, GIT Mailing-list


In particular, some versions of gcc complains as follows:

        CC vcs-svn/sliding_window.o
    vcs-svn/sliding_window.c: In function `check_overflow':
    vcs-svn/sliding_window.c:36: warning: comparison is always false \
        due to limited range of data type

        CC vcs-svn/fast_export.o
    vcs-svn/fast_export.c: In function `fast_export_blob_delta':
    vcs-svn/fast_export.c:303: warning: comparison is always false due \
        to limited range of data type

Simply casting the (limited range unsigned) variable in the comparison
to an uintmax_t does not suppress the warning, however, since gcc is
"smart" enough to know that the cast does not change anything regarding
the value of the casted expression. In order to suppress the warning, we
replace the variable with a new uintmax_t variable initialized with the
value of the original variable.

Note that the "some versions of gcc" which complain includes 3.4.4 and
4.1.2, whereas gcc version 4.4.0 compiles the code without complaint.

Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
---

Hi Jonathan,

When I wrote this patch, your "jn/svn-fe" branch was still in pu, so I was
going to ask you to squash this, or some variant, into any re-roll ...

Note, in the original version of this patch, the change to check_overflow()
was much simpler; it was effectively the same 2-line change (modulo some
variable names) which is applied to fast_export_blob_delta(). But it just
didn't look right (not sure why!), which prompted the renaming of the
function parameter names. This is, obviously, an unrelated change, so maybe
the change to sliding_window.c should be reverted to the 2-line change ...

ATB,
Ramsay Jones

 vcs-svn/fast_export.c    |    3 ++-
 vcs-svn/sliding_window.c |   11 ++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c
index 19d7c34..6edd37e 100644
--- a/vcs-svn/fast_export.c
+++ b/vcs-svn/fast_export.c
@@ -300,7 +300,8 @@ void fast_export_blob_delta(uint32_t mode,
 				uint32_t len, struct line_buffer *input)
 {
 	long postimage_len;
-	if (len > maximum_signed_value_of_type(off_t))
+	uintmax_t delta_len = (uintmax_t) len;
+	if (delta_len > maximum_signed_value_of_type(off_t))
 		die("enormous delta");
 	postimage_len = apply_delta((off_t) len, input, old_data, old_mode);
 	if (mode == REPO_MODE_LNK) {
diff --git a/vcs-svn/sliding_window.c b/vcs-svn/sliding_window.c
index 1bac7a4..49a7293 100644
--- a/vcs-svn/sliding_window.c
+++ b/vcs-svn/sliding_window.c
@@ -31,15 +31,16 @@ static int read_to_fill_or_whine(struct line_buffer *file,
 	return 0;
 }
 
-static int check_overflow(off_t a, size_t b)
+static int check_overflow(off_t offset, size_t len)
 {
-	if (b > maximum_signed_value_of_type(off_t))
+	uintmax_t delta_len = (uintmax_t) len;
+	if (delta_len > maximum_signed_value_of_type(off_t))
 		return error("unrepresentable length in delta: "
-				"%"PRIuMAX" > OFF_MAX", (uintmax_t) b);
-	if (signed_add_overflows(a, (off_t) b))
+				"%"PRIuMAX" > OFF_MAX", delta_len);
+	if (signed_add_overflows(offset, (off_t) len))
 		return error("unrepresentable offset in delta: "
 				"%"PRIuMAX" + %"PRIuMAX" > OFF_MAX",
-				(uintmax_t) a, (uintmax_t) b);
+				(uintmax_t) offset, delta_len);
 	return 0;
 }
 
-- 
1.7.9

^ permalink raw reply related

* Re: [PATCH] vcs-svn: Fix some compiler warnings
From: Jonathan Nieder @ 2012-01-31 19:20 UTC (permalink / raw)
  To: Ramsay Jones; +Cc: David Barr, Junio C Hamano, GIT Mailing-list
In-Reply-To: <4F28378F.6080108@ramsay1.demon.co.uk>

Hi,

Ramsay Jones wrote:

> In particular, some versions of gcc complains as follows:
> 
>         CC vcs-svn/sliding_window.o
>     vcs-svn/sliding_window.c: In function `check_overflow':
>     vcs-svn/sliding_window.c:36: warning: comparison is always false \
>         due to limited range of data type

Yuck.  Suppressing this warning would presumably also suppress the
optimization that notices the comparison is always false.

The -Wtype-limits warning also triggers in some other perfectly
reasonable situations: see <http://gcc.gnu.org/PR51712>.  I wonder if
we should keep a list of unreliable warnings somewhere (e.g.,
Meta/Make).

[...]
> Note that the "some versions of gcc" which complain includes 3.4.4 and
> 4.1.2, whereas gcc version 4.4.0 compiles the code without complaint.

Thanks for tracking this down.  Interesting.  -Wtype-limits was split
out from the default set of warnings (!) in gcc 4.3 to address
<http://gcc.gnu.org/PR12963>, among other bugs (r124875, 2007-05-20).

[...]
> --- a/vcs-svn/fast_export.c
> +++ b/vcs-svn/fast_export.c
> @@ -300,7 +300,8 @@ void fast_export_blob_delta(uint32_t mode,
>  				uint32_t len, struct line_buffer *input)
>  {
>  	long postimage_len;
> -	if (len > maximum_signed_value_of_type(off_t))
> +	uintmax_t delta_len = (uintmax_t) len;
> +	if (delta_len > maximum_signed_value_of_type(off_t))
>  		die("enormous delta");
>  	postimage_len = apply_delta((off_t) len, input, old_data, old_mode);

Is there some less ugly way to write the condition "if this value is
not representable in this type"?

I guess I could live with something like the following (please don't
take the names too seriously):

	static inline off_t off_t_or_die(uintmax_t val, const char *msg_if_bad)
	{
		if (val > maximum_signed_value_of_type(off_t))
			die("%s", msg_if_bad);
		return (off_t) val;
	}

	...

		off_t delta_len = off_t_or_die(len, "enormous delta");
		postimage_len = apply_delta(delta_len, input, ...);

What do you think?

Jonathan

^ permalink raw reply

* Re: [PATCH v2] find_pack_entry(): do not keep packed_git pointer locally
From: Nicolas Pitre @ 2012-01-31 19:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy, git
In-Reply-To: <7vr4yf92dg.fsf@alter.siamese.dyndns.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1509 bytes --]

On Tue, 31 Jan 2012, Junio C Hamano wrote:

> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> 
> > +		/*
> > +		 * p can be NULL from the else clause above, if initial
> > +		 * f_p_e_last_found value (i.e. INVALID_PACK) is NULL, we may
> > +		 * advance p again to an imaginary pack in invalid memory
> > +		 */

Ah!  OK so that's why I initially came up with that (void*)1 value.

> But I think the real issue is that the original loop is written in an
> obscure way.

Can't disagree with that, especially when the original author (myself) 
doesn't see clearly through it anymore.

> The conversion in f7c22cc (always start looking up objects in the last 
> used pack first, 2007-05-30) wanted to turn the traversal that always 
> went from the tip of a linked list to instead first probe the 
> promising one, and then scan the list from the tip like it used to do, 
> except that it did not want to probe the one it thought promising 
> again.

Exact.

> So perhaps restructuring the loop by making the logic to probe into a
> single pack into a helper function, e.g.
> 
> static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
> {
> 	if (last_found) {
> 		if (find_one(sha1, e, last_found))
> 			return 1;
> 	}
>         for (p = packed_git; p; p = p->next) {
>         	if (p == last_found || !find_one(sha1, e, p))
> 			continue;
> 		last_found = p;
> 		return 1;
> 	}
>         return 0;
> }
> 
> would make the resulting flow far easier to follow, no?

Indeed.


Nicolas

^ permalink raw reply

* Re: Alternates corruption issue
From: Jeff King @ 2012-01-31 19:39 UTC (permalink / raw)
  To: Richard Purdie; +Cc: GIT Mailing-list, Hart, Darren, Ashfield, Bruce
In-Reply-To: <1328018729.13744.26.camel@ted>

On Tue, Jan 31, 2012 at 02:05:29PM +0000, Richard Purdie wrote:

> I have a problem with git clone commands using alternates failing by
> mixing up different repositories. I have a situation where I could end
> up with both:
> 
> /srv/mirrors/repo
> /srv/mirrors/repo.git

I think the alternates thing is just a side effect. The real problem is
that clone is picking the wrong repo to clone from! So a simple complete
test would be something like:

    # make confusing bare repos
    git init --bare bare &&
    git init --bare bare.git &&

    # now make some commits; after this
    # segment, "bare" should have its tip
    # at commit "one", and "bare.git" should
    # be at "two".
    git init source &&
    (cd source &&
     echo content >file &&
     git add file &&
     git commit -m one &&
     git push ../bare HEAD &&
     echo content >>file &&
     git commit -a -m two &&
     git push ../bare.git HEAD
    ) &&

    # now try to clone bare and see which one we get;
    # we would expect the tip to be at "one", but it's not
    git clone bare clone &&
    cd clone &&
    echo one >expect &&
    git log -1 --format=%s >actual &&
    diff -u expect actual

    # we cloned the wrong repository!

> Looking at the code, the cause seems to be
> 
> clone.c:get_repo_path():
> 
> 	static char *suffix[] = { "/.git", ".git", "" };
> 
> since its looking in order for:
>  repo/.git (fails)
>  repo.git (suceeds, incorrect)
>  repo (never looked at)

Yeah, this seems brain-dead. It's good that git looks through a magic
list to guess what I meant, but shouldn't the first thing it tries be
the literal string that I gave, and only _then_ kick in the magic?

But even weirder, this doesn't match the lookup in other parts of git. I
see four distinct places in git where we do repository lookup:

  1. get_repo_path used by clone (i.e., this)

  2. enter_repo used by upload-pack, receive-pack, and git-daemon; this
     looks first for ".git/.git", to find a non-bare repo which is named
     like a bare one.

  3. setup_git_directory_*, used by most git programs. This starts
     looking in the current directory and going up, looking first for
     ".git", and then checking for a bare repo. So if you were to do
     "cd bare && git foo", then we would correctly find the current
     directory, not "bare.git".

  4. setup_explicit_git_dir, which gets called if you use --git-dir or
     set GIT_DIR. This expects to find the repo directly in the
     directory you specified, with no magic.

So I think (3) and (4) are sensible, but I tend to think that (1) and
(2) are wrong, and should prefer the directory you gave before the
magic.

> I'm not sure what would break if that order were to change, swapping the
> last two options.

I believe that would work in your case, but it seems like the most
correct thing would actually be:

  { "", "/.git", ".git" }

That is:

  1. Try the literal path the user gave as a repo

  2. Otherwise, try it as the root of a working tree (containing .git)

  3. Otherwise, assume they were too lazy to type ".git" and include it

If you simply swap the last two, then there is one obscure case you
would miss: a bare repo which contains a .git directory. Of course, that
seems like an insane thing to have, but if you did have it, I would
expect git to follow the rules I outlined above. That being said,
if you follow the rules in setup_git_directory_gently_1, it actually
prefers "/.git" to a bare repo. So probably your swap is better, as it
matches the lookup here with the regular setup_git_directory one.

One slight complication is that get_repo_path only checks whether the
paths exist, not whether they are actually git repositories. So by
simply swapping the order, you are breaking some other obscure cases,
like where a "foo" directory exists but is _not_ a git repo, and a
"foo.git" exists alongside it (which sounds a bit crazy, but I could see
somebody using that scheme if they wanted didn't want the git repository
to live inside the worktree for some reason).

One way of dealing with that would be to make get_repo_path a little
more robust by only selecting paths which actually look like git
directories.

The patch below does this, and makes my test above pass. But I think
before talking too much about code, it would be best to decide on what
the lookup order _should_ be, and then we can write tests and implement
to them.

-Peff

---
diff --git a/builtin/clone.c b/builtin/clone.c
index 9084feb..0fbbae9 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -108,7 +108,7 @@ static const char *argv_submodule[] = {
 
 static char *get_repo_path(const char *repo, int *is_bundle)
 {
-	static char *suffix[] = { "/.git", ".git", "" };
+	static char *suffix[] = { "/.git", "", ".git" };
 	static char *bundle_suffix[] = { ".bundle", "" };
 	struct stat st;
 	int i;
@@ -118,7 +118,7 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 		path = mkpath("%s%s", repo, suffix[i]);
 		if (stat(path, &st))
 			continue;
-		if (S_ISDIR(st.st_mode)) {
+		if (S_ISDIR(st.st_mode) && is_git_directory(path)) {
 			*is_bundle = 0;
 			return xstrdup(absolute_path(path));
 		} else if (S_ISREG(st.st_mode) && st.st_size > 8) {
diff --git a/cache.h b/cache.h
index 9bd8c2d..7b2857f 100644
--- a/cache.h
+++ b/cache.h
@@ -436,6 +436,7 @@ extern char *get_object_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
 extern int set_git_dir(const char *path);
+extern int is_git_directory(const char *path);
 extern const char *get_git_namespace(void);
 extern const char *strip_namespace(const char *namespaced_ref);
 extern const char *get_git_work_tree(void);
diff --git a/path.c b/path.c
index b6f71d1..1ca6567 100644
--- a/path.c
+++ b/path.c
@@ -293,7 +293,7 @@ const char *enter_repo(const char *path, int strict)
 
 	if (!strict) {
 		static const char *suffix[] = {
-			".git/.git", "/.git", ".git", "", NULL,
+			"/.git", "", ".git/.git", ".git", NULL,
 		};
 		const char *gitfile;
 		int len = strlen(path);
@@ -324,8 +324,11 @@ const char *enter_repo(const char *path, int strict)
 			return NULL;
 		len = strlen(used_path);
 		for (i = 0; suffix[i]; i++) {
+			struct stat st;
 			strcpy(used_path + len, suffix[i]);
-			if (!access(used_path, F_OK)) {
+			if (!stat(used_path, &st) &&
+			    (S_ISREG(st.st_mode) ||
+			     (S_ISDIR(st.st_mode) && is_git_directory(used_path)))) {
 				strcat(validated_path, suffix[i]);
 				break;
 			}
diff --git a/setup.c b/setup.c
index 61c22e6..7a3618f 100644
--- a/setup.c
+++ b/setup.c
@@ -247,7 +247,7 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
  *    a proper "ref:", or a regular file HEAD that has a properly
  *    formatted sha1 object name.
  */
-static int is_git_directory(const char *suspect)
+int is_git_directory(const char *suspect)
 {
 	char path[PATH_MAX];
 	size_t len = strlen(suspect);

^ permalink raw reply related

* Re: [PATCH] Fix an "variable might be used uninitialized" gcc warning
From: Jonathan Nieder @ 2012-01-31 19:43 UTC (permalink / raw)
  To: Ramsay Jones; +Cc: Junio C Hamano, GIT Mailing-list
In-Reply-To: <4F2834AD.20004@ramsay1.demon.co.uk>

Ramsay Jones wrote:

> The versions which complain are 3.4.4 and 4.1.2, whereas 4.4.0 compiles
> the code without complaint. So, gcc *may* be getting more sane, but I wouldn't
> bet on it! :-P
>
> I've had examples of this kind of warning, which relies heavily on the
> analysis performed primarily for the optimizer, come-and-go in gcc before

Yep, judging from the commit message, Junio found the same warning
in 4.6.2.

[...]
> Having said that, unless you are going to decree that the project only
> supports gcc (and presumably only some particular versions of gcc), then you
> may well find similar warnings triggered when using other compilers anyway ...

Sure, when the control flow grows too complicated, that's probably worth
fixing anyway, for the sake of humans especially.

Sometimes gcc is the only crazy one, though. ;-)

Thanks for the update.
Jonathan

^ permalink raw reply

* Re: [PATCH] vcs-svn: Fix some compiler warnings
From: Junio C Hamano @ 2012-01-31 20:14 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: Ramsay Jones, David Barr, GIT Mailing-list
In-Reply-To: <20120131192053.GC12443@burratino>

Jonathan Nieder <jrnieder@gmail.com> writes:

> 		off_t delta_len = off_t_or_die(len, "enormous delta");
> 		postimage_len = apply_delta(delta_len, input, ...);
>
> What do you think?

Another possibility would be to make the "die" part responsibility of the
caller of the helper function, e.g.

	if (value_out_of_range(off_t, len))
		die("enormous delta");

which may make the caller easier to follow and the helper easier to reuse.

^ permalink raw reply

* Re: Alternates corruption issue
From: Junio C Hamano @ 2012-01-31 20:25 UTC (permalink / raw)
  To: Jeff King; +Cc: Richard Purdie, GIT Mailing-list, Hart, Darren, Ashfield, Bruce
In-Reply-To: <20120131193922.GA31551@sigill.intra.peff.net>

Jeff King <peff@peff.net> writes:

> I believe that would work in your case, but it seems like the most
> correct thing would actually be:
>
>   { "", "/.git", ".git" }
>
> That is:
>
>   1. Try the literal path the user gave as a repo
>
>   2. Otherwise, try it as the root of a working tree (containing .git)
>
>   3. Otherwise, assume they were too lazy to type ".git" and include it

That sounds sensible, together with this, to which I agree with:

> One way of dealing with that would be to make get_repo_path a little
> more robust by only selecting paths which actually look like git
> directories.

... but ...

> diff --git a/builtin/clone.c b/builtin/clone.c
> index 9084feb..0fbbae9 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -108,7 +108,7 @@ static const char *argv_submodule[] = {
>  
>  static char *get_repo_path(const char *repo, int *is_bundle)
>  {
> -	static char *suffix[] = { "/.git", ".git", "" };
> +	static char *suffix[] = { "/.git", "", ".git" };

... this does not match that simple and clear guideline.

Shouldn't this simply be { "", "/.git", ".git" }?

> diff --git a/path.c b/path.c
> index b6f71d1..1ca6567 100644
> --- a/path.c
> +++ b/path.c
> @@ -293,7 +293,7 @@ const char *enter_repo(const char *path, int strict)
>  
>  	if (!strict) {
>  		static const char *suffix[] = {
> -			".git/.git", "/.git", ".git", "", NULL,
> +			"/.git", "", ".git/.git", ".git", NULL,
>  		};

Neither does this.

Shouldn't this be { "", "/.git", ".git", ".git/.git", NULL }?

I must be missing something from your description...

^ permalink raw reply

* Re: Alternates corruption issue
From: Jeff King @ 2012-01-31 20:44 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Richard Purdie, GIT Mailing-list, Hart, Darren, Ashfield, Bruce
In-Reply-To: <7v1uqf8vqu.fsf@alter.siamese.dyndns.org>

On Tue, Jan 31, 2012 at 12:25:45PM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > I believe that would work in your case, but it seems like the most
> > correct thing would actually be:
> >
> >   { "", "/.git", ".git" }
> >
> > That is:
> >
> >   1. Try the literal path the user gave as a repo
> >
> >   2. Otherwise, try it as the root of a working tree (containing .git)
> >
> >   3. Otherwise, assume they were too lazy to type ".git" and include it
> 
> That sounds sensible, together with this, to which I agree with:
> [...]
> ... but ...
> [...]
> > -	static char *suffix[] = { "/.git", ".git", "" };
> > +	static char *suffix[] = { "/.git", "", ".git" };
> 
> ... this does not match that simple and clear guideline.
> 
> Shouldn't this simply be { "", "/.git", ".git" }?

No, it does not match. While the sequence I outlined above makes the
most sense to me, it does not match what setup_git_directory does, which
prefers "foo/.git" to using "foo" as a bare repo. I think being
consistent between all of the lookup points makes sense. The patch took
the least-invasive approach and aligned clone and enter_repo with
setup_git_directory.

However, we could also tweak setup_git_directory to prefer bare repos
over ".git" to keep things consistent. While it makes me feel good from
a theoretical standpoint (because the rules above seem simple and
intuitive to me), I'm not sure it's a good idea in practice.

The case we would "catch" with such a change is when you have a ".git"
directory inside a bare repo. Right now, we prefer the ".git" inside it,
and ignore the containing bare repo. With such a change, we would prefer
the outer bare repo. Which makes sense to me. It does break a use
case like this:

  # make a new repo
  git init
  cd .git
  # now track parts of the repo
  git init
  git add config
  git commit -m 'tracking our repo config'

but I'm not sure if that is sane or not.

But also consider false positives. What if you have a repository that
looks like a git repo (i.e., has "objects", "refs", and "HEAD" in it),
but also has ".git". Right now we say "Oh, it has .git, that must be the
repo". But with the proposed change, we could accidentally find the
enclosing repo.

Now, the chances of is_git_directory being wrong seem quite slim to me.
But then, the chances of somebody actually have a repo with a ".git"
_inside_ it seem pretty slim to me. So I think we are really dealing
with a tiny corner case, and it is perhaps anybody's guess whether
anyone is depending on the current behavior in the wild. I don't overly
care either way, but when in doubt, I tend to stick with the existing
behavior.

> >  	if (!strict) {
> >  		static const char *suffix[] = {
> > -			".git/.git", "/.git", ".git", "", NULL,
> > +			"/.git", "", ".git/.git", ".git", NULL,
> >  		};
> 
> Neither does this.
> 
> Shouldn't this be { "", "/.git", ".git", ".git/.git", NULL }?

Right, same case.

> I must be missing something from your description...

I mentioned the issue in my original message, but perhaps didn't
emphasize it very well.

-Peff

^ permalink raw reply

* Re: [RFC/PATCH] add update to branch support for "floating submodules"
From: Jens Lehmann @ 2012-01-31 20:55 UTC (permalink / raw)
  To: Phil Hord; +Cc: Junio C Hamano, Leif Gruenwoldt, git
In-Reply-To: <CABURp0pDoS1wgJ+Fs3XFX=A_EuR4Gzi4mHLiQP+-icT_d3J+WQ@mail.gmail.com>

Am 30.01.2012 22:15, schrieb Phil Hord:
> I lost my grip on this thread over the holidays...
> 
> On Tue, Dec 13, 2011 at 4:09 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
>> Am 13.12.2011 15:17, schrieb Phil Hord:
>>>   git pull origin topic_foo && git submodule foreach 'git pull origin topic_foo'
>>>
>>>   git submodule foreach 'git push origin topic_foo' && git push origin topic_foo
>>
>> This sounds to me like you would need the "--recurse-submodules" option
>> implemented for "git pull" and "git push", no?
> 
> Only if I have nested submodules, but yes, we do use --recurs* in our scripts.

I'm confused, push doesn't know the "--recurse-submodules" option
at all yet while pull only does a deep fetch when it is given, the
submodule work trees are not updated to the merge result right now.

>> And I miss to see how
>> floating would help when the tips of some submodules are not ready to
>> work with other submodules tips ...
> 
> By project policy, for any branch, all submodules' tips of the
> same-named branch should be interoperable.  The CI server looks after
> this, as much as he can.

We do the same thing on our CI server, but it can only test some
combinations (even though that tends to show most problems pretty
early). But in the end every superproject is responsible to use a
working set of submodule commits, and I would rather bet on a
combination the CI server tested than on what happens to be on the
current tips.

> I think of branch names as sticky notes (extra-lightweight tags,
> sometimes).  We have linear history in many of our vendor submodules,
> but multiple "branches" indicate where each superproject branch has
> presumably finished integration.

We also add a branch in submodules every time a superproject needs
to move away from the submodules master (so the commits won't get
lost by accident).

>>> But not all my developers are git-gurus yet, and they sometimes mess
>>> up their ad hoc scripts or miss important changes they forgot to push
>>> in one submodule or another.
>>
>> Sure, even though current git should help you some by showing changes
>> in the submodules.
> 
> Real newbies may not even remember to use 'git status' strategically.

Hmm, but then they will screw up things in the superproject too, no?

>>>  Or worse, their pull or push fails and
>>> they can't see the problem for all the noise.  So they email it to me.
>>
>> We circumvent that by not pulling, but fetching and merging in the
>> submodule first and after that in the superproject. You have much more
>> control about what is going wrong where (and can have more
>> git-experienced people help with - or even do - the merges).
> 
> I do that, too, and I wish I didn't have to.  I wish I could safely
> and sanely recover from a conflicted "git pull --recurse-submodules"
> pull from the superproject.

That's what my recursive checkout work is aiming at. Me thinks after
that we will also need some good ideas on how to present and help
solving submodule merge conflicts.

> That is, I wish doing so were as
> straightforward as recovering from the same condition would be if all
> my code were in one repository instead of in submodules.
>
> Which is the gist -- I wish submodules did not make git more
> complicated than it already is.

I think we can make working with submodule much easier than it is
now, the next step being updating all submodule work trees as git
updates the superproject's work tree. Even though I suspect that in
the long run submodules will always be a bit more complicated than
having everything in one repository, I'm confident that will be by
far outweighed by the advantages they bring.

^ permalink raw reply

* Re: Alternates corruption issue
From: Jonathan Nieder @ 2012-01-31 21:40 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131204417.GA30969@sigill.intra.peff.net>

Jeff King wrote:

> No, it does not match. While the sequence I outlined above makes the
> most sense to me, it does not match what setup_git_directory does, which
> prefers "foo/.git" to using "foo" as a bare repo. I think being
> consistent between all of the lookup points makes sense. The patch took
> the least-invasive approach and aligned clone and enter_repo with
> setup_git_directory.
>
> However, we could also tweak setup_git_directory to prefer bare repos
> over ".git" to keep things consistent. While it makes me feel good from
> a theoretical standpoint (because the rules above seem simple and
> intuitive to me), I'm not sure it's a good idea in practice.

Wait, don't these two functions serve two completely different purposes?

One is the implementation of (A):

	cd foo
	git rev-parse --git-dir

The other implements (B):

	git ls-remote foo

If "foo" is actually a bare repository that moonlights as a worktree for
a non-bare repository, then:

 1) Whoever set up these directories is completely insane[*].  Maybe we
    should emit a warning.

 2) As a naive user, I would expect (A) to give a different result
    from (B).

Hope that helps,
Jonathan

[*] ok, ok, they can be confused instead of insane:
http://bugs.debian.org/399041

^ permalink raw reply

* Re: Alternates corruption issue
From: Jeff King @ 2012-01-31 21:47 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131214047.GA13547@burratino>

On Tue, Jan 31, 2012 at 03:40:47PM -0600, Jonathan Nieder wrote:

> Jeff King wrote:
> 
> > No, it does not match. While the sequence I outlined above makes the
> > most sense to me, it does not match what setup_git_directory does, which
> > prefers "foo/.git" to using "foo" as a bare repo. I think being
> > consistent between all of the lookup points makes sense. The patch took
> > the least-invasive approach and aligned clone and enter_repo with
> > setup_git_directory.
> >
> > However, we could also tweak setup_git_directory to prefer bare repos
> > over ".git" to keep things consistent. While it makes me feel good from
> > a theoretical standpoint (because the rules above seem simple and
> > intuitive to me), I'm not sure it's a good idea in practice.
> 
> Wait, don't these two functions serve two completely different purposes?

Yes, but I would expect the lookup to be the same.

> One is the implementation of (A):
> 
> 	cd foo
> 	git rev-parse --git-dir
> 
> The other implements (B):
> 
> 	git ls-remote foo

Right. But would you expect:

  git ls-remote foo

to behave the same as:

  cd foo
  git ls-remote .

and would you furthermore expect that to behave the same as:

  cd foo
  git rev-parse --git-dir

?

Maybe I am crazy, but I see all of them as ways of specifying "I am
interested in repository foo", and any lookup magic should be the same
in all cases.

> If "foo" is actually a bare repository that moonlights as a worktree for
> a non-bare repository, then:
> 
>  1) Whoever set up these directories is completely insane[*].  Maybe we
>     should emit a warning.

Yes, I think we are dealing with an insane corner case.

>  2) As a naive user, I would expect (A) to give a different result
>     from (B).

Why?

-Peff

^ permalink raw reply

* Re: Alternates corruption issue
From: Jonathan Nieder @ 2012-01-31 21:55 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131214740.GA2465@sigill.intra.peff.net>

Jeff King wrote:

> Right. But would you expect:
>
>   git ls-remote foo
>
> to behave the same as:
>
>   cd foo
>   git ls-remote .
>
> and would you furthermore expect that to behave the same as:
>
>   cd foo
>   git rev-parse --git-dir
>
> ?

Nah.  I never run "git ls-remote .". ;-)

[...]
>>  2) As a naive user, I would expect (A) to give a different result
>>     from (B).
>
> Why?

Normally git commands expect me to be in (possibly a deeply nested
subdirectory) of the worktree.  The typical case is a non-bare
repository.  I have been taught that it walks to the toplevel and
finds a ".git" directory.

By contrast, the path passed to git transport commands like "git fetch
otherhost:/foo/bar/baz.git" is a path to the git repository metadata.
I am not allowed to pass a path to a subdirectory, for example.

As a user, when would the distinction ever come up?  One is a fuzzy
"which repository am I working in", and the other is a precise "point
me to the metadata directory, but I allow you to abbreviate a little
by leaving out the trailing .git".

^ permalink raw reply

* Re: Alternates corruption issue
From: Jeff King @ 2012-01-31 22:05 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131215501.GF13252@burratino>

On Tue, Jan 31, 2012 at 03:55:01PM -0600, Jonathan Nieder wrote:

> >>  2) As a naive user, I would expect (A) to give a different result
> >>     from (B).
> >
> > Why?
> 
> Normally git commands expect me to be in (possibly a deeply nested
> subdirectory) of the worktree.  The typical case is a non-bare
> repository.  I have been taught that it walks to the toplevel and
> finds a ".git" directory.
> 
> By contrast, the path passed to git transport commands like "git fetch
> otherhost:/foo/bar/baz.git" is a path to the git repository metadata.
> I am not allowed to pass a path to a subdirectory, for example.

True. But I consider that to make the walk-backwards-from-pwd case
simply a superset. That is, in (A) we are walking backwards and trying
to apply the lookup rule from (B) individually to each directory we
consider (though even that is not entirely true, as we don't look for
parallel "$PWD.git" directories in the walk).

I'll admit I don't care that much, though. This is extremely unlikely to
come up. The real issue is fixing the fact that we prefer "foo.git" to
"foo", even when the user told us "foo". I am content to leave the rest
of it as-is, which is what my original patch did.

-Peff

^ permalink raw reply

* Re: Alternates corruption issue
From: Jonathan Nieder @ 2012-01-31 22:22 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131220510.GA3253@sigill.intra.peff.net>

Jeff King wrote:

> True. But I consider that to make the walk-backwards-from-pwd case
> simply a superset. That is, in (A) we are walking backwards and trying
> to apply the lookup rule from (B) individually to each directory we
> consider (though even that is not entirely true, as we don't look for
> parallel "$PWD.git" directories in the walk).

That parenthesis is important.  Although in a nicer world maybe we
would want some symmetry like this, (A) and (B) really have nothing to
do with each other.

Forgetting the algorithms:

 (A) means "find what repository we are in the worktree for, or,
 barring that, what bare repository we are in".

 (B) means "find which repository the user pointed to.  To be extra
 nice, we allow a '.git' extension to be left out, so the URL used
 doesn't have to include the redundant information that this is a
 git repository, and we even allow pointing to the toplevel of a
 worktree instead of a repository, too."

Notice that the above description does not exactly match the actual
behavior of git.  For example, if someone has a directory layout like
this:

  repo-manipulator/
     .git/
     src/
     testcases/
       repo1.git/
       repo2.git/

and git is run from repo1.git, according to the description above, the
naive user _wanted_ git commands to apply to the toplevel repository.
And in practice, I think that's often true, though changing the
behavior of git to match that would not be worth the downsides.

> I'll admit I don't care that much, though. This is extremely unlikely to
> come up.

I admit part of the reason I care is that just putting "" first would
probably taken care of the more important part of
<http://bugs.debian.org/399041>.

Anyway, thanks for explaining.  Hopefully I can get to this soon and
factor out a common function for get_repo_path and enter_repo to call
so playing with the ordering becomes a little less scary. ;-)

Jonathan

^ permalink raw reply

* Re: Alternates corruption issue
From: Jeff King @ 2012-01-31 22:42 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131222258.GG13252@burratino>

On Tue, Jan 31, 2012 at 04:22:58PM -0600, Jonathan Nieder wrote:

> Forgetting the algorithms:
> 
>  (A) means "find what repository we are in the worktree for, or,
>  barring that, what bare repository we are in".
> 
>  (B) means "find which repository the user pointed to.  To be extra
>  nice, we allow a '.git' extension to be left out, so the URL used
>  doesn't have to include the redundant information that this is a
>  git repository, and we even allow pointing to the toplevel of a
>  worktree instead of a repository, too."

I can see that as a plausible interpretation. But I think your "means"
is kind of vague.  In other words, we are assigning a meaning that is
not actually documented anywhere, and which we are hoping matches user
expectations. So the correct behavior kind of depends on your mental
model. IOW, I find your mental model plausible, but it is not the one
that I had.

But like I said, I'm OK either way. I'll prepare this fix with the least
behavior change possible. Then doing your change on top should be a
trivial rearrangement of the lookup arrays (the "hard" part for your
proposed change is adding in the is_git_directory() calls[1], but I'll
do that as part of mine).

> I admit part of the reason I care is that just putting "" first would
> probably taken care of the more important part of
> <http://bugs.debian.org/399041>.

Would that fix it? If I understand it, the repo in question is bare with
a ".git" directory inside it. Your proposed change would make "git
ls-remote foo" work, but wouldn't "cd foo && git log" still be broken?
At the very least, it would show a completely different repo than
ls-remote.

-Peff

[1] Without the is_git_directory() check, the ordering you propose
    breaks things very badly. Because if I point to a non-bare directory
    "foo", we say "OK, foo exists" and never look at "foo/.git". So
    instead, we have to say "OK, foo exists, but hey, it looks nothing
    like a .git directory" and keep trying.

^ permalink raw reply

* Project structure of .NET-Projects using git submodule or something different
From: Harald Heigl @ 2012-01-31 22:41 UTC (permalink / raw)
  To: git

Hi, I'm searching for an adequate Project-structure for our .NET-Projects,
but I think the problem isn't specific to .NET-Programs, it's more "how can
I nest submodules toghether".

Let's assume following Project structure (Dependencies and Subdependencies
are submodules and submodules of the submodules)
Project
	Dependency 1
		Dependency 2
		Dependency 3
	Dependency 4
	Dependency 2


The problem is if I want to build them I need to build 2+3, then 1, 4 and 2
again and then the project. As you may see project 2 is a submodule of
dependency 1 and also of project. I don't feel comfortable with this setup.
What do you think?
I've also thought about symlinks (though I'm mainly on Windows ), but with
symlinks I'll lose the tight coupling of git submodules by SHA1-revision.
I could also add Dependency 1-4 to my main project, not loading submodule
2-3 within  dependency 1, but then the Project-Files of .NET for dependency1
may change depending if I clone Dependency1 on its own or if I clone my
superproject.

Sometimes I have longer chains (project - submodule - subsubmodule - . ), so
it could easily be that I clone a superproject and 10 subprojects, even
though there are only 3-5 really different subprojects, rest would be
duplicates.

How would you handle this? Git submodules? Something different? 

Thanks in advance,
Harald

^ permalink raw reply

* Re: [RFC/PATCH] add update to branch support for "floating submodules"
From: Phil Hord @ 2012-01-31 22:50 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: Junio C Hamano, Leif Gruenwoldt, git
In-Reply-To: <4F28554D.9090107@web.de>

On Tue, Jan 31, 2012 at 3:55 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
> Am 30.01.2012 22:15, schrieb Phil Hord:
>> I lost my grip on this thread over the holidays...
>>
>> On Tue, Dec 13, 2011 at 4:09 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
>>> Am 13.12.2011 15:17, schrieb Phil Hord:
>>>>   git pull origin topic_foo && git submodule foreach 'git pull origin topic_foo'
>>>>
>>>>   git submodule foreach 'git push origin topic_foo' && git push origin topic_foo
>>>
>>> This sounds to me like you would need the "--recurse-submodules" option
>>> implemented for "git pull" and "git push", no?
>>
>> Only if I have nested submodules, but yes, we do use --recurs* in our scripts.
>
> I'm confused, push doesn't know the "--recurse-submodules" option
> at all yet while pull only does a deep fetch when it is given, the
> submodule work trees are not updated to the merge result right now.

Sorry.  I type faster than I think sometimes.

I meant that I do use something like this:
    git submodule foreach --recursive 'git checkout master' && git
checkout master

And I expect to use something like this:
    git submodule foreach --recursive 'git push origin topic_foo' &&
git push origin topic_foo

>>> And I miss to see how
>>> floating would help when the tips of some submodules are not ready to
>>> work with other submodules tips ...
>>
>> By project policy, for any branch, all submodules' tips of the
>> same-named branch should be interoperable.  The CI server looks after
>> this, as much as he can.
>
> We do the same thing on our CI server, but it can only test some
> combinations (even though that tends to show most problems pretty
> early). But in the end every superproject is responsible to use a
> working set of submodule commits, and I would rather bet on a
> combination the CI server tested than on what happens to be on the
> current tips.

Yes, I see what you mean.  In our case, what "happens to be on the
tips" should also have been vetted by our Gerrit+Jenkins code review
dance (for each branch * each superproject), and so it should always
be good.  If it's not, we have the Jenkins-maintained gitlink history
we can use to bisect.

>> I think of branch names as sticky notes (extra-lightweight tags,
>> sometimes).  We have linear history in many of our vendor submodules,
>> but multiple "branches" indicate where each superproject branch has
>> presumably finished integration.
>
> We also add a branch in submodules every time a superproject needs
> to move away from the submodules master (so the commits won't get
> lost by accident).

Good idea.  Gerrit sees to this for us also, but we do share code on
ancillary git servers and we follow the same practice.

>>>> But not all my developers are git-gurus yet, and they sometimes mess
>>>> up their ad hoc scripts or miss important changes they forgot to push
>>>> in one submodule or another.
>>>
>>> Sure, even though current git should help you some by showing changes
>>> in the submodules.
>>
>> Real newbies may not even remember to use 'git status' strategically.
>
> Hmm, but then they will screw up things in the superproject too, no?

What I mean is that a developer may be completely focused on one
particular submodule (his domain).  He does his work in this module,
and when it's ready he commits and pushes to the server.  'git status'
shows him that his directory is clean.  But this is only because he
doesn't really know where the submodules top-directories are, so he
doesn't realize that he has changes in another submodule that he has
not committed.  He has to know to run 'git status' from somewhere in
the superproject (ostensibly in the root directory of that
superproject).  But he may forget since 'git status' already assured
him he was done.

Like this:

#-- Setup
mkdir super && cd super && git init
mkdir A && touch A/foo
git add .
git submodule add gerrit:iptv/iptv_scripts B
git commit -m "Initial commit"

#-- Work flow
cd A && echo changes > foo
cd ../B && echo changes > foo
git add . && git commit -m "Made some changes"
git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)

So git just told my new-to-git developer that his workdir is clean
because he happened to run it from super/B.  But if he ran it from
super/A (or super) it would tell him otherwise.

I guess what would help here is something like the opposite of 'git
status' showing the status of descendant submodules;  it would help if
it showed the status of sibling submodules and the superproject as
well.

>>>>  Or worse, their pull or push fails and
>>>> they can't see the problem for all the noise.  So they email it to me.
>>>
>>> We circumvent that by not pulling, but fetching and merging in the
>>> submodule first and after that in the superproject. You have much more
>>> control about what is going wrong where (and can have more
>>> git-experienced people help with - or even do - the merges).
>>
>> I do that, too, and I wish I didn't have to.  I wish I could safely
>> and sanely recover from a conflicted "git pull --recurse-submodules"
>> pull from the superproject.
>
> That's what my recursive checkout work is aiming at. Me thinks after
> that we will also need some good ideas on how to present and help
> solving submodule merge conflicts.
>
>> That is, I wish doing so were as
>> straightforward as recovering from the same condition would be if all
>> my code were in one repository instead of in submodules.
>>
>> Which is the gist -- I wish submodules did not make git more
>> complicated than it already is.
>
> I think we can make working with submodule much easier than it is
> now, the next step being updating all submodule work trees as git
> updates the superproject's work tree. Even though I suspect that in
> the long run submodules will always be a bit more complicated than
> having everything in one repository, I'm confident that will be by
> far outweighed by the advantages they bring.

I'm really looking forward to it.

Thanks,
Phil

^ permalink raw reply

* Rebase regression in v1.7.9?
From: Felipe Contreras @ 2012-01-31 22:56 UTC (permalink / raw)
  To: git

Hi,

Try the following steps:

% git checkout -b tmp v1.7.9
% git cherry-pick 6e1c9bb^2^
% git rebase -i --onto 6e1c9bb HEAD^
% git rebase --continue

The rebase will finish, but there will be a .git/CHERRY_PICK_HEAD file.

This doesn't happen if you run rebase without -i, or do rebase --skip instead.

IIRC correctly rebase --continue used to work fine.

Cheers.

-- 
Felipe Contreras

^ permalink raw reply

* Re: Alternates corruption issue
From: Jonathan Nieder @ 2012-01-31 22:59 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Richard Purdie, GIT Mailing-list, Hart, Darren,
	Ashfield, Bruce
In-Reply-To: <20120131224240.GA3844@sigill.intra.peff.net>

Jeff King wrote:
> On Tue, Jan 31, 2012 at 04:22:58PM -0600, Jonathan Nieder wrote:

>> I admit part of the reason I care is that just putting "" first would
>> probably taken care of the more important part of
>> <http://bugs.debian.org/399041>.
>
> Would that fix it? If I understand it, the repo in question is bare with
> a ".git" directory inside it.

The layout was foo/.git/.git.  The real repository was made with plain
"git init" or "git clone", and then "git svn init" or similar was run
from within .git, creating a .git subdirectory.  (Something more must
have happened, actually, since the tree was weirdly sparse:

	$ find .git/.git
	.git/.git
	.git/.git/svn
	.git/.git/svn/git-svn
	.git/.git/svn/git-svn/.rev_db

)

In the current scheme, to access such a broken repository remotely,
you have to use a URL ".../foo".  URLs pointing to foo/.git (like gitk
once used) end up rewritten as .git/.git.  Of course, your patch with
the is_git_directory() will fix this specific case. :)

Not a huge deal, especially since "git svn init" prints out where it
is writing these days.

^ 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