Git development
 help / color / mirror / Atom feed
* Re: git cherry unkillable
From: sean @ 2006-01-22 14:51 UTC (permalink / raw)
  To: sean; +Cc: arvidjaar, git
In-Reply-To: <BAYC1-PASMTP10435A067270A659801A48AE110@CEZ.ICE>

On Sun, 22 Jan 2006 06:39:04 -0500
sean <seanlkml@sympatico.ca> wrote:

> The attached patch works for me but i'm concerned about it a bit.  

Below is a better version that doesn't obscure the proper exit value in the normal
case and exits with 1 if interrupted by the user.   It also ensures that the cleanup
isn't executed twice when the script is interrupted.

However, for Bash (at least) none of this is necessary; all the traps could just 
be changed to only trap 0 and the cleanup will be executed for all cases.   However,
I don't know how compatible that is with other shells.   If other shells behave
the same, the best fix is just to strip the 1,2,3 and 15 from each of the existing
trap lines and not bother with the patch given below.

Sean


diff --git a/git-cherry.sh b/git-cherry.sh
index 1a62320..0b2ef1f 100755
--- a/git-cherry.sh
+++ b/git-cherry.sh
@@ -49,7 +49,8 @@ ours=`git-rev-list $ours ^$limit` || exi
 tmp=.cherry-tmp$$
 patch=$tmp-patch
 mkdir $patch
-trap "rm -rf $tmp-*" 0 1 2 3 15
+trap "rm -rf $tmp-*" 0
+trap "exit 1" 1 2 3 15
 
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
diff --git a/git-format-patch.sh b/git-format-patch.sh
index 7e67c4e..6ba6339 100755
--- a/git-format-patch.sh
+++ b/git-format-patch.sh
@@ -77,7 +77,8 @@ tt)
 esac
 
 tmp=.tmp-series$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
+trap "rm -f $tmp-*" 0
+trap "exit 1" 1 2 3 15
 
 series=$tmp-series
 commsg=$tmp-commsg
diff --git a/git-ls-remote.sh b/git-ls-remote.sh
index f699268..7dc224b 100755
--- a/git-ls-remote.sh
+++ b/git-ls-remote.sh
@@ -38,7 +38,8 @@ peek_repo="$(get_remote_url "$@")"
 shift
 
 tmp=.ls-remote-$$
-trap "rm -fr $tmp-*" 0 1 2 3 15
+trap "rm -rf $tmp-*" 0
+trap "exit 1" 1 2 3 15
 tmpdir=$tmp-d
 
 case "$peek_repo" in
diff --git a/git-reset.sh b/git-reset.sh
index 6c9e58a..166b635 100755
--- a/git-reset.sh
+++ b/git-reset.sh
@@ -4,7 +4,8 @@ USAGE='[--mixed | --soft | --hard]  [<co
 . git-sh-setup
 
 tmp=${GIT_DIR}/reset.$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
+trap "rm -f $tmp-*" 0
+trap "exit 1" 1 2 3 15
 
 reset_type=--mixed
 case "$1" in

^ permalink raw reply related

* Re: git cherry unkillable
From: Andrey Borzenkov @ 2006-01-22 15:01 UTC (permalink / raw)
  To: sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP10435A067270A659801A48AE110@CEZ.ICE>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sunday 22 January 2006 14:39, sean wrote:
>
> The attached patch works for me 

ack at least for git-cherry

> but i'm concerned about it a bit.  With 
> this patch it looks like the signal handler is executed twice; once as
> normal and a second time in response to the added "exit" statement.   By
> adding ";trap - 0;exit" it is only executed once, but i'm not sure how
> universal that is, and letting it run twice shouldn't be a big deal anyway.
>

why not

trap "rm -rf $tmp-*" 0
trap "exit" 1 2 3 15

?

- -andrey
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFD055JR6LMutpd94wRAn06AJ0RrLXwND67hvhRrSeaQvUjgrfGrACeK1cs
JA0jLNs5/8FPwpZqzKRd3eo=
=8QbF
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: git cherry unkillable
From: Andrey Borzenkov @ 2006-01-22 15:21 UTC (permalink / raw)
  To: sean; +Cc: git, zsh-workers
In-Reply-To: <BAYC1-PASMTP123903F6C83FFE0EDA6284AE110@CEZ.ICE>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sunday 22 January 2006 17:51, sean wrote:
> On Sun, 22 Jan 2006 06:39:04 -0500
>
> sean <seanlkml@sympatico.ca> wrote:
> > The attached patch works for me but i'm concerned about it a bit.
>
> Below is a better version that doesn't obscure the proper exit value in the
> normal case and exits with 1 if interrupted by the user.   It also ensures
> that the cleanup isn't executed twice when the script is interrupted.
>
> However, for Bash (at least) none of this is necessary; all the traps could
> just be changed to only trap 0 and the cleanup will be executed for all
> cases.   However, I don't know how compatible that is with other shells.  
> If other shells behave the same, the best fix is just to strip the 1,2,3
> and 15 from each of the existing trap lines and not bother with the patch
> given below.
>

this patch fails on zsh; trap 0 never executed after signal (SIGINT to be 
sure) is caught:

#!/bin/zsh

trap "exit 0" 1 2 3 15
trap "echo  exiting" 0

sleep 100000000

{pts/0}% /tmp/timout.zsh ^C
{pts/0}% 

- -andrey

> Sean
>
>
> diff --git a/git-cherry.sh b/git-cherry.sh
> index 1a62320..0b2ef1f 100755
> --- a/git-cherry.sh
> +++ b/git-cherry.sh
> @@ -49,7 +49,8 @@ ours=`git-rev-list $ours ^$limit` || exi
>  tmp=.cherry-tmp$$
>  patch=$tmp-patch
>  mkdir $patch
> -trap "rm -rf $tmp-*" 0 1 2 3 15
> +trap "rm -rf $tmp-*" 0
> +trap "exit 1" 1 2 3 15
>
>  _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
>  _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
> diff --git a/git-format-patch.sh b/git-format-patch.sh
> index 7e67c4e..6ba6339 100755
> --- a/git-format-patch.sh
> +++ b/git-format-patch.sh
> @@ -77,7 +77,8 @@ tt)
>  esac
>
>  tmp=.tmp-series$$
> -trap 'rm -f $tmp-*' 0 1 2 3 15
> +trap "rm -f $tmp-*" 0
> +trap "exit 1" 1 2 3 15
>
>  series=$tmp-series
>  commsg=$tmp-commsg
> diff --git a/git-ls-remote.sh b/git-ls-remote.sh
> index f699268..7dc224b 100755
> --- a/git-ls-remote.sh
> +++ b/git-ls-remote.sh
> @@ -38,7 +38,8 @@ peek_repo="$(get_remote_url "$@")"
>  shift
>
>  tmp=.ls-remote-$$
> -trap "rm -fr $tmp-*" 0 1 2 3 15
> +trap "rm -rf $tmp-*" 0
> +trap "exit 1" 1 2 3 15
>  tmpdir=$tmp-d
>
>  case "$peek_repo" in
> diff --git a/git-reset.sh b/git-reset.sh
> index 6c9e58a..166b635 100755
> --- a/git-reset.sh
> +++ b/git-reset.sh
> @@ -4,7 +4,8 @@ USAGE='[--mixed | --soft | --hard]  [<co
>  . git-sh-setup
>
>  tmp=${GIT_DIR}/reset.$$
> -trap 'rm -f $tmp-*' 0 1 2 3 15
> +trap "rm -f $tmp-*" 0
> +trap "exit 1" 1 2 3 15
>
>  reset_type=--mixed
>  case "$1" in
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFD06MSR6LMutpd94wRApgAAJ0e0AUIS83XTa4BA1rEY1XriHKZmQCgnXZd
1sElZOLAgyuxgi3EHiaMGFc=
=xwjP
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: git cherry unkillable
From: sean @ 2006-01-22 15:32 UTC (permalink / raw)
  To: Andrey Borzenkov; +Cc: git, zsh-workers
In-Reply-To: <200601221821.54461.arvidjaar@mail.ru>

On Sun, 22 Jan 2006 18:21:53 +0300
Andrey Borzenkov <arvidjaar@mail.ru> wrote:

> this patch fails on zsh; trap 0 never executed after signal (SIGINT to be 
> sure) is caught:
> 
> #!/bin/zsh
> 
> trap "exit 0" 1 2 3 15
> trap "echo  exiting" 0
> 
> sleep 100000000
> 
> {pts/0}% /tmp/timout.zsh ^C
> {pts/0}% 
> 

Damn, would be so much nicer to get this stuff out of shell scripts.   Anyway,
your discovery kills the idea of being able to just ignore the higher signal
traps...   The following implements the same idea as my second patch
in hopefully a slightly more cross-shell compatible way;  it works on bash
and zsh at least.

diff --git a/git-cherry.sh b/git-cherry.sh
index 1a62320..686210b 100755
--- a/git-cherry.sh
+++ b/git-cherry.sh
@@ -49,7 +49,8 @@ ours=`git-rev-list $ours ^$limit` || exi
 tmp=.cherry-tmp$$
 patch=$tmp-patch
 mkdir $patch
-trap "rm -rf $tmp-*" 0 1 2 3 15
+trap "rm -rf $tmp-*" 0
+trap "kill -0 $$" 1 2 3 15
 
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
diff --git a/git-format-patch.sh b/git-format-patch.sh
index 7e67c4e..9f93bbb 100755
--- a/git-format-patch.sh
+++ b/git-format-patch.sh
@@ -77,7 +77,8 @@ tt)
 esac
 
 tmp=.tmp-series$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
+trap "rm -f $tmp-*" 0
+trap "kill -0 $$" 1 2 3 15
 
 series=$tmp-series
 commsg=$tmp-commsg
diff --git a/git-ls-remote.sh b/git-ls-remote.sh
index f699268..0cd1f07 100755
--- a/git-ls-remote.sh
+++ b/git-ls-remote.sh
@@ -38,7 +38,8 @@ peek_repo="$(get_remote_url "$@")"
 shift
 
 tmp=.ls-remote-$$
-trap "rm -fr $tmp-*" 0 1 2 3 15
+trap "rm -rf $tmp-*" 0
+trap "kill -0 $$" 1 2 3 15
 tmpdir=$tmp-d
 
 case "$peek_repo" in
diff --git a/git-reset.sh b/git-reset.sh
index 6c9e58a..597b36e 100755
--- a/git-reset.sh
+++ b/git-reset.sh
@@ -4,7 +4,8 @@ USAGE='[--mixed | --soft | --hard]  [<co
 . git-sh-setup
 
 tmp=${GIT_DIR}/reset.$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
+trap "rm -f $tmp-*" 0
+trap "kill -0 $$" 1 2 3 15
 
 reset_type=--mixed
 case "$1" in

^ permalink raw reply related

* Re: git cherry unkillable
From: sean @ 2006-01-22 15:48 UTC (permalink / raw)
  To: sean; +Cc: arvidjaar, git, zsh-workers
In-Reply-To: <BAYC1-PASMTP03EC255443CA14D57D82F6AE110@CEZ.ICE>

On Sun, 22 Jan 2006 10:32:04 -0500
sean <seanlkml@sympatico.ca> wrote:

> Damn, would be so much nicer to get this stuff out of shell scripts.   Anyway,
> your discovery kills the idea of being able to just ignore the higher signal
> traps...   The following implements the same idea as my second patch
> in hopefully a slightly more cross-shell compatible way;  it works on bash
> and zsh at least.

Ooops, not even close on that attempt :o/   Here's a version that really does
work on zsh and bash; and should work on all shells.

Sean

diff --git a/git-cherry.sh b/git-cherry.sh
index 1a62320..4925f1f 100755
--- a/git-cherry.sh
+++ b/git-cherry.sh
@@ -49,7 +49,9 @@ ours=`git-rev-list $ours ^$limit` || exi
 tmp=.cherry-tmp$$
 patch=$tmp-patch
 mkdir $patch
-trap "rm -rf $tmp-*" 0 1 2 3 15
+cleanup() { rm -rf $tmp-*; }
+trap cleanup 0
+trap "cleanup;trap 0;exit 1" 1 2 3 15
 
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
diff --git a/git-format-patch.sh b/git-format-patch.sh
index 7e67c4e..574a79c 100755
--- a/git-format-patch.sh
+++ b/git-format-patch.sh
@@ -77,7 +77,9 @@ tt)
 esac
 
 tmp=.tmp-series$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
+cleanup() { rm -f $tmp-*; }
+trap cleanup 0
+trap "cleanup;trap 0;exit 1" 1 2 3 15
 
 series=$tmp-series
 commsg=$tmp-commsg
diff --git a/git-ls-remote.sh b/git-ls-remote.sh
index f699268..0259a88 100755
--- a/git-ls-remote.sh
+++ b/git-ls-remote.sh
@@ -38,7 +38,9 @@ peek_repo="$(get_remote_url "$@")"
 shift
 
 tmp=.ls-remote-$$
-trap "rm -fr $tmp-*" 0 1 2 3 15
+cleanup() { rm -rf $tmp-*; }
+trap cleanup 0
+trap "cleanup;trap 0;exit 1" 1 2 3 15
 tmpdir=$tmp-d
 
 case "$peek_repo" in
diff --git a/git-reset.sh b/git-reset.sh
index 6c9e58a..3336690 100755
--- a/git-reset.sh
+++ b/git-reset.sh
@@ -4,7 +4,9 @@ USAGE='[--mixed | --soft | --hard]  [<co
 . git-sh-setup
 
 tmp=${GIT_DIR}/reset.$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
+cleanup() { rm -f $tmp-*; }
+trap cleanup 0
+trap "cleanup;trap 0;exit 1" 1 2 3 15
 
 reset_type=--mixed
 case "$1" in

^ permalink raw reply related

* Re: What is in git.git
From: Daniel Barkalow @ 2006-01-22 17:53 UTC (permalink / raw)
  To: Josef Weidendorfer; +Cc: Junio C Hamano, git
In-Reply-To: <200601220033.26321.Josef.Weidendorfer@gmx.de>

On Sun, 22 Jan 2006, Josef Weidendorfer wrote:

> On Saturday 21 January 2006 20:37, you wrote:
> > Alexander Litvinov <lan@ac-sw.com> writes:
> > >> 1. Can I bind some branch instead of tag (commit) ?
> > ... 
> > If you mean by "binding a branch", to record how each subproject
> > relates to the toplevel project (i.e. "the subproject bound to
> > X/ subdirectory of the toplevel project comes from branch Y"),
> > that information needs to be somewhere, but recording it in the
> > commit object goes against the whole git philosophy.
> 
> The original gitlink proposal did exactly this: it recorded
> the place where a subproject is bound by putting a gitlink into
> a tree. This way, the binding point can be changed, and is subject to
> versioning itself.
> 
> I just realized that this is not currently possible with the bind lines.
> What about the following usage szenario:
> - in a superproject, I use a subproject X implementing some lib by 
>   binding it at X/. My Makefile recurses into X/ for this.
>   This is recorded at commit point (A)
> - later on, I realize I need another lib from a probject Y; I want
>   to put the libs X and Y into subdirectory lib/ of my superproject;
>   i.e. I bind Y at lib/Y/ and move the binding point of X to lib/X/.
>   The Makefile is changed accordingly to build the subprojects.
>   This is recorded at commit point (B)
> 
> A $GITDIR/bind alone will no work, as moving back to (A) would keep
> the binding point of subproject, and make is broken.

I think you're misunderstanding the use of the "bind" file or equivalent. 
It isn't a configuration file that specifies where the subprojects go; 
it's a state file that tracks where the subprojects currently are. The 
commits by themselves are sufficient to indentify the locations of the 
subprojects, and the bind file would be written by "git checkout" reading 
a commit with subprojects. It's used to create the next commit, in much 
the same way that MERGE_HEAD is used to create the next commit by storing 
information between the git call that starts a merge that needs user 
interaction and the git call to commit the merge.

So moving back to (A) wouldn't keep the binding point of subproject, 
because it would rewrite bind to what it had been.

I'm going to suggest again keeping this information in the index file (but 
not in the index data structure, so the changes to the code are only in 
the library routines to read and write the file, and, of course, anything 
that's actually trying to manipulate the binding locations). I started 
working on a patch to pu to skip S_IFDIR entries from the index file when 
building the table in memory, and that was straightforward, but I got into 
sysadmin issues when I was going to test giving it something to skip.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [PATCH] Mention install-doc in INSTALL
From: J. Bruce Fields @ 2006-01-22 18:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Petr Baudis, git
In-Reply-To: <7vr771gcu9.fsf@assigned-by-dhcp.cox.net>

On Sat, Jan 21, 2006 at 07:29:02PM -0800, Junio C Hamano wrote:
> Petr Baudis <pasky@suse.cz> writes:
> 
> > But you really do not want to build the documentation as root.
> 
> True.
> 
> > Cogito's "solution" is:
> >
> > + - By default, separate documentation (manpages, text, HTML) is not built
> > +   since it requires asciidoc and xmlto, and those tools are not so common.
> 
> That's cheating ;-), but I cannot blame you.
> 
> I'll push out this hopefully tonight.

Looks good to me; thanks!--b.

^ permalink raw reply

* Re: [RFC] Reverting "git push logic change"?
From: Daniel Barkalow @ 2006-01-22 19:09 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Greg KH
In-Reply-To: <7vfynivx9s.fsf_-_@assigned-by-dhcp.cox.net>

On Fri, 20 Jan 2006, Junio C Hamano wrote:

> The change introduced by 9e9b267 commit broke "correct" usage of
> git push to push matching refs, to work around a problem
> observed in a usage pattern on a shared repository.
> 
> I think I made a bad judgement in evaluating the scenario, and
> made a bad change to "fix" a problem that did not exist.  I
> apologize for having caused this confusion.
> 
> My conclusion after thinking about the problem again is that we
> would be better of if we reverted that commit.  This message is
> to make my intention clear, and solicit objections or comments
> from the list.
> 
> The use case that prompted this change was this:
> 
>  - A shared repository is created by cloning Linus repository.
>    This repository gets "origin" (then-current Linus master) and
>    "master" (the same).
> 
> 	$ git clone --naked \
>           git://git.kernel.org/.../linux-2.6.git/ project.git
> 
>  - Two developers use this as their shared repository.  They
>    first start out by cloning from it, do their development in
>    their "master" branch and pushing back to the "master" branch
>    of the shared repository.  Their workflow is:
> 
> 	0. Clone it (once per developer):
>         $ git clone ssh://pub.example.com/project.git/ work
> 
> 	1. To make sure the developers are in sync:
> 	$ git pull ssh://pub.example.com/project.git/ ;# (a) or
> 	$ git pull origin			      ;# (b)
> 
>         2. His own development:
> 	$ edit;compile;test;git commit
> 
> 	3. Pull from upstream, to avoid conflicts with it (only when needed):
> 	$ git pull git://git.kernel.org/.../linux-2.6.git/
> 
> 	4. Push back the result to shared repository:
>         $ git push ssh://pub.example.com/project.git/
> 
> With this workflow, in the two developer repositories, "origin"
> branch is not really well maintained.  If "git pull origin" was
> used with the remotes/origin file "git clone" initially gave
> him, it would have kept track of the latest push into the shared
> "master" closely, but if the explicit URL was used, "origin" of
> the developer repository would have been left behind.
> 
> This is not problem as far as the correctness of the "master"
> branch is concerned.  The fast-forward check when pushing into
> the shared repository "master" branch prevents the two
> developers from losing commits.  In other words, either way to
> pull from the shared repository is legal/valid.
> 
> However, the push done in step 4. triggers the default "push all
> matching refs" behaviour.  All three repositories have "origin"
> and "master", which means this results in "origin" being updated
> in the shared repository.  But one developer repository has a
> stale "origin" while the other developer has an up-to-date
> "origin".  This triggers a "not a fast forward" error, which
> does not cause the push of "master" to fail, but still looks
> worrisome.

I think there are a number of good solutions:

 - Make the case of a pure rewind (i.e., pushing something that would be a 
   fast-forward in the other direction) have no effect and give a more 
   positive message like 'Remote "origin" is already ahead of your 
   version.' I expect that something of that sort would comfort the users 
   and distinguish branches that you're not actively using and have fallen 
   behind on from branches that you are using, but someone else is also 
   using. This seems like a good idea even if we do other stuff.
 - Have a command to write, report, and modify remotes files, so Greg can 
   tell it exactly what he actually wants without mucking around with the 
   files by hand. Also generally nice.
 - Require --all in push, but, if none are given, produce a summary of 
   what you could specify instead of assuming you mean to push nothing. 
   Then Greg would see master:master as the obvious thing, and do that.
 - Maybe "git clone" should add "Push: master:master" by default if the 
   URL permits pushing?

I think that having it default to matching branches isn't really ideal, 
since that seems to me to work for practically everybody only by 
coincidence: master:master is by far the most common case; then 
there are some people who use multiple branches, but they must have done 
something other than the default to create this situation, anyway; then 
there's the case where "master" isn't a head on both sides, but (at least 
in my experience), master:master is still what the user means (case 
happens when pushing a first commit from a clone of an empty repository). 

Maybe the default should be master:master? It seems to fit the general 
pattern of defaulting to master. Or maybe (what HEAD points to):(matching 
branch), or (but I'm not too comfortable with this one) HEAD:master.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: What is in git.git
From: Junio C Hamano @ 2006-01-22 20:08 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.64.0601221106330.25300@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> I think you're misunderstanding the use of the "bind" file or equivalent. 
>...
> So moving back to (A) wouldn't keep the binding point of subproject, 
> because it would rewrite bind to what it had been.

A lot better said than my version of the response.  Thanks.

> I'm going to suggest again keeping this information in the index file (but 
> not in the index data structure, so the changes to the code are only in 
> the library routines to read and write the file, and, of course, anything 
> that's actually trying to manipulate the binding locations). I started 
> working on a patch to pu to skip S_IFDIR entries from the index file when 
> building the table in memory, and that was straightforward, but I got into 
> sysadmin issues when I was going to test giving it something to skip.

I have been thinking about this one, and having read that
read-cache code I think the coding is not too involved.

My current inclination is to use the same version number (2) by
default and promote it to a new version number (3) once you add
subproject-binding information to the index file.  Then current
tools would keep working on repositories created or operated
upon with the new tools, as long as the project does not use the
new feature.

^ permalink raw reply

* Re: What is in git.git
From: Daniel Barkalow @ 2006-01-22 20:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vu0bwdo08.fsf@assigned-by-dhcp.cox.net>

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

> I have been thinking about this one, and having read that
> read-cache code I think the coding is not too involved.
> 
> My current inclination is to use the same version number (2) by
> default and promote it to a new version number (3) once you add
> subproject-binding information to the index file.  Then current
> tools would keep working on repositories created or operated
> upon with the new tools, as long as the project does not use the
> new feature.

I think bumping the index file version number shouldn't be too big a deal; 
index files are rarely used by different versions, except for the case 
where you've installed a new version of git, and that's generally a later 
version, not an earlier one.

It might make sense to add logic to make the stable series accept version 
3 files without special entries, though. And maybe future-proof by having 
it look for unexpected flags and give a "too new version" error for them, 
even if the version number is within range. (I.e., if we add more special 
entry types later, it would tell you if your index file uses a feature 
that the version of git you're using doesn't support, even if the version 
number hasn't changed, and we reserve changing the version number for 
things where the file wouldn't read right at all or something previously 
legal changes meaning.)

On a side topic, is there any reason not to convert ls-tree to use struct
tree, and kill the other tree-object-parsing code, which doesn't seem to 
be used by anything else?

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [RFC] Reverting "git push logic change"?
From: Junio C Hamano @ 2006-01-22 20:31 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git, Greg KH
In-Reply-To: <Pine.LNX.4.64.0601221311530.25300@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

>  - Make the case of a pure rewind (i.e., pushing something that would be a 
>    fast-forward in the other direction) have no effect and give a more 
>    positive message like 'Remote "origin" is already ahead of your 
>    version.'

If the remote is not behind you, you would not be able to tell
if it is ahead of you or totally unrelated, unless you fetch
from them.  So I am afraid this is unpractical.

>  - Have a command to write, report, and modify remotes files, so Greg can 
>    tell it exactly what he actually wants without mucking around with the 
>    files by hand. Also generally nice.

For the record, it was somebody else.  Greg has the repositories
on both ends set up correctly, and does not suffer from this
"left behind origin" error message.  He has every right to
expect the "all the matching refs" semantics to keep working.

I think in this case, it was not the lack of tool to "tell it
exactly what he actually wants", but "what he actually wants"
was not quite well understood by the developers who experienced
this problem (again, not Greg).  This is a user error but that
is not their fault.  It means that we need to document this
better:

	A typical "cloned" repository has an "origin" branch to
	record the head commit of the upstream repository when
	the repository was cloned, and the branch is used to
	keep track of further development at the upstream.  But
	in a shared repository, it usually is not used for
	further development by your developers who clone from it
	and then push their changes back to it (for that they
	would use the "master" branch).  Your developers may
	occasionally need to sync with the upstream, but that is
	done by pulling from the upstream directly, and the
	"origin" branch at the shared repository is not
	involved.  In other words, that branch is useless and
	tends to be left behind.  If you are preparing a
	repository by first cloning from somewhere else, remove
	branches that your developers and people who download
	from your shared repository do not use, including
	"origin".

	"git push", without telling the tool which branches to
        push explicitly, pushes the branches that exist on both
        ends.  Culling unused branches, especially "origin",
        from the shared repository helps your developers because
        they do not have to do anything special to prevent their
        "origin" from being pushed back to the shared repository.

or something like that.

>  - Require --all in push, but, if none are given, produce a summary of 
>    what you could specify instead...

This is essentially what the "fix" did, except giving a summary.
The effect to the end user was that we were robbing "matching
refs" option from them.

>  - Maybe "git clone" should add "Push: master:master" by default if the 
>    URL permits pushing?

This might be a good thing to have.  I suspect majority of users
would benefit from this.

> I think that having it default to matching branches isn't really ideal, 
> since that seems to me to work for practically everybody only by 
> coincidence: master:master is by far the most common case; then 
> there are some people who use multiple branches, but they must have done 
> something other than the default to create this situation, anyway;

Actually I started to think matching is a very good default for
everyday use.

 - In the recommended "topic branches" workflow, a developer
   repository has more branches than his public repository he
   pushes into.  A typical public repository on kernel.org has
   either "master" alone, or "test" and "release" pair.  In
   either case, I expect the set of branches on these public
   repositories have "matching" ones in the owners' development
   repositories.  "matching" push lets them updated without
   pushing topic branch heads _unless_ the developer also wants
   to push topic branches to public, which reduces the clutter
   on the public repository.

 - In a shared repository setup, a developer still can employ
   topic branches workflow for himself.  The same "matching
   semantics prevents unneeded exposure of private topic
   branches" applies here.

 - In a non-default developer repository that has more than one,
   they must have done something other than the default.  For
   example:

	$ git branch test
        $ git branch release
        $ git push public:myrepo test release

   We _could_ require (or strongly suggest) them to keep a
   remotes/ shorthand for push destination and have:

	URL: public:myrepo
        Push: test
        Push: release

   so that next push would be "git push public".  Another
   possibility is that "git push public test release"
   (i.e. using a "remotes/public" shorthand) _could_ offer to
   update the remotes/ file when it sees these branches do not
   appear on Push: lines.

   But the "matching ones" push has the same effect.  It
   remembers which ones have been pushed out before, without
   mucking with remotes/ file, as long as the branch names are
   the same on the both ends (which I suspect is the most common
   usage).

   Also we need to remember there are people who push into more
   than one repositories, and they would need to keep and
   maintain separate remotes/ file per destination if there is
   no "matching ones" option.

If we add "Push: master" upon clone from host:repo (or local),
then these new repositories would push master into master and
nothing else with "git push origin", and "git push URL" to the
same remote repository without using remotes/ shorthand would
result in the matching behaviour.  That may be a good default.

^ permalink raw reply

* Re: What is in git.git
From: Junio C Hamano @ 2006-01-22 20:35 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0601221512470.25300@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> On a side topic, is there any reason not to convert ls-tree to use struct
> tree, and kill the other tree-object-parsing code, which doesn't seem to 
> be used by anything else?

ls-tree _might_ be doing something struct tree interface does
not support, but I do not know.

If you are inclined to, please go wild ;-).

^ permalink raw reply

* Re: What is in git.git
From: Junio C Hamano @ 2006-01-22 20:41 UTC (permalink / raw)
  To: git
In-Reply-To: <200601220033.26321.Josef.Weidendorfer@gmx.de>

Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:

> I understand that "moving binding point of X from X/ to lib/X/" is not
> representable within the index as a simple change. Is this the main issue
> for your "against the whole git philosophy"?

No.  I meant an exposure of local branch names by recording them
in the commit object, and nothing else, by that comment.

Instead of using an extra $GIT_DIR/bind file extending what we
record in the index file is OK.  $GIT_INDEX_FILE, $GIT_DIR/HEAD,
and $GIT_DIR/bind pretty much go hand-in-hand anyway and they
_are_ local to the repository, just like branch names are, so I
do not have any problem with using local branch names in these
places, but not in a commit object (or gitlink object for that
matter).

^ permalink raw reply

* git pull on a branch semantics
From: Luben Tuikov @ 2006-01-22 20:58 UTC (permalink / raw)
  To: git

Hi,

pwd is a git repo; current branch is A; there's a few
branches in this git repo.
In .git/remotes/ I've a file name "projectC", which looks like:

URL:<url>
Pull:projectC:projectC
Push:projectC:projectC

That is both here and remotely I've projectC being a branch
here and remotely.

I'd like to pull changes to projectC only, from the remote projectC to the local projectC, but my
current branch is A.

I blissfully do:

git pull projectC

git correctly tells me that the heads are the same in
branchC here and remote, but it then goes ahead to merge
projectC in the current branch A (project A) since they
have a common ancestor.

But because of the "Pull" line in .git/remotes/projectC
what the intention was is to pull from projectC remotely
and merge any new changes in projectC locally, and only
in projectC (irrespective of what the current branch
is (in the pwd)).

Is this behavior a bug or is this a "feature"?

Thanks,
   Luben

^ permalink raw reply

* Re: git pull on a branch semantics
From: Junio C Hamano @ 2006-01-22 21:02 UTC (permalink / raw)
  To: ltuikov; +Cc: git
In-Reply-To: <20060122205852.255.qmail@web31812.mail.mud.yahoo.com>

Luben Tuikov <ltuikov@yahoo.com> writes:

> URL:<url>
> Pull:projectC:projectC
> Push:projectC:projectC
>
> That is both here and remotely I've projectC being a branch
> here and remotely.
>
> I'd like to pull changes to projectC only, from the remote projectC to the local projectC, but my
> current branch is A.
>
> I blissfully do:
>
> git pull projectC

You wanted to "git fetch", not "git pull" which is "fetch
followed by merge into the current branch".

^ permalink raw reply

* Re: [RFC] Reverting "git push logic change"?
From: Junio C Hamano @ 2006-01-22 21:31 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <7vr770c8db.fsf@assigned-by-dhcp.cox.net>

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

> ...  This is a user error but that is not their fault.  It
> means that we need to document this better:

I hope something like this is clear enough?

-- >8 --
[PATCH] Recommend to remove unused `origin` in a shared repository

It is a common mistake to leave an unsed `origin` branch behind
if a shared public repository was created by first cloning from
somewhere else.  Subsequent `git push` into it with the default
"push all the matching ref" would push the `origin` branch from
the developer repository uselessly.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt
index b8fa299..35579cc 100644
--- a/Documentation/tutorial.txt
+++ b/Documentation/tutorial.txt
@@ -1667,6 +1667,26 @@ complain, telling you that the remote `m
 fast forward.  You need to pull and merge those other changes
 back before you push your work when it happens.
 
+The `git push` command without any explicit refspec parameter
+pushes the refs that exist both in the local repository and the
+remote repository.  So the last `push` can be done with either
+one of these:
+------------
+$ git push origin
+$ git push repo.shared.xz:/pub/scm/project.git/
+------------
+as long as the shared repository does not have any branches
+other than `master`.
+[NOTE]
+============
+If you created your shared repository by cloning from somewhere
+else, you may have the `origin` branch.  Your developers
+typically do not use that branch; remove it.  Otherwise, that
+would be pushed back by the `git push origin` because your
+developers' repository would surely have `origin` branch to keep
+track of the shared repository, and would be counted as "exist
+on both ends".
+============
 
 Advanced Shared Repository Management
 -------------------------------------

^ permalink raw reply related

* Re: [RFC] Reverting "git push logic change"?
From: sean @ 2006-01-22 21:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: barkalow, git
In-Reply-To: <7vu0bw9ch7.fsf@assigned-by-dhcp.cox.net>

On Sun, 22 Jan 2006 13:31:00 -0800
Junio C Hamano <junkio@cox.net> wrote:


> +If you created your shared repository by cloning from somewhere
> +else, you may have the `origin` branch.  Your developers
> +typically do not use that branch; remove it.  Otherwise, that
> +would be pushed back by the `git push origin` because your
> +developers' repository would surely have `origin` branch to keep
> +track of the shared repository, and would be counted as "exist
> +on both ends".


What about just always excluding the origin branch from being 
implicitly pushed; even if it does exist in both repositories?
In the rare cases where it is actually desired to be pushed,
it can be done explicitly.

Sean

^ permalink raw reply

* Re: [RFC] Reverting "git push logic change"?
From: Junio C Hamano @ 2006-01-22 23:09 UTC (permalink / raw)
  To: sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP0532B701820FA4ADB3C640AE110@CEZ.ICE>

sean <seanlkml@sympatico.ca> writes:

> What about just always excluding the origin branch from being 
> implicitly pushed; even if it does exist in both repositories?
> In the rare cases where it is actually desired to be pushed,
> it can be done explicitly.

The problem is "origin" is just a Porcelain convention and we
would not want to teach that to the core level, so that will not
fly.

^ permalink raw reply

* [PATCH] Cogito: Handle push over http
From: Beber @ 2006-01-22 23:57 UTC (permalink / raw)
  To: pasky; +Cc: git

[-- Attachment #1: Type: text/plain, Size: 150 bytes --]

Hi,

Here is a patch allow cg-push to push over http.

You can pull http://guybrush.ath.cx/git/public/cogito.git/
Or use attach patch.

Beber

[-- Attachment #2: http-push-for-cg.patch --]
[-- Type: application/octet-stream, Size: 427 bytes --]

--- a/cg-push
+++ b/cg-push
@@ -69,7 +69,7 @@ fi
 sprembranch=":refs/heads/$rembranch"
 
 if [ "${uri#http://}" != "$uri" ]; then
-	die "pushing over HTTP not supported yet"
+	git-http-push "$uri/" $locbranch
 elif [ "${uri#git+ssh://}" != "$uri" ]; then
 	send_pack_update "$name" "$(echo "$uri" | sed 's#^git+ssh://\([^/]*\)\(/.*\)$#\1:\2#')" "$locbranch$sprembranch" "${tags[@]}"
 elif [ "${uri#rsync://}" != "$uri" ]; then

^ permalink raw reply

* Re: RFC: Subprojects
From: Petr Baudis @ 2006-01-23  0:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Josef Weidendorfer, git
In-Reply-To: <7vek37rj83.fsf@assigned-by-dhcp.cox.net>

Dear diary, on Mon, Jan 16, 2006 at 09:49:48PM CET, I got a letter
where Junio C Hamano <junkio@cox.net> said that...
>    We could introduce "bind the rest" to make write-tree write
>    out a tree that contains only the containing project part and
>    not any of the subproject part (e.g. Makefile, README and
>    src/ but not linux-2.6/ nor gcc-4.0/ in the earlier example).
>    Essentially the contents of such a tree object would be the
>    same as what "gitlink" approach would have had for the
>    containing project in the index file, minus "gitlink" entries
>    themselves).  This is not so surprising, because the missing
>    information "gitlink" approach recorded in the tree object
>    itself is expressed on "bind" lines in the commit object with
>    this approach.

Now, I must have missed the obvious again, but what is the point in
having the write-tree --exclude stuff? My impression (also from your
later mail in this thread) is that now the moment you introduce any
binds, your top-level development changes to "two-tiered" - the
top-level project and the meta-project holding it all together. I'd say
that's pretty confusing and I don't see big gain in this; the simplicity
of the original proposal was a lot more appealing.

-- 
				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

* Re: RFC: Subprojects
From: Petr Baudis @ 2006-01-23  1:22 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: Junio C Hamano, Josef Weidendorfer, git
In-Reply-To: <Pine.LNX.4.64.0601181214150.25300@iabervon.org>

Dear diary, on Wed, Jan 18, 2006 at 07:21:59PM CET, I got a letter
where Daniel Barkalow <barkalow@iabervon.org> said that...
> Okay, so you're using additional branch heads in the superproject to track 
> the current state of the subprojects. That makes sense, although I think 
> it would confuse people less if they were held separately. IIRC, 
> refs/subprojects/kernel/heads/master is a perfectly good ref name these 
> days, so that might be a good idea. That would also mean that 
> refs/tags/v2.6.14 and refs/tags/v2.7.2.3 wouldn't get confused (being 
> linux and gcc tags, respectively), because they'd be under the appropriate 
> subprojects.

I passionately agree - this is the only thing I do not like on the
current Junio's proposal (besides that top-level subproject confusion).
The way it is proposed, you are mixing different projects in a single
refs namespace and I think that's *really* confusing.

Besides, you are going to get a lot of complications since to do merging
properly you need two heads per subproject (its 'master' and 'origin'
heads; and it's useful to have e.g. all the upstream heads called
'origin' since then you can say cg-fetch -r origin in the superproject
and have all the subproject origins fetched as well) and you might want
to have other subproject heads as well. Now, for different superproject
heads, you want separate set of subproject heads. You can see the
downward spiral from here, I guess... And multiply all that by two since
you also have tags.

It actually took me a short while to realize that keeping separate
subproject/.git/refs makes no sense precisely because for different
superproject heads, you want a different set of subproject refs.
So in line with Daniel's proposal, I'd propose:

	refs/subprojects/<superhead>/<subid>/heads/master

<superhead> is the name of the current HEAD (${#refs/heads/}). <subid>
is a little more tricky - this should be the part after the equal sign
in .git/mtab (or .git/binds or .git/subprojects or whichever is the name
of the day). Obviously, you can just figure out something, but I'd like
to assign this automagically.

OTOH, in Cogito I might as well just default to sha1 of something random
(e.g.  the path+commitid+time()) since I do not expect this to be
normally referenced by a human; I just intend to switch from refs/ to
refs/subprojects/<superhead>/<subid>/ when dealing with the subproject
exclusively. ($GIT_REF_DIR (by default $GIT_DIR/refs) would come useful;
I'll probably whip up a patch when I get to finally need it.)

> I hope people will want to prepare their commits to the kernel subproject 
> as would be suitable for pushing to Linus, which would suggest that they'd 
> tend to do a commit in the kernel subproject embedded in their 
> superproject separately from doing the commit in the superproject, and 
> so the branch head would match the index but not the bind line when they 
> got to committing the superproject.

FWIW, my idea is that it should be "a seamless experience for the user"
(tm) to do development in a subproject of another project, and I can see
no reason why should that be hard to do in any way.

-- 
				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

* Re: [RFC] Reverting "git push logic change"?
From: Junio C Hamano @ 2006-01-23  1:31 UTC (permalink / raw)
  To: sean; +Cc: git
In-Reply-To: <7vpsmjamgw.fsf@assigned-by-dhcp.cox.net>

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

> sean <seanlkml@sympatico.ca> writes:
>
>> What about just always excluding the origin branch from being 
>> implicitly pushed; even if it does exist in both repositories?
>> In the rare cases where it is actually desired to be pushed,
>> it can be done explicitly.
>
> The problem is "origin" is just a Porcelain convention and we
> would not want to teach that to the core level, so that will not
> fly.

One improvement that can be done is to update "git clone --bare"
so that it does not create "origin", which is more or less
pointless for such a "distribution point" repository.

This reminds me that I need to deprecate --naked and introduce --bare
to the clone command...

^ permalink raw reply

* Notes on Subproject Support
From: Junio C Hamano @ 2006-01-23  1:35 UTC (permalink / raw)
  To: git; +Cc: Daniel Barkalow, Petr Baudis

This is still a draft/WIP, but "release early" is a good
discipline, so...

-- >8 --

Notes on Subproject Support
===========================
Junio C Hamano <junkio@cox.net>
v1.0 January 22, 2006

Scenario
--------

The examples in the following discussion show how this proposal
plans to help this:

. A project to build an embedded Linux appliance "gadget" is
  maintained with git.

. The project uses linux-2.6 kernel as its subcomponent.  It
  starts from a particular version of the mainline kernel, but
  adds its own code and build infrastructure to fit the
  appliance's needs.

. The working tree of the project is laid out this way:
+
------------
 Makefile       - Builds the whole thing.
 linux-2.6/     - The kernel, perhaps modified for the project.
 appliance/     - Applications that run on the appliance, and
                  other bits.
------------

. The project is willing to maintain its own changes out of tree
  of the Linux kernel project, but would want to be able to feed
  the changes upstream, and incorporate upstream changes to its
  own tree, taking advantage of the fact that both itself and
  the Linux kernel project are version controlled with git.

The idea here is to:

. Keep `linux-2.6/` part as an independent project.  The work by
  the project on the kernel part can be naturally exchanged with
  the other kernel developers this way.  Specifically, a tree
  object contained in commit objects belonging to this project
  does *not* have linux-2.6/ directory at the top.

. Keep the `appliance/` part as another independent project.
  Applications are supposed to be more or less independent from
  the kernel version, but some other bits might be tied to a
  specific kernel version.  Again, a tree object contained in
  commit objects belonging to this project does *not* have
  appliance/ directory at the top.

. Have another project that combines the whole thing together,
  so that the project can keep track of which versions of the
  parts are built together.

We will call the project that binds things together the
'toplevel project'.  Other projects that hold `linux-2.6/` part
and `appliance/` part are called 'subprojects'.

Notice that `Makefile` at the top is part of the toplevel
project in this example, but it is not necessary.  We could
instead have the appliance subproject include this file.  In
such a setup, the appliance subproject would have had `Makefile`
and `appliance/` directory at the toplevel.


Setting up
----------

Let's say we have been working on the appliance software,
independently version controlled with git.  Also the kernel part
has been version controlled separately, like this:
------------
$ ls -dF current/*/.git current/*
current/Makefile    current/appliance/.git/  current/linux-2.6/.git/
current/appliance/  current/linux-2.6/
------------

Now we would want to get a combined project.  First we would
clone from these repositories (which is not strictly needed --
we could use `$GIT_ALTERNATE_OBJECT_DIRECTORIES` instead):

------------
$ mkdir combined && cd combined
$ cp ../current/Makefile .
$ git init-db
$ mkdir -p .git/refs/subs/{kernel,gadget}/{heads,tags}
$ git clone-pack ../current/linux-2.6/ master | read kernel_commit junk
$ git clone-pack ../current/appliance/ master | read gadget_commit junk
------------

We will introduce a new command to set up a combined project:

------------
$ git bind-projects \
	$kernel_commit linux-2.6/ \
	$gadget_commit appliance/
------------

This would do an equivalent of:

------------
$ git read-tree --prefix=linux-2.6/ $kernel_commit
$ git read-tree --prefix=appliance/ $gadget_commit
------------
[NOTE]
============
Earlier outlines sent to the git mailing list talked
about `$GIT_DIR/bind` to record what subproject are bound to
which subtree in the curent working tree and index.  This
proposal instead records that information in the index file
when `--prefix=linux-2.6/` is given to `read-tree`.

Also note that in this round of proposal, there is no separate
branches that keep track of heads of subprojects.
============

Let's not forget to add the `Makefile`, and check the whole
thing out from the index file.
------------
$ git add Makefile
$ git checkout-index -f -u -q -a
------------

Now our directory should be identical with the `current`
directory.  After making sure of that, we should be able to
commit the whole thing:

------------
$ diff -x .git -r ../current ../combined
$ git commit -m 'Initial toplevel project commit'
------------

Which should create a new commit object that records what is in
the index file as its tree, with `bind` lines to record which
subproject commit objects are bound at what subdirectory, and
updates the `$GIT_DIR/refs/heads/master`.  Such a commit object
might look like this:
------------
tree 04803b09c300c8325258ccf2744115acc4c57067
bind 5b2bcc7b2d546c636f79490655b3347acc91d17f linux-2.6/
bind 0bdd79af62e8621359af08f0afca0ce977348ac7 appliance/
author Junio C Hamano <junio@kernel.org> 1137965565 -0800
committer Junio C Hamano <junio@kernel.org> 1137965565 -0800

Initial toplevel project commit
------------


Making further commits
----------------------

The easiest case is when you updated the Makefile without
changing anything in the subprojects.  In such a case, we just
need to create a new commmit object that records the new tree
with the current `HEAD` as its parent, and with the same set of
`bind` lines.

When we have changes to the subproject part, we would make a
separate commit to the subproject part and then record the whole
thing by making a commit to the toplevel project.  The user
interaction might go this way:
------------
$ git commit
error: you have changes to the subproject bound at linux-2.6/.
$ git commit --subproject linux-2.6/
$ git commit
------------

With the new `--subproject` option, the directory structure
rooted at `linux-2.6/` part is written out as a tree, and a new
commit object that records that tree object with the commit
bound to that portion of the tree (`5b2bcc7b` in the above
example) as its parent is created.  Then the final `git commit`
would record the whole tree with updated `bind` line for the
`linux-2.6/` part.


Checking out
------------

After cloning such a toplevel project, `git clone` without `-n`
option would check out the working tree.  This is done by
reading the tree object recorded in the commit object (which
records the whole thing), and adding the information from the
"bind" line to the index file.

------------
$ cd ..
$ git clone -n combined cloned ;# clone the one we created earlier
$ cd cloned
$ git checkout
------------

This round of proposal does not maintain separate branch heads
for subprojects.  The bound commits and their subdirectories
are recorded in the index file from the commit object, so there
is no need to do anything other than updating the index and the
working tree.


Switching branches
------------------

Along with the traditional two-way merge by `read-tree -m -u`,
we would need to look at:

. `bind` lines in the current `HEAD` commit.

. `bind` lines in the commit we are switching to.

. subproject binding information in the index file.

to make sure we do sensible things.

Just like until very recently we did not allow switching
branches when two-way merge would lose local changes, we can
start by refusing to switch branches when the subprojects bound
in the index do not match what is recorded in the `HEAD` commit.

Because in this round of the proposal we do not use the
`$GIT_DIR/bind` file nor separate branches to keep track of
heads of the subprojects, there is nothing else other than the
working tree and the index file that needs to be updated when
switching branches.


Merging
-------

Merging two branches of the toplevel projects can use the
traditional merging mechanism mostly unchanged.  The merge base
computation can be done using the `parent` ancestry information
taken from the two toplevel project branch heads being merged,
and merging of the whole tree can be done with a three-way merge
of the whole tree using the merge base and two head commits.
For reasons described later, we would not merge the subproject
parts of the trees during this step, though.

When the two branch heads use different versions of subproject,
things get a bit tricky.  First, let's forget for a moment about
the case where they bind the same project at different location.
We would refuse if they do not have the same number of `bind`
lines that bind something at the same subdirectories.

------------
$ git merge 'Merge in a side branch' HEAD side
error: the merged heads have subprojects bound at different places.
 ours:
	linux-2.6/
	appliance/
 theirs:
	kernel/
	gadget/
	manual/
------------

Such renaming can be handled by first moving the bind points in
our branch, and redoing the merge (this is a rare operation
anyway).  It might go like this:

------------
$ git bind-projects \
	$kernel_commit kernel/ \
	$gadget_commit gadget/
$ git commit -m 'Prepare for merge with side branch'
$ git merge 'Merge in a side branch' HEAD side
error: the merged heads have subprojects bound at different places.
 ours:
	kernel/
	gadget/
 theirs:
	kernel/
	gadget/
	manual/
------------

Their branch added another subproject, so this did not work (or
it could be the other way around -- we might have been the one
with `manual/` subproject while they didn't).  This suggests
that we may want an option to `git merge` to allow taking a
union of subprojects.  Again, this is a rare operation, and
always taking a union would have created a toplevel project that
had both `kernel/` and `linux-2.6/` bound to the same Linux
kernel project from possibly different vintage, so it would be
prudent to require the set of bound subprojects to exactly match
and give the user an option to take a union.

------------
$ git merge --union-subprojects 'Merge in a side branch HEAD side
error: the subproject at `kernel/` needs to be merged first.
------------

Here, the version of the Linux kernel project in the `side`
branch was different from what our branch had on our `bind`
line.  On what kind of difference should we give this error?
Initially, I think we could require one is the fast forward of
the other (ours might be ahead of theirs, or the other way
around), and take the descendant.

Or we could do an independent merge of subprojects heads, using
the `parent` ancestry of the bound subproject heads to find
their merge-base and doing a three-way merge.  This would leave
the merge result in the subproject part of the working tree and
the index.

[NOTE]
This is the reason we did not do the whole-tree three way merge
earlier.  The subproject commit bound to the merge base commit
used for the toplevel project may not be the merge base between
the subproject commits bound to the two toplevel project
commits.

So let's deal with the case to merge only a subproject part into
our tree first.


Merging subprojects
-------------------

An operation of more practical importance is to be able to merge
in changes done outside to the projects bound to our toplevel
project.

------------
$ git pull --subproject=kernel/ git://git.kernel.org/.../linux-2.6/
------------

might do:

. fetch the current `HEAD` commit from Linus.
. find the subproject commit bound at kernel/ subtree.
. perform the usual three-way merge of these two commits, in
  `kernel/` part of the working tree.

After that, `git commit \--subproject` option would be needed to
make a commit.

[NOTE]
This suggests that we would need to have something similar to
`MERGE_HEAD` for merging the subproject part.

^ permalink raw reply

* [ANNOUNCE] quilt2git / git2quilt
From: Tejun Heo @ 2006-01-23  2:33 UTC (permalink / raw)
  To: lkml, git

Hello, all.

I've made up two little perl scripts to convert back and forth between 
quilt patch series and git commit series.  Hope someone finds it useful.

http://home-tj.org/wiki/index.php/Misc

Thanks.

-- 
tejun

^ permalink raw reply

* Re: Notes on Subproject Support
From: Daniel Barkalow @ 2006-01-23  3:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Petr Baudis
In-Reply-To: <7v3bjfafql.fsf@assigned-by-dhcp.cox.net>

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

> Also note that in this round of proposal, there is no separate
> branches that keep track of heads of subprojects.

Interesting; I think it may become useful to allow for such heads, but we 
can deal with that when it arises. (e.g., maybe you want to use topic 
branches in the kernel development you do in the linux-2.6/ subdirectory 
of your superproject working tree; so long as the core isn't using refs 
for its own purposes, this is up to the user to keep straight and we can 
help later when we have usage notes)

> ============
> 
> Let's not forget to add the `Makefile`, and check the whole
> thing out from the index file.
> ------------
> $ git add Makefile

Maybe bind-projects should be "add-projects", to match "add", which has a 
similar effect at the user level?

> $ git checkout-index -f -u -q -a
> ------------
> 
> Now our directory should be identical with the `current`
> directory.  After making sure of that, we should be able to
> commit the whole thing:
> 
> ------------
> $ diff -x .git -r ../current ../combined
> $ git commit -m 'Initial toplevel project commit'
> ------------
> 
> Which should create a new commit object that records what is in
> the index file as its tree, with `bind` lines to record which
> subproject commit objects are bound at what subdirectory, and
> updates the `$GIT_DIR/refs/heads/master`.  Such a commit object
> might look like this:
> ------------
> tree 04803b09c300c8325258ccf2744115acc4c57067

Does this tree include trees for the bound projects?

> bind 5b2bcc7b2d546c636f79490655b3347acc91d17f linux-2.6/
> bind 0bdd79af62e8621359af08f0afca0ce977348ac7 appliance/
> author Junio C Hamano <junio@kernel.org> 1137965565 -0800
> committer Junio C Hamano <junio@kernel.org> 1137965565 -0800
> 
> Initial toplevel project commit
> ------------
> 
> 
> Making further commits
> ----------------------
> 
> The easiest case is when you updated the Makefile without
> changing anything in the subprojects.  In such a case, we just
> need to create a new commmit object that records the new tree
> with the current `HEAD` as its parent, and with the same set of
> `bind` lines.
> 
> When we have changes to the subproject part, we would make a
> separate commit to the subproject part and then record the whole
> thing by making a commit to the toplevel project.  The user
> interaction might go this way:
> ------------
> $ git commit
> error: you have changes to the subproject bound at linux-2.6/.
> $ git commit --subproject linux-2.6/
> $ git commit
> ------------

I think "cd linux-2.6 && git commit" should work for the subproject, too, 
but that can be a later enhancement.

> With the new `--subproject` option, the directory structure
> rooted at `linux-2.6/` part is written out as a tree, and a new
> commit object that records that tree object with the commit
> bound to that portion of the tree (`5b2bcc7b` in the above
> example) as its parent is created.

And the commit is written to the index, in the special slot for the 
subproject, replacing its parent, I assume.

> Switching branches
> ------------------
> 
> Along with the traditional two-way merge by `read-tree -m -u`,
> we would need to look at:
> 
> . `bind` lines in the current `HEAD` commit.
> 
> . `bind` lines in the commit we are switching to.
> 
> . subproject binding information in the index file.
> 
> to make sure we do sensible things.

This is one place I think storing the bindings in the commit is awkward. 
read-tree deals in trees (hence the name), but will need information from 
the commit.

I think it should be possible to hide the existance of subtrees in an 
add-on to the struct tree API such that code that doesn't handle it 
specifically doesn't see a difference, similarly to how the index file can 
be handled. (parse_tree would fill out the structure as if the subproject 
were a tree instead of a commit, assuming that the structure it's 
pretending to be is the full tree, but there would be an additional 
field for the commit if it's a subproject, until we've gone through 
everything to make it work with subprojects).

I'm hoping to kill off the other tree object parser, which is only used by 
ls-tree and diff-index at this point, but my workstation's home directory 
hard drive seems to have gotten weirdly messed up at the hardware level 
(and seems to have lost a lot of the contents of unused storage, or 
something), so this may take a little while. At that point, whatever 
special things we do in tree objects can be handled automatically with 
changes only to a single location.

	-Daniel
*This .sig left intentionally blank*

^ 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