Re: Notes on Subproject Support

From: Junio C Hamano <>
Date: 2006-01-23 15:36:23
Daniel Barkalow <> writes:

>> tree 04803b09c300c8325258ccf2744115acc4c57067
> Does this tree include trees for the bound projects?

Yes, this part has not been changed from earlier thoughts.

>> bind 5b2bcc7b2d546c636f79490655b3347acc91d17f linux-2.6/
>> bind 0bdd79af62e8621359af08f0afca0ce977348ac7 appliance/
>> author Junio C Hamano <> 1137965565 -0800
>> committer Junio C Hamano <> 1137965565 -0800

The tree 04803b...  tree has everything.  If you run git-ls-tree
on 04803b... would have a tree object recorded at linux-2.6, and
it is the same as the tree associated with the commit 5b2bcc...

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

It's just a matter of Porcelain scripting, so that is probably
true.  However I do not want people to get too used to it and
expect "cd Documentation && git commit" to work in git.git

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

Yes.  It would probably be done with `update-index --bind` to
update the bound subproject commit there.

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

That's why it is 'along with'.  Dealing with binding information
can be done between commits and index without bothering tree
objects.  read-tree would not have to deal with it, and I think
keeping it that way is probably a good idea.

In other words, I think the design so far does not require us to
touch tree objects at all, and I'd be happy if we do not have to.

One reason I started the bound commit approach was exactly
because I only needed to muck with commit objects and did not
have to touch trees and blobs; after trying to implement the
core level for "gitlink", which I ended up touching quite a lot
and have abandoned for now.

Here is an update to the still-WIP draft.

-- >8 --
Separate role of read-tree and update-index cleaner

The previous draft prematurely merged what read-tree --prefix
does with what update-index --bind would do.  Keep them separate
for now until we know what the common patterns would be.

Introduce 'update-index --unbind'.  We would probably need a new
command that extracts bind information out of index when we
start writing Porcelainish, but it is not specified yet.

Attempt to clarify what the "merging into subproject part" would
do a bit.  "git pull --subproject=" is fetch + merge, just like
the current subproject-unaware 'git pull' is.

diff --git a/Subpro.txt b/Subpro.txt
index 4036e71..837cab8 100644
--- a/Subpro.txt
+++ b/Subpro.txt
@@ -95,19 +95,22 @@ $ git bind-projects \
 	$gadget_commit appliance/
-This would do an equivalent of:
+This would probably do an equivalent of:
+$ rm -f "$GIT_DIR/index"
 $ git read-tree --prefix=linux-2.6/ $kernel_commit
 $ git read-tree --prefix=appliance/ $gadget_commit
+$ git update-index --bind linux-2.6/ $kernel_commit
+$ git update-index --bind appliance/ $gadget_commit
 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
+which subtree in the current working tree and index.  This
 proposal instead records that information in the index file
-when `--prefix=linux-2.6/` is given to `read-tree`.
+with `update-index --bind` command.
 Also note that in this round of proposal, there is no separate
 branches that keep track of heads of subprojects.
@@ -258,9 +261,11 @@ our branch, and redoing the merge (this 
 anyway).  It might go like this:
-$ git bind-projects \
-	$kernel_commit kernel/ \
-	$gadget_commit gadget/
+$ git reset
+$ git update-index --unbind linux-2.6/
+$ git update-index --unbind appliance/
+$ git update-index --bind $kernel_commit kernel/
+$ git update-index --bind $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.
@@ -336,7 +341,55 @@ make a commit.
 This suggests that we would need to have something similar to
-`MERGE_HEAD` for merging the subproject part.
+`MERGE_HEAD` for merging the subproject part.  In the case of
+merging two toplevel project commits, we probably can read the
+`bind` lines from the `MERGE_HEAD` commit and either our `HEAD`
+commit or our index file.  Further, we probably would require
+that the latter two must match, just as we currently require the
+index file matches our `HEAD` commit before `git merge`.
+Just like the current `pull = fetch + merge` semantics, the
+subproject aware version `git pull \--subproject=frotz` would be
+a `git fetch \--subproject=frotz` followed by a `git merge
+\--subproject=frotz`.  So the above would be:
+. Fetch the head.
+$ git fetch --subproject=kernel/ git://
+which would do:
+. fetch the commit chain from the remote repository.
+. write something like this to `FETCH_HEAD`:
+3ee68c4...\tfor-merge-into kernel/\tbranch 'master' of git://.../linux-2.6
+. Run `git merge`.
+$ git merge --subproject=kernel/ \
+    'Merge git://.../linux-2.6 into kernel/' HEAD 3ee68c4...
+. In case it does not cleanly automerge, `git merge` would write
+the necessary information for a later `git commit` to use in
+`MERGE_HEAD`.  It may look like this:
+3ee68c4af3fd7228c1be63254b9f884614f9ebb2	kernel/
+With this, a later invocation of `git commit` to record the
+result of hand resolving would be able to notice that:
+. We should be first resolving `kernel/` subproject.
+. The remote `HEAD` is `3ee68c4...` commit.
+. The merge message is `Merge git://.../linux-2.6 into kernel/`.
+and make a merge commit, and register that resulting commit in
+the index file using `update-index --bind` instead of updating
+*any* branch head (remember, we do not use separate branches to
+keep track of subproject heads anymore).

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to
More majordomo info at
Received on Mon Jan 23 15:38:26 2006

This archive was generated by hypermail 2.1.8 : 2006-01-23 15:38:36 EST