Re: [PATCH] - Added recurse command to git submodule

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



"Imran M Yousuf" <imyousuf@xxxxxxxxx> 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.


-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux