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

Re: git diff across submodules

From
Jens Lehmann <jens.lehmann@web.de>
Date
Sep 20, 2012, 19:51 UTC
Message-ID
<505B73CE.5030009@web.de>
In-Reply-To
<7v4nmtfxvx.fsf@alter.siamese.dyndns.org>
Am 20.09.2012 00:31, schrieb Junio C Hamano:
Show 73 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
> 
>> 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.

That's pretty cool! Even though diff options like --stat and --name-only still won't take into account what happened inside the submodule this approach makes it possible to see the diff recursively. Wouldn't it make sense add this script to contrib (after teaching it new and removed submodules and documenting its use in a few lines after the shebang)?

Previous: Junio C HamanoNext: Junio C Hamano
Message 5 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.