Git development
 help / color / mirror / Atom feed
* Re: dangling commits
From: Junio C Hamano @ 2006-01-15 22:55 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: git
In-Reply-To: <20060115221108.3ED2E352659@atlas.denx.de>

Wolfgang Denk <wd@denx.de> writes:

> Is ther eany way to clean up such a situation and really get  rid  of
> the  dangling  commits?  I understand that I'd first need some way to
> "unpack" the packs, but how to do this? 

The easiest is to repack into a single big ball of wax:

	$ git repack -a -d

If you know the pack the stale object is in, you can move it out
of objects/pack/ and repack only that one.

	$ mv .git/objects/packs/pack-$badone.{idx,pack} .
	$ git unpack-objects <pack-$badone.pack
        $ git repack

After you are done:

	$ git prune

^ permalink raw reply

* Re: dangling commits
From: Wolfgang Denk @ 2006-01-15 22:11 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vslrp2nw0.fsf@assigned-by-dhcp.cox.net>

In message <7vslrp2nw0.fsf@assigned-by-dhcp.cox.net> you wrote:
>
> Note that only because that is these dangling objects are packed
> in the past, and when fetching over http, packs are fetched as a
> whole.

Is ther eany way to clean up such a situation and really get  rid  of
the  dangling  commits?  I understand that I'd first need some way to
"unpack" the packs, but how to do this? 

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Heavier than air flying machines are impossible.
                    -- Lord Kelvin, President, Royal Society, c. 1895

^ permalink raw reply

* Re: dangling commits
From: Junio C Hamano @ 2006-01-15 21:15 UTC (permalink / raw)
  To: git
In-Reply-To: <dqedel$d0q$1@sea.gmane.org>

Nick Williams <njw@jarb.freeserve.co.uk> writes:

> Andreas Ericsson wrote:
>..
>> Nopes. One clones over http, so you'll get all objects in the object
>> database. The other clones over the far more clever git protocol
>> which calculates which objects you need. Obviously you don't need
>> dangling commits (and their related blobs), so there will be no such
>> items.

Note that only because that is these dangling objects are packed
in the past, and when fetching over http, packs are fetched as a
whole.

> So, is there any advantage of using http? Seems like git:// makes more
> sense.

As long as you can go native git:// protocol, I do not see much
reason to use http:// commit walkers.  OTOH, if you are
firewalled and your sysadmins do not let you pass 9418/tcp
outgoing, HTTP might be your only choice.

^ permalink raw reply

* Re: cvs-migration.txt
From: Junio C Hamano @ 2006-01-15 21:11 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: git
In-Reply-To: <20060115195804.GD3985@fieldses.org>

"J. Bruce Fields" <bfields@fieldses.org> writes:

> I find the following sentence from cvs-migration.txt slightly confusing:
>
> 	"The cut-off is date-based, so don't change the branches that
> 	were imported from CVS."
>
> I assume the branches referrred to are the target git branches, not the
> source CVS branches?  (And are date-based cut-offs really the essential
> reason for this restriction?)

Sorry, I cannot answer this one immediately without researching
myself; I do not use cvsimport.

The way I read the code agrees with you.  The date from the
topmost commit from each git branch is read, and used to limit
the changes we read from CVS into them.  The code reads from
"author date", which is technically incorrect, but what we are
saying here is that you should never commit into these branches
yourself and let cvsimport be the only one that touch them, so
using commiter date and author date would not make a difference.

^ permalink raw reply

* Re: dangling commits
From: Nick Williams @ 2006-01-15 21:37 UTC (permalink / raw)
  To: git
In-Reply-To: <43CAB6ED.3010703@op5.se>

Andreas Ericsson wrote:
> Nick Williams wrote:
> 
>> Hi, after cloning the git repo with
>>
>> cg-clone http://www.kernel.org/pub/scm/git/git.git git
>>
>> and then doing
>>
>> git-fsck-objects --full
>>
>> I get the following
>>
>> dangling commit 42db15448ea3c21ae458d5ea873157449042c07c
>> dangling commit 4d04a4022e7f9f3ada3a64e2010ce65e1fcc5c64
>> dangling commit a773f5bda1835d739ee7209589e137ddd7199142
>> dangling commit ceb90a511add3b362f1384aa6ea35370d12db315
>>
>> However if I do cg-clone git://git.kernel.org/pub/scm/git/git.git
>> there's no output from git-fsck --full
>>
>> git version = 1.1.GIT
>> cogito version = cogito-0.17pre.GIT
>>
>> did I do something wrong (again)?
>>
> 
> Nopes. One clones over http, so you'll get all objects in the object 
> database. The other clones over the far more clever git protocol which 
> calculates which objects you need. Obviously you don't need dangling 
> commits (and their related blobs), so there will be no such items.

OK, that makes sense - thanks for the explanation.

> 
> That there are on kernel.org at all is because Junio does rebases of the 
> pu branch and then pushes them out, which means that the objects from 
> the last rebase of that branch are left dangling.
> 

So, is there any advantage of using http? Seems like git:// makes more 
sense.

^ permalink raw reply

* Re: dangling commits
From: Andreas Ericsson @ 2006-01-15 20:56 UTC (permalink / raw)
  To: Nick Williams; +Cc: git
In-Reply-To: <dqebk9$75f$1@sea.gmane.org>

Nick Williams wrote:
> Hi, after cloning the git repo with
> 
> cg-clone http://www.kernel.org/pub/scm/git/git.git git
> 
> and then doing
> 
> git-fsck-objects --full
> 
> I get the following
> 
> dangling commit 42db15448ea3c21ae458d5ea873157449042c07c
> dangling commit 4d04a4022e7f9f3ada3a64e2010ce65e1fcc5c64
> dangling commit a773f5bda1835d739ee7209589e137ddd7199142
> dangling commit ceb90a511add3b362f1384aa6ea35370d12db315
> 
> However if I do cg-clone git://git.kernel.org/pub/scm/git/git.git
> there's no output from git-fsck --full
> 
> git version = 1.1.GIT
> cogito version = cogito-0.17pre.GIT
> 
> did I do something wrong (again)?
> 

Nopes. One clones over http, so you'll get all objects in the object 
database. The other clones over the far more clever git protocol which 
calculates which objects you need. Obviously you don't need dangling 
commits (and their related blobs), so there will be no such items.

That there are on kernel.org at all is because Junio does rebases of the 
pu branch and then pushes them out, which means that the objects from 
the last rebase of that branch are left dangling.

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

^ permalink raw reply

* Re: [PATCH] cvsimport: ease migration from CVSROOT/users format
From: Andreas Ericsson @ 2006-01-15 20:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqyd684p.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> 
>  * Andreas, I also tweaked the regexp to parse the native format
>    from /^([^ \t=]*)[ \t=]*([^<]*)(<.*$)\s*/
>    to /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/.  I think this tweak is
>    correct, but I would appreciate if you can proofread and ACK
>    on it.  The differences are:
> 

It looks correct and seems to do the trick.


>    - We grabbed <> pairs and stored in author_email (this is a
>      bugfix).
> 

gitk showed them as a single such even though theye were passed double. 
Perhaps some other tool stripped it along the way? Good catch anyways.

> +		}
> +		# NEEDSWORK: Maybe warn on unrecognized lines?
>  	}

I don't think so. I think it's safe to assume that people will check and 
double-check that everything's correct before removing the CVS repo, so 
it should be easy enough to redo the import (although possibly 
time-consuming).

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

^ permalink raw reply

* dangling commits
From: Nick Williams @ 2006-01-15 21:05 UTC (permalink / raw)
  To: git

Hi, after cloning the git repo with

cg-clone http://www.kernel.org/pub/scm/git/git.git git

and then doing

git-fsck-objects --full

I get the following

dangling commit 42db15448ea3c21ae458d5ea873157449042c07c
dangling commit 4d04a4022e7f9f3ada3a64e2010ce65e1fcc5c64
dangling commit a773f5bda1835d739ee7209589e137ddd7199142
dangling commit ceb90a511add3b362f1384aa6ea35370d12db315

However if I do cg-clone git://git.kernel.org/pub/scm/git/git.git
there's no output from git-fsck --full

git version = 1.1.GIT
cogito version = cogito-0.17pre.GIT

did I do something wrong (again)?

^ permalink raw reply

* Re: what exactly is git-tag looking for when you try to sign a tag?
From: Linus Torvalds @ 2006-01-15 20:02 UTC (permalink / raw)
  To: Alan Chandler; +Cc: git
In-Reply-To: <200601151932.05342.alan@chandlerfamily.org.uk>



On Sun, 15 Jan 2006, Alan Chandler wrote:
> 
> git-tag -s v1.0
> 
> and it complained that I don't have any secret key available.
> 
> What exactly is the process of making one available?

Do 

	gpg --list-secret-keys

to check what keys you have available to sign with.

Then, use

	git tag -u "key user name" v1.0

because what has _probably_ happened is that if you just use "-s" it will 
pick your "committer name" as the key identifier, and you probably made 
your keys using your real email or other identifier.

So "-u <username>" means the same thing as "-s", but with additionally 
specifying _which_ key it should use.

Alternatively, you should be able to just use "gpg --edit-key <keyname>" 
and then using "adduid" to add your git committer ID as a user of the key. 
At which point "git tag -s <tagname>" should just work, since gpg will be 
able to match up the keys automatically.

		Linus

^ permalink raw reply

* Re: Starting a new project remotely
From: Daniel Barkalow @ 2006-01-15 20:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd5it47lr.fsf@assigned-by-dhcp.cox.net>

On Sun, 15 Jan 2006, Junio C Hamano wrote:

> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > Is there something currently that acts like git-clone, except that it sets 
> > up automatic connections in the opposite direction? That is, you run it in 
> > a repository with no origin, and it pushes the data to the specified 
> > location (which probably needs to be set up already as an empty 
> > repository) and sets the local side's origin remote to the location given.
> 
> The "git push" command allows you to push into an empty or even
> unrelated destination, but I do think there no wrapper that
> creates remotes/ file.  BTW, calling that "origin" is probably
> confusing.  In the scenario you outlined, your local side is the
> source and the remote is the sink.

My general pattern is that I have an "origin" repository, which is public 
and central. I do work in various other repositories, and push the results 
to origin when I finish them. I create these with "git clone", so the 
central point is called "origin" in each clone.

The odd case is when I start out; I have a repository with the initial 
commit, and "origin" is blank. The desired result is that the central 
location gets this commit, and the repository I'm starting from becomes 
identical to any clone of the central location.

I don't create the initial commit in the central location because there's 
no working tree there, and it's a pain to prepare a commit without one. I 
suppose the alternative is to support cloning a blank repository, so I 
could prepare the initial commit just like any later one.

Incidentally, I think it would be useful to have a script that creates a 
remotes/ file given a command line like push or pull. Then you could use 
"git pull" with a long command line until you were happy with the 
behavior, and then make a shortcut out of it. It'd also be nice to have 
the command list the remotes for you as well. If anyone's in the mood for 
scripting and wants something to work on...

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* cvs-migration.txt
From: J. Bruce Fields @ 2006-01-15 19:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

I find the following sentence from cvs-migration.txt slightly confusing:

	"The cut-off is date-based, so don't change the branches that
	were imported from CVS."

I assume the branches referrred to are the target git branches, not the
source CVS branches?  (And are date-based cut-offs really the essential
reason for this restriction?)

--b.

^ permalink raw reply

* what exactly is git-tag looking for when you try to sign a tag?
From: Alan Chandler @ 2006-01-15 19:32 UTC (permalink / raw)
  To: git

Since I reached my first release of my software this morning, I though I would 
try and get a bit more formal with things and attempted to sign the tag

Although I had tried gpg several years ago, I didn't seem to have any keys in 
my keyring, so I just generated a new one with 

gpg --gen-key

You can see a key listed with you check for secret keys

with gpg -K

but then I tried to generate a tag with 

git-tag -s v1.0

and it complained that I don't have any secret key available.

What exactly is the process of making one available?
-- 
Alan Chandler
http://www.chandlerfamily.org.uk
Open Source. It's the difference between trust and antitrust.

^ permalink raw reply

* Re: Starting a new project remotely
From: Junio C Hamano @ 2006-01-15 19:24 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0601151323320.25300@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> Is there something currently that acts like git-clone, except that it sets 
> up automatic connections in the opposite direction? That is, you run it in 
> a repository with no origin, and it pushes the data to the specified 
> location (which probably needs to be set up already as an empty 
> repository) and sets the local side's origin remote to the location given.

The "git push" command allows you to push into an empty or even
unrelated destination, but I do think there no wrapper that
creates remotes/ file.  BTW, calling that "origin" is probably
confusing.  In the scenario you outlined, your local side is the
source and the remote is the sink.

FYI, here is what I have in my remotes/ko file to interact with
my kernel.org repository (the one that is mirrored out to the
public machines):

        URL: zzz.kernel.org:/pub/scm/git/git.git/
        Push: master
        Push: +pu
        Push: maint
        Pull: master:refs/tags/ko-master
        Pull: +pu:refs/tags/ko-pu
        Pull: maint:refs/tags/ko-maint

and with this, I first run

	$ git fetch ko
	$ git show-branch master ko-master

to make sure I am not rewinding what I have already pushed out
by mistake, and then

	$ git push ko
        $ git push --tags ko ;# if I added a new tag

^ permalink raw reply

* Re: [RFC][PATCH] Cogito support for simple subprojects
From: Junio C Hamano @ 2006-01-15 19:15 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git, Simon Richter
In-Reply-To: <20060115150721.GE28365@pasky.or.cz>

Petr Baudis <pasky@suse.cz> writes:

> ... I currently don't
> think a recursive cg-merge is a particularily good idea, for one.
> I think the good default is to make all read-only commands by default
> recursive and all modifying commands by default non-recursive. (And
> it might be useful to be able to mark some subprojects read-only.)

All sounds sane and simple.  Good job!

Especially because this does not even try to let the project
express its version dependencies on its subprojects, I like it
for its simplicity (which makes it very easy to explain, to my
mind that is the biggest plus).  However, I fear that others
might complain to say that the contained things do not deserve
to be called "subprojects" if there is no version linkage [*1*].

I think something like this is greatly helpful for people (like
me) as "an end user who builds from source out of SCM not from
tarballs."

If you go this route, one minor concern is what the format of
the $GIT_DIR/subproject should be (and if they do not deserve to
be called "subproject" then what the name of the file be),
because this may likely be a "nice if they were compatible" item
across Porcelains.  The list of names separated with LF has two
very big pluses:

 - it is certainly the easiest to parse.

 - it can readily be used as --exclude-from file, as long as you
   do not care about another directory with a same name
   somewhere other than the subproject itself.

Even if the limitation to the latter becomes a real issue, a
separate exclude-from file could easily be generated on the fly
(prefix them with '/' to force "not anywhere in the subtree but
only here" matching, perhaps with escaping shell glob pattern
while you are at it), which does not sound so bad.


[Footnote]

*1* I do not personally care about version linkage; this is me
being lazy to avoid core side support ;-).  Yesterday I was
mucking with rev-list code to see how gitlink and/or bind commit
would affect what it needs to do (especially wrt its --objects
flag), and I did not like the potential code impact I saw there.

^ permalink raw reply

* Starting a new project remotely
From: Daniel Barkalow @ 2006-01-15 18:45 UTC (permalink / raw)
  To: git

Is there something currently that acts like git-clone, except that it sets 
up automatic connections in the opposite direction? That is, you run it in 
a repository with no origin, and it pushes the data to the specified 
location (which probably needs to be set up already as an empty 
repository) and sets the local side's origin remote to the location given.

This recipe seems to work:

 git branch origin master
 echo >$GIT_DIR/remotes/origin \
"URL: $repo
Pull: $head_points_at:$origin"
 git push origin $origin:refs/heads/$head_points_at

(where $origin is "origin", $head_points_at is "master", $repo is the 
target repository, "origin" is the remote you want to create, and "master" 
is the head that currently holds the commit you want to push)

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [RFC][PATCH] Cogito support for simple subprojects
From: Linus Torvalds @ 2006-01-15 17:38 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Simon Richter, git
In-Reply-To: <20060115150721.GE28365@pasky.or.cz>



On Sun, 15 Jan 2006, Petr Baudis wrote:
> 
>   I've tried to take a different approach - KISS and don't make the
> subprojects part of the git-tracked tree but a thing purely local to
> your particular checkout. Subprojects are simply listed in
> .git/subprojects and various commands are called recursively on them.

This seems very sane. Goodie.

		Linus

^ permalink raw reply

* [RFC][PATCH] Cogito support for simple subprojects
From: Petr Baudis @ 2006-01-15 15:07 UTC (permalink / raw)
  To: Simon Richter; +Cc: git
In-Reply-To: <43C52B1F.8020706@hogyros.de>

  Hello,

  I've tried to take a different approach - KISS and don't make the
subprojects part of the git-tracked tree but a thing purely local to
your particular checkout. Subprojects are simply listed in
.git/subprojects and various commands are called recursively on them.

  - No auto-cloning of subprojects is possible.
  - Switching between branches and merging is troublesome in case the
    required subprojects arrangement changes inbetween. Now, this is
    a matter of taste - I don't see this as a huge problem since you
    can make special provisions for that and this should be going to be
    so rare that it's not worth optimizing for in my eyes.
  + It's simple.
  + It's flexible. You can have _optional_ subprojects - IIRC e.g.
    mplayer can use ffmpeg if it's checked out as a subproject but
    will use own copy if it's not there. You can clone subprojects
    based e.g. on selected features before compilation. If you do so,
    your GIT won't bother you with uncommitted local changes, and you
    will not have to filter this out from any other changes you are
    going to commit.

  The main goal of this is simply to be able to check out bunch of
stuff to subdirectories and make cg-update update all of it, without
any special scripts. ;-)

  This patch is just trivial proof-of-concept thing which makes only
cg-update and cg-fetch aware of the subprojects; many commands still
need to be taught about subprojects but some don't - I currently don't
think a recursive cg-merge is a particularily good idea, for one.
I think the good default is to make all read-only commands by default
recursive and all modifying commands by default non-recursive. (And
it might be useful to be able to mark some subprojects read-only.)

  How to create a subproject? Simply cg-clone inside a working copy,
it will register it automagically. So far there are no tools to further
maintain the subprojects, though, therefore a mv or rm needs to be
followed by an appropriate modification of parent .git/subprojects.


  This is not committed yet - I'm curious about your opinions.

diff --git a/TODO b/TODO
index 0658b39..29daf30 100644
--- a/TODO
+++ b/TODO
@@ -90,23 +90,13 @@ cg-*patch should be pre-1.0.)
 
 * cg-Xfetchprogress showing smooth progress for packfiles
 
+* Enhance subprojects notion
+	So far the subprojects support is trivial and prone to user error.
+	E.g. cg-add should check if it doesn't poke into a subproject,
+	cg-status should list subprojects, etc.
 
-Post 1.0:
-
-* Subprojects
-	Support a GIT project inside a GIT project:
 
-		x/.git
-		x/foo/bar/.git
-		x/foo/bar/baz/.git
-		x/quux/zot/.git
-
-	That means cg-update working recursively and cg-add'n'stuff
-	checking if there isn't another .git along the path of its
-	argument.
-
-	Needs more thought, especially wrt. fetching and merging
-	recursive semantics.
+Post 1.0:
 
 * Comfortable cg-log
 	Probably make it a real terminal application, not just less
diff --git a/cg-Xlib b/cg-Xlib
index 46a8a73..6e6265e 100755
--- a/cg-Xlib
+++ b/cg-Xlib
@@ -197,6 +197,10 @@ list_untracked_files()
 		if [ -f "$EXCLUDEFILE" ]; then
 			EXCLUDE[${#EXCLUDE[@]}]="--exclude-from=$EXCLUDEFILE"
 		fi
+		EXCLUDEFILE="$_git/subprojects"
+		if [ -f "$EXCLUDEFILE" ]; then
+			EXCLUDE[${#EXCLUDE[@]}]="--exclude-from=$EXCLUDEFILE"
+		fi
 		# This is just for compatibility (2005-09-16).
 		# To be removed later.
 		EXCLUDEFILE="$_git/exclude"
@@ -209,6 +213,29 @@ list_untracked_files()
 	git-ls-files -z --others "${EXCLUDE[@]}"
 }
 
+# Usage: subprojects_recurse ACTIONNAME COMMAND...
+# Run command recursively on subprojects, displaying warning using the
+# ACTIONNAME string in case any of them failed.
+subprojects_recurse()
+{
+	[ -s "$_git/subprojects" ] || return 0
+	local failures=0 subprj= actionname="$1" s=
+	local Actionname="$(echo "$actionname" | perl -pe '$_=ucfirst')"
+	shift
+	while IFS= read -r subprj; do
+		echo "Running $actionname in $subprj..." >&2
+		if ( cd "$subprj" && "$@" ); then
+			echo "$Actionname in $subprj succeeded." >&2
+		else
+			echo "$Actionname in $subprj failed!" >&2
+			failures=$(($failures+1))
+		fi
+	done <"$_git/subprojects"
+	local s=; if [ $failures -gt 1 ]; then s=s; fi
+	[ $failures -gt 0 ] && echo "Warning: $failures subproject $actionname$s failed" >&2
+	return $failures
+}
+
 # Usage: showdate SECONDS TIMEZONE [FORMAT]
 # Display date nicely based on how GIT stores it.
 # Save the date to $_showdate
diff --git a/cg-clone b/cg-clone
index f86a548..dfb6dc8 100755
--- a/cg-clone
+++ b/cg-clone
@@ -11,6 +11,15 @@
 # parameter is omitted, the basename of the source repository is used as the
 # destination.
 #
+# If you are cloning inside another working tree, you are automatically
+# establishing a subproject - that means that when you will update the
+# parent project, this project will be auto-updated as well, and in the
+# future, certain other operations may also recurse to subprojects. Use the
+# -P option to prevent this from becoming a subproject. Also please note
+# that the subprojects support is preliminary and subject to change. If you
+# remove the subproject later, you must also remove the corresponding entry
+# in '.git/subprojects' for now.
+#
 # OPTIONS
 # -------
 # -l::	Symlink the object database when cloning locally
@@ -24,20 +33,28 @@
 #	Note that you MUST NOT prune repository containing a symlink
 #	or being symlinked to.
 #
+# -P::	Prevent this from becoming a subproject
+#	If this option is passed, cg-clone will never create a subproject
+#	even if called inside working tree of another project.
+#
 # -s::	Clone into the current directory
 #	Clone in the current directory instead of creating a new one.
 #	Specifying both -s and a destination directory makes no sense.
+#	This also implies -P.
 
-USAGE="cg-clone [-l] [-s] LOCATION [DESTDIR]"
+USAGE="cg-clone [-l] [-P] [-s] LOCATION [DESTDIR]"
 _git_repo_unneeded=1
 
 . ${COGITO_LIB}cg-Xlib || exit 1
 
 same_dir=
 symlink=
+may_subproject=1
 while optparse; do
 	if optparse -l; then
 		symlink=1
+	elif optparse -P; then
+		may_subproject=
 	elif optparse -s; then
 		same_dir=1
 	else
@@ -65,7 +82,13 @@ else
 	location="$location"
 fi
 
+parentprj=
+parentpath=
 if [ ! "$same_dir" ]; then
+	if [ "$may_subproject" ]; then
+		parentprj="$(git-rev-parse --git-dir 2>/dev/null)"
+		parentpath="$(git-rev-parse --show-prefix 2>/dev/null)$dir"
+	fi
 	[ -e "$dir" ] && die "$dir/ already exists"
 	mkdir "$dir" || exit $?
 	cd "$dir" || exit $?
@@ -94,4 +117,14 @@ cp "$_git/refs/heads/origin" "$_git/refs
 	git-update-index --refresh ||
 	exit 1
 
+if [ "$parentprj" ]; then
+	cd ..
+	parentroot="${parentprj%.git}"
+	if [ -z "$parentroot" ]; then
+		parentroot="$(pwd)"
+	fi
+	echo "Registering as a subproject of $parentroot..."
+	echo "$parentpath" >>"$parentprj"/subprojects
+fi
+
 echo "Cloned to $dir/ (origin $location available as branch \"origin\")"
diff --git a/cg-fetch b/cg-fetch
index c3dfb81..9d44d9f 100755
--- a/cg-fetch
+++ b/cg-fetch
@@ -28,6 +28,10 @@
 # -f:: Force the complete fetch even if the heads are the same.
 #	Force the complete fetch even if the heads are the same.
 #
+# -R:: Do not recurse to subprojects
+#	Do not recursively fetch the subprojects (see the `cg-clone`
+#	documentation for more information).
+#
 # -v:: Enable verbosity
 #	Display more verbose output - most notably list all the files
 #	touched by the fetched changes.
@@ -53,7 +57,7 @@
 #	won't unpack the transferred pack.
 
 
-USAGE="cg-fetch [-f] [-v] [BRANCH_NAME]"
+USAGE="cg-fetch [-f] [-R] [-v] [BRANCH_NAME]"
 
 . ${COGITO_LIB}cg-Xlib || exit 1
 deprecated_alias cg-fetch cg-pull
@@ -234,12 +238,15 @@ fetch_tags()
 
 
 recovery=
+recurse=1
 verbose=
 while optparse; do
 	if optparse -f; then
 		# When forcing, let the fetch tools make more extensive
 		# walk over the dependency tree with --recover.
 		recovery=--recover
+	elif optparse -R; then
+		recurse=
 	elif optparse -v; then
 		verbose=1
 	else
@@ -248,9 +255,10 @@ while optparse; do
 done
 
 name="${ARGS[0]}"
-
 [ "$name" ] || { [ -s "$_git/branches/origin" ] && name=origin; }
+[ "$recurse" ] && subprojects_recurse "fetch" cg-fetch $recovery $verbose "$name"
 [ "$name" ] || die "where to fetch from?"
+
 uri=$(cat "$_git/branches/$name" 2>/dev/null) || die "unknown branch: $name"
 
 rembranch=
diff --git a/cg-update b/cg-update
index 1d6e0a0..1b21338 100755
--- a/cg-update
+++ b/cg-update
@@ -25,23 +25,30 @@
 # -f:: Force the complete fetch even if the heads are the same.
 #	Force the complete fetch even if the heads are the same.
 #
+# -R:: Do not recurse to subprojects
+#	Do not recursively update the subprojects (see the `cg-clone`
+#	documentation for more information).
+#
 # --squash:: Use "squash" merge to record pending commits as a single merge commit
 #	"Squash" merge - condense all the to-be-merged commits to a single
 #	merge commit. This is not to be used lightly; see the cg-merge
 #	documenation for further details.
 
-USAGE="cg-update [-f] [--squash] [BRANCH_NAME]"
+USAGE="cg-update [-f] [-R] [--squash] [BRANCH_NAME]"
 _git_requires_root=1
 
 . ${COGITO_LIB}cg-Xlib || exit 1
 
 force=
 squash=
+recurse=1
 while optparse; do
 	if optparse -f; then
 		force=-f
 	elif optparse --squash; then
 		squash=--squash
+	elif optparse -R; then
+		recurse=
 	else
 		optfail
 	fi
@@ -49,13 +56,14 @@ done
 
 name="${ARGS[0]}"
 [ "$name" ] || { [ -s "$_git/branches/origin" ] && name=origin; }
+[ "$recurse" ] && subprojects_recurse "update" cg-update $force $squash "$name"
 [ "$name" ] || die "where to update from?"
 
 # cg-merge can do better decision about fast-forwarding if it sees this.
 [ -s "$_git/refs/heads/$name" ] && export _cg_orig_head="$(cat "$_git/refs/heads/$name")"
 
 if [ -s "$_git/branches/$name" ]; then
-	cg-fetch $force "$name" || exit 1
+	cg-fetch -R $force "$name" || exit 1
 else
 	echo "Updating from a local branch."
 fi
diff --git a/t/t9215-update-recursive.sh b/t/t9215-update-recursive.sh
new file mode 100755
index 0000000..d0e27a4
--- /dev/null
+++ b/t/t9215-update-recursive.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2005 Petr Baudis
+#
+test_description="Tests recursive cg-update functionality
+
+Create a subproject and then try to cg-update."
+
+. ./test-lib.sh
+
+mkdir prj1
+echo file >prj1/file
+test_expect_success 'initialize project 1' \
+	"(cd prj1 && cg-init -I && cg-add file && cg-commit -C -m\"Initial commit\")"
+
+mkdir prj2
+echo file >prj2/FILE
+test_expect_success 'initialize project 2' \
+	"(cd prj2 && cg-init -I && cg-add FILE && cg-commit -C -m\"Initial commit\")"
+
+test_expect_success 'clone project 1' \
+	"cg-clone prj1 clone"
+test_expect_success 'clone project 2 as subproject of project 1' \
+	"(cd clone && cg-clone ../prj2)"
+
+test_expect_success 'commit to project 1' \
+	"(cd prj1 && echo foo >>file && cg-commit -m\"Commit in project 1\")"
+test_expect_success 'commit to project 2' \
+	"(cd prj2 && echo bar >>FILE && cg-commit -m\"Commit in project 2\")"
+
+test_expect_success 'non-recursive update' \
+	"(cd clone && cg-update -R)"
+test_expect_success 'check if the prj1 head was updated in clone' \
+	"(cmp prj1/.git/refs/heads/master clone/.git/refs/heads/master)"
+test_expect_success 'check if the prj1 working copy was updated in clone' \
+	"(cmp prj1/file clone/file)"
+test_expect_failure 'check if the prj2 head was not updated in clone' \
+	"(cmp prj2/.git/refs/heads/master clone/prj2/.git/refs/heads/origin)"
+
+test_expect_success 'commit to project 1' \
+	"(cd prj1 && echo baz >>file && cg-commit -m\"Commit in project 1\")"
+
+test_expect_success 'recursive update' \
+	"(cd clone && cg-update)"
+test_expect_success 'check if the prj1 head was updated in clone' \
+	"(cmp prj1/.git/refs/heads/master clone/.git/refs/heads/master)"
+test_expect_success 'check if the prj1 working copy was updated in clone' \
+	"(cmp prj1/file clone/file)"
+test_expect_success 'check if the prj2 head was updated in clone' \
+	"(cmp prj2/.git/refs/heads/master clone/prj2/.git/refs/heads/master)"
+test_expect_success 'check if the prj2 working copy was updated in clone' \
+	"(cmp prj2/FILE clone/prj2/FILE)"
+
+test_done


-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Of the 3 great composers Mozart tells us what it's like to be human,
Beethoven tells us what it's like to be Beethoven and Bach tells us
what it's like to be the universe.  -- Douglas Adams

^ permalink raw reply related

* [PATCH] cvsimport: ease migration from CVSROOT/users format
From: Junio C Hamano @ 2006-01-15 11:30 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git

This fixes a minor bug, which caused the author email to be
doubly enclosed in a <> pair (the code gave enclosing <> to
GIT_AUTHOR_EMAIL and GIT_COMMITTER_EMAIL environment variable).

The read_author_info() subroutine is taught to also understand
the user list in CVSROOT/users format.  This is primarily done
to ease migration for CVS users, who can use the -A option
to read from existing CVSROOT/users file.  write_author_info()
always writes in the git-cvsimport's native format ('='
delimited and value without quotes).

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 * Andreas, I also tweaked the regexp to parse the native format
   from /^([^ \t=]*)[ \t=]*([^<]*)(<.*$)\s*/
   to /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/.  I think this tweak is
   correct, but I would appreciate if you can proofread and ACK
   on it.  The differences are:

   - We did not require '=' anywhere, but accepted "= = =".
   - We had funny '$' in the middle; probably a typo. 
   - We first slurped author name with trailing whitespaces, only 
     to strip that separately in later steps.
   - We grabbed <> pairs and stored in author_email (this is a
     bugfix).

 git-cvsimport.perl |   29 ++++++++++++++++++++---------
 1 files changed, 20 insertions(+), 9 deletions(-)

1b23ed3d1f9f3d83ea8b94ebc37c99e0ca32a09b
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 8d493c2..3ddbdfa 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -48,16 +48,28 @@ sub read_author_info($) {
 	open my $f, '<', "$file" or die("Failed to open $file: $!\n");
 
 	while (<$f>) {
-		chomp;
-		# Expected format is this;
+		# Expected format is this:
 		#   exon=Andreas Ericsson <ae@op5.se>
-		if (m/^([^ \t=]*)[ \t=]*([^<]*)(<.*$)\s*/) {
+		if (m/^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/) {
 			$user = $1;
-			$conv_author_name{$1} = $2;
-			$conv_author_email{$1} = $3;
-			# strip trailing whitespace from author name
-			$conv_author_name{$1} =~ s/\s*$//;
+			$conv_author_name{$user} = $2;
+			$conv_author_email{$user} = $3;
 		}
+		# However, we also read from CVSROOT/users format
+		# to ease migration.
+		elsif (/^(\w+):(['"]?)(.+?)\2\s*$/) {
+			my $mapped;
+			($user, $mapped) = ($1, $3);
+			if ($mapped =~ /^\s*(.*?)\s*<(.*)>\s*$/) {
+				$conv_author_name{$user} = $1;
+				$conv_author_email{$user} = $2;
+			}
+			elsif ($mapped =~ /^<?(.*)>?$/) {
+				$conv_author_name{$user} = $user;
+				$conv_author_email{$user} = $1;
+			}
+		}
+		# NEEDSWORK: Maybe warn on unrecognized lines?
 	}
 	close ($f);
 }
@@ -68,8 +80,7 @@ sub write_author_info($) {
 	  die("Failed to open $file for writing: $!");
 
 	foreach (keys %conv_author_name) {
-		print $f "$_=" . $conv_author_name{$_} .
-		  " " . $conv_author_email{$_} . "\n";
+		print $f "$_=$conv_author_name{$_} <$conv_author_email{$_}>\n";
 	}
 	close ($f);
 }
-- 
1.1.2-gd425

^ permalink raw reply related

* Re: My first git success [not quite]
From: Junio C Hamano @ 2006-01-15 10:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: walt, git
In-Reply-To: <Pine.LNX.4.64.0601141117120.13339@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> Now, Junio has patches (maybe they even got merged in mainline) to relax 
> the "exactly the same" rule a bit, and instead try to merge any dirty 
> state into the branch you're switching to. Conceptually nothing changed: 
> dirty state is branchless, so when you switch to another branch, the dirty 
> state follows you. 

FYI, I pushed this out, along with some other changes.

 * checkout -m can be used to merge while switching branches.
 * format-patch now always does --mbox and shows RFC2822 Date.
 * clone --naked can be used for creating "project.git" style repository.
 * octopus allows hand resolving in limited form.
 * show-branch user interface updates.
 * push --tags to push all tags; it does not fall back on "matching" refs.

^ permalink raw reply

* Re: Question on empty commit
From: Junio C Hamano @ 2006-01-15  9:48 UTC (permalink / raw)
  To: ltuikov; +Cc: git
In-Reply-To: <20060114021800.4688.qmail@web31803.mail.mud.yahoo.com>

Luben Tuikov <ltuikov@yahoo.com> writes:

> Now the last merge introduced an empty commit, since
> tree A and tree B had been in sync (only local and
> remote trunk had been out of sync).  While it was expected
> that no commit would be introduced since they were in sync.
>
> Was the empty commit correct behavior?

I do not quite follow you, but immediately before the "empty
commit" (I presume you mean the last "git merge" that merges
treeA head in treeB), you say "the treeA and treeB had been in
sync".  What do you exactly mean?  The tree object in the head
commits in treeA branch and treeB branch were identical?

If that is the case, the commit being empty is the correct
behaviour, because there is no difference in the set of files
introduced by that commit.  And the commit being made is also
the correct behaviour, because those two branches have different
development history, and the commit is what binds them together.

^ permalink raw reply

* Re: [PATCH] cg-seek should not complain if run twice
From: Pavel Roskin @ 2006-01-15  6:03 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20060114233037.GA28365@pasky.or.cz>

Hello, Petr!

Quoting Petr Baudis <pasky@suse.cz>:

> It seems cleaner to just make cg-seek fail with a sensible error message
> if it's already unseeked.

I don't like this.  What if "cvs up -A" would fail if run twice?  What if
cg-clean would fail if there was nothing to clean?  What if sync would fail if
it didn't cause a single disk write?  Idempotent operations are easier to work
with.  Please see http://en.wikipedia.org/wiki/Idempotent_(software)

I could make an exception for the case when the command invocation indicates
that the user is unaware of something, and that it would endanger the user's
data.  But it's not the case for cg-seek without arguments on non-seeked
repository.  The intention is clear, and the knowledge of the current state of
the repository doesn't matter, since there will be no merge or something.

--
Regards,
Pavel Roskin

^ permalink raw reply

* Re: www.kernel.org/git is slow...
From: Josh Boyer @ 2006-01-15  1:57 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: ftpadmin, git
In-Reply-To: <20060114203654.GA10314@mars.ravnborg.org>

On 1/14/06, Sam Ravnborg <sam@ravnborg.org> wrote:
> During the last couple of days http://www.kernel.org/git has
> been very slow.

I've noticed this too, so it's not just you.  Just another data point.

josh

^ permalink raw reply

* Re: RFC: Subprojects
From: Tom Prince @ 2006-01-15  1:55 UTC (permalink / raw)
  To: git
In-Reply-To: <7v4q4671tg.fsf@assigned-by-dhcp.cox.net>

On Sat, Jan 14, 2006 at 04:49:15PM -0800, Junio C Hamano wrote:
> Martin Langhoff <martin.langhoff@gmail.com> writes:
> 
> > I am with gitzilla on this one. Let the projects have their own
> > bootstraping mechanisms, using make, ant or whatever catches their
> > fancy. One of the great things about git is that it doesn't assume
> > that it's being used by all the projects in the world -- thanks to
> > Linus' disregard for arbitrary metadata and to your git-cherry
> > implementation, it's all about the content -- and so it interoperates
> > great with Arch, SVN, CVS, etc.
> 
> 
> I hope this settles this issue and nobody would bring up "Wee
> want subprojects" ever again ;-).
> 

But since we can import everything into a GIT repository, and have
(some) tools for pushing changes back, we can pretend that it is being
used for every project in the world.

  Tom

^ permalink raw reply

* Re: RFC: Subprojects
From: Junio C Hamano @ 2006-01-15  1:01 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <7vek3ah8f9.fsf@assigned-by-dhcp.cox.net>

Continuing with the "union" approach...

Junio C Hamano <junkio@cox.net> writes:

>  - append the tree object in "kernel" commit object to the
>    current index, rerooted at linux-2.6/; similar for "gcc" at
>    gcc-4.0/. We may need a new mode and option for read-tree for
>    this, or we may not.  Internally this step would be scripted
>    in "git bind" wrapper like this:
>
> 	git read-tree --bind --prefix=linux-2.6 kernel
> 	git read-tree --bind --prefix=gcc-4.0 gcc
>
>    and would result in an index file that has these trees
>    "mounted" at specified places...

Clarification.  By "mounted", I mean 'without affecting existing
index entries, create index entries from the tree, with all the
paths have "linux-2.6/" prefixed to them'.

>  - record the branch name vs subproject directory binding in
>    $GIT_DIR/ somewhere, say $GIT_DIR/mtab ;-).
>
> 	$ cat .git/mtab
> 	kernel	linux-2.6
>       gcc	gcc-4.0

I now realize this needs to be something like:

	master	kernel=linux-2.6/ gcc=gcc-4.0/

that is, "when on branch master, bind these two heads at these
directories", to allow switching to another branch and switching
back to this branch.  And the file should probably be called
$GIT_DIR/modules, to parallel CVSROOT/modules file.

>	$ git cat-file commit HEAD
>       tree e9de76f2e141824439caa00a65e3b91d05d125c9
>       parent bfca932434cc65e7aa90794e7c4d66f75d00b16a
>       bind a8fe7257b8427d31cfcca0aa336335bb43689fc9 linux-2.6
>       bind b3b2df23226634f42c9646bd7961fbea8b00f914 gcc-4.0
>       author Junio C Hamano <junkio@cox.net> 1137205528 -0800
>       committer Junio C Hamano <junkio@cox.net> 1137205528 -0800
>
>	Bind kernel and gcc into us.
>...
> Now I have to think about clones and merges but this is getting
> too long so I'll leave it to a separate message.

The core-level cloning would just "clone" the objects, treating
"bind" line in the commit just like "parent" to pull necessary
objects.

Checkout would involve the usual read-tree -u which extracts the
tree (which is the whole tree, with files of the subprojects in
it), and notices "bind" lines are there but there are no
matching $GIT_DIR/modules entries for those directories.
Probably it would create $GIT_DIR/refs/heads/bind/a8fe725 for
the linux-2.6 subproject (what the original committer called
"kernel" branch), and similarly for the gcc-4.0 subproject, add
an appropriate entry to $GIT_DIR/modules file.  The user would
then rename the branch names and optionally arrange remotes/
files to update the bound branches appropriately:

	$ mv .git/refs/heads/bind/a8fe725 .git/refs/heads/kernel

Now, let's say this "master" branch is checked out, and somehow
the "kernel" branch gets updated.  That is, the commit recorded
on the "bind" line of the HEAD commit does not match the branch
head that can be found out via $GIT_DIR/modules file.  This will
not happen if you are committing into the "master" branch using
the "commit to subprojects and then to the toplevel project"
mechanism yourself, but it would happen if the "kernel" branch
was moved by "git fetch" fast-forwarding, or if you switched to
the "kernel" branch (which would essentially remove everything
from your tree, and checkout the kernel source at the root
level, not in linux-2.6/ subdirectory), did an upstream merge
yourself, and switched back to the "master" branch.

To keep the problem simpler, let's say we only deal with the
case where "kernel" branch head is a fast-forward of what is on
"bind" in the HEAD commit of "master" branch.  Then "checkout"
needs to notice it, and check out the subdirectory from the
"kernel" branch head (*not* using the object name on "bind"
line).

So the outline of the "checkout" would be like this:

 * Read commit object from new HEAD.

 * For each "bind" line:

   If the subdirectory does not have a corresponding branch,
   create one in $GIT_DIR/refs/heads/bind/; record it in
   $GIT_DIR/modules for the new branch (otherwise leave branch
   as is).

   Make sure the commit recorded on "bind" line is an ancestor
   of the branch head.  Otherwise it is an error and checkout is
   prevented until the "kernel" branch is resolved to be a
   descendant of it.

   Run "read-tree -u --prefix=" to merge in the subtree into the
   index, and update the working tree.

At this point, there may be mismatch between the tree in the
HEAD and the working tree files and index, when subproject
commit recorded on the "bind" line is different from the
corresponding subproject branch head, and "git diff" would show
it.  When making a commit here, the "subproject and then
toplevel" commit scheme I described earlier would record the
current "kernel" branch head on the "bind" line in the new
commit, along with the tree object that contains the tree from
"kernel" branch head commit as a subtree.


About "merge", we should be able to do this:

	$ git checkout master ;# the whole mess
        $ git pull -b kernel git://..torvalds/linux-2.6.git/

that is, 'pull from this URL but into "kernel" branch not to the
current branch'.  Independent of this "subprojects" topic,
merging in a separate temporary directory into non-current
branch is something we have talked about some time ago, and in
this particular case, instead of using a throw-away temporary
directory, we have a pre-made directory to do the merge already,
so let's say that is solved elsewhere first.  Once we have that,
the above "checkout" would be able to integrate the result into
the "master" project.

^ permalink raw reply

* Re: RFC: Subprojects
From: Junio C Hamano @ 2006-01-15  0:49 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: gitzilla, git, Johannes Schindelin, Simon Richter
In-Reply-To: <46a038f90601141628n2ec32e8fy7fc23d8d7884c0f2@mail.gmail.com>

Martin Langhoff <martin.langhoff@gmail.com> writes:

> I am with gitzilla on this one. Let the projects have their own
> bootstraping mechanisms, using make, ant or whatever catches their
> fancy. One of the great things about git is that it doesn't assume
> that it's being used by all the projects in the world -- thanks to
> Linus' disregard for arbitrary metadata and to your git-cherry
> implementation, it's all about the content -- and so it interoperates
> great with Arch, SVN, CVS, etc.

I had the exactly the same reaction when I saw the project
bundling facility of Arch (tla 1.0 -- I do not know what the
newer versions use).  It probably was a great way to tie two or
more Arch projects together, but it would quickly become less
useful once the component project is outside Arch space and the
toplevel project would end up with doing some Makefile targets
like ALASCM described.

I hope this settles this issue and nobody would bring up "Wee
want subprojects" ever again ;-).

^ 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