git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "Imran M Yousuf" <imyousuf@gmail.com>
Cc: "Lars Hjemli" <hjemli@gmail.com>,
	git@vger.kernel.org,
	"Imran M Yousuf" <imyousuf@smartitengineering.com>
Subject: Re: [PATCH] - Added recurse command to git submodule
Date: Wed, 09 Jan 2008 20:09:05 -0800	[thread overview]
Message-ID: <7vy7ay8gpq.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <7bfdc29a0801091927v4eb65a60qf5b185924b9d1e44@mail.gmail.com> (Imran M. Yousuf's message of "Thu, 10 Jan 2008 09:27:20 +0600")

"Imran M Yousuf" <imyousuf@gmail.com> writes:

>> Also, some commands cannot be made recursive by driving them
>> from a higher level recursive wrapper.  "git submodule recursive
>> log" would not make much sense, not only because the order of
>> the log entries are output from different invocations would not
>> be useful, but because the revision range specifier would need
>> to be different in different submodules (e.g. library submodules
>> and application submodule will not share version name namespace,
>> i.e. "log v1.0..v2.0" is undefined, and worse yet, running "log
>> v1.0:path/to/sub..v2.0:path/to/sub" in a submodule when running
>> "log v1.0..v2.0" in the toplevel is not a correct solution
>> either in general).
>
> What is you suggestion in such cases Junio?

Not doing it using the wrapper approach, but actually have the
underlying command be aware of the recursiveness.

Let's take a small example of library project contained within
an application project as a submodule (think of ffmpeg in
mplayer or something like that).

Library project has this history:

             3---A
            /
    ---1---2---4---B

while the application project has this history:

    ---5---X---6---Y

and at time X (and before that point), it binds commit A at a
directory "lib/" as a submodule.  The commit 6 (between X and Y)
changes it to bind commit B there instead.  You have both
toplevel and submodule checked out.  The HEAD in the application
project is at Y while the HEAD in the library project is at B.
Your work tree may or may not be clean.

How would a recursive "git diff" between two versions should
behave, with various arguments?

	$ git diff X Y

Currently this will say something like:

	--- a/lib
        +++ b/lib
	@@ -1 +1 @@
	-Subproject commit A
        +Subproject commit B

You can make it recurse naturally by recursing into lib/
subproject instead (at least conceptually this is a simple
change but it may not be so straightforward, implementation
wise).

How would you handle this, then?

	$ git diff X Y -- Documentation/

A wrapper approach that blindly descends into lib/ and runs "git
diff X Y -- Documentation/" there is wrong at two levels.
Commits X and Y do not even exist there, and Documentation/
pathspec is wrong.  The documentation may be called docs/ in the
library project, or it may not even exist, and that is not what
the user asked to see anyway.  If the user were interested in
the documentation of the library, the pathspec would have said
lib/Documentaiton/ (or lib/docs/).

For "git diff", the right solution happens to be invoking the
command recursively without any pathspec.  The higher level
chose to recurse into the directory already because it saw
changes --- by definition everything underneath is interesting.

	Side note.  If we support asking for lib/docs/ from the
	toplevel, the recursive one would use docs/ as its
	pathspec in this case.  

The point is that pathspec needs to be munged from the higher
level iteration, and more importantly that is pretty much
specific to "git diff".  "git diff" itself needs to have the
knowledge of what to do when working recursively --- wrapper
approach would not work well.

How would a recursive version of "git log" work, then?

	$ git log X..Y

Again, a naive wrapper approach of descending into lib/ and
running "git log X..Y" recursively would not give us anything
useful.

But if "git log" itself knew recursive behaviour, it should be
able to do much better.  It can show Y and 6, and at that point
it could notice that between 6 and its parent X the commit bound
at lib/ as submodule has changed from A to B, so it could insert
the log from submodule there.  If we were running with
--left-right, we might see something like this:

	>Y
	>6
            >B
            >4
            >2
            <A
            <3
	    -2
	-X

If the toplevel "git log" was invoked with a pathspec, again, it
needs to be adjusted to submodule.

I think a wrapper approach could be adequate for simple things
like "checking out the whole tree including all of its
submodules".  But even that has to be done carefully.

What should this command (recursive version) do?

	$ git checkout X

The toplevel detaches head at commit X, and notices that it
contains a submodule at lib/ whose HEAD now needs to point at
A.  The recursive command should go there, and say

	$ git checkout A

What should it do when this checkout cannot be made because your
work tree is not clean?  Ideally, it should abort and roll-back
the checkout of commit X at the toplevel (otherwise you will end
up in a mixed state).

There are more interesting issues when you bring up a situation
where X and Y binds that library project at different place
(i.e. submodule was moved inside the toplevel), which I avoided
to talk about here to keep this message short.

  reply	other threads:[~2008-01-10  4:09 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-09  5:51 [PATCH] - Added recurse command to git submodule imyousuf
2008-01-09  8:38 ` Junio C Hamano
2008-01-09  8:55   ` Imran M Yousuf
2008-01-09 10:42   ` Lars Hjemli
2008-01-09 20:26     ` Junio C Hamano
2008-01-10  3:27       ` Imran M Yousuf
2008-01-10  4:09         ` Junio C Hamano [this message]
2008-01-10  4:50           ` Imran M Yousuf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7vy7ay8gpq.fsf@gitster.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=hjemli@gmail.com \
    --cc=imyousuf@gmail.com \
    --cc=imyousuf@smartitengineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).