git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git diff across submodules

From
Junio C Hamano <gitster@pobox.com>
Date
Sep 19, 2012, 22:31 UTC
Message-ID
<7v4nmtfxvx.fsf@alter.siamese.dyndns.org>
In-Reply-To
<7vobl3m8pb.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
Show 18 quoted lines
> I also suspect that you do not have to change "git diff" at all to
> show the patch recursively by using the attribute mechanism (look in
> Documentation/gitattributes.text for a string GIT_EXTERNAL_DIFF).
> It might be just as simple as doing this:
>
> 	echo >.gitattributes "/lib/frotz diff=subrecurse" 
> 	git config diff.subrecurse.command $HOME/bin/diff-subrecurse
>       cat >$HOME/bin/diff-subrecurse <<\-EOF
> 	#!/bin/sh
>       path=$1 old_hex=$3 new_hex=$6
>       unset GIT_DIR
>       cd "$path" || exit 1
>       git diff "$old_hex" "$new_hex"        
>       EOF
>       chmod +x $HOME/bin/diff-subrecurse
>
> The corner cases like "new submodule", "removed submodule" are left
> as an exercise to the reader ;-)

It turns out that essentially the above outline I concocted in my MUA is usable almost as-is.

Here is what I ended up with.
 * In .git/config of the superproject, I added this:
        [diff "submodule-recurse"]
		command = src/bin/diff-submodule-recurse
 * In the superproject, src/bin/diff-submodule-recurse has this
   (this is probably whitespace damaged---the lines must be indented
   by HT for the here document to correctly work):
        #!/bin/sh
        # $1   $2       $3      $4       $5       $6      $7
        # path old-file old-hex old-mode new-file new-hex new-mode
        case "$#,$4,$7" in
        7,160000,160000) ;;
        *)      echo "diff --git a/$1 b/$1"
                echo "(punt)"
                exit
                ;;
        esac
        unset GIT_DIR
        cd "$1" || {
                cat <<-\EOF
                diff --git a/$1 b/$1
                (cannot chdir to $1)
		-Subproject commit $3
		+Subproject commit $6
                EOF
        }
        git --no-pager diff --src-prefix="s/$1/" --dst-prefix="m/$1/" "$3" "$6"
 * In .gitattributes of the superproject, I have this:
        /var	diff=submodule-recurse

The superproject in this case is a repository to control what I have in my $HOME directory (e.g. it has src/dot/Makefile that builds and installs the appropriate dotfiles, src/bin/Makefile that builds and installs to $HOME/bin, etc.), and one subdirectory, 'var', is a submodule that is only cloned to some but not all machines I clone this superproject to.

With this setting, things like
	$ git diff HEAD~20
show differences with recursion into the var/ submodule just fine.
Previous: Junio C HamanoNext: Jens Lehmann
Message 4 of 6 in “git diff across submodules”
  1. Kenny SimpsonSep 18, 2012
  2. Jens LehmannSep 18, 2012
  3. Junio C HamanoSep 18, 2012
  4. Junio C HamanoSep 19, 2012
  5. Jens LehmannSep 20, 2012
  6. Junio C HamanoSep 20, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.