git: list of all changed files including those in submodules
Asked Answered
V

8

49

I would like to get a list of all files, which have changed betweet two commits including those in submodules.

I know I can do this:

git diff --name-only --diff-filter=ACMR ${revision} HEAD

It returns a list of files, including the submodule-path, but not the files within.

Example: I've updated a submodule. I commited the super-project. Now I want to get a list of all files which have been modified.

Do you know a way to get this done?

Vivianne answered 25/5, 2012 at 15:21 Comment(0)
A
61

Update 2017: as I mentioned in "see diff of commit on submodule in gitlab",


Original 2012 answer (pre 2017 Git 2.14)

Maybe a simple line would be enough:

git submodule foreach --recursive git diff --name-status

That would actually list files in submodules within submodules.
(The --recursive option comes from git1.7.3+)

Anceline answered 27/10, 2012 at 13:39 Comment(9)
git submodule update --remote --recursive followed by your foreach diff command shows nothing (because it just runs git diff in each submodule). How can we see the diff of the update we just ran?Johanna
@Johanna an update --remote would change the gitlink (SHA1 representing the submodule commit checked out). If you can get the previous gitlink sha1 and the current one (with a simple git diff in the parent repo), you can then go in the submodule, and do a git diff between those two SHA1.Anceline
I thought the questioner was looking for a way to do that automatically.Johanna
I'm lookingfor the same as OP, the --submodule=diff works wonderfully, except in combination with --name-only. I need the files that changed, including the submodules. Is that somehow possible? git version is 2.17.1. Recursing doesn't work either, because I need to check against a specific merge-base on the top level repo.Mollescent
@Mollescent Not sure: that would be a good question on its own.Anceline
@Anceline OPs question is with name-only, I now used a workaround, I basically use your command, filter it with grep for the lines starting with +++ and --- and then cut the first part and pass that to uniq.Mollescent
@Mollescent Got it. That seems not very convenient indeed.Anceline
This answer is incorrect as question is specific about --name-only which will not work.Isa
@Isa Agreed. That is what the previous comment from CodeMonkey alluded to.Anceline
A
5

You can find out what version a submodule was at, as of a given parent module commit, using git ls-tree:

subcommit=$(git ls-tree $parentcommit $submodulepath | awk '{print $3}')

So here's a script that should get you much of the way there, up to output formatting and such:

#!/bin/sh

function compare {
    if [[ -z "$3" ]];
        then git diff --name-only --ignore-submodules=all --diff-filter=ACMR "$1" "$2"
        else git diff --name-only --ignore-submodules=all --diff-filter=ACMR "$1" "$2" | awk -v r=$3 '{ print "" r "/" $0}'
    fi

    for submodule in `git submodule | awk '{print $2}'`
    do
        old=$(git ls-tree $1 $submodule | awk '{print $3}')
        new=$(git ls-tree $2 $submodule | awk '{print $3}')
        (cd $submodule; compare $old $new $submodule)
    done
}

compare "$1" "$2"

This will output all files like this (although Base is a submodule): HtmlTemplates/Css/Screen.css Base/Php/Classes/Helper.php

Afghanistan answered 1/11, 2012 at 1:46 Comment(0)
M
4

July 8,2017

Now to get a diff including that of a submodule, you can use the command -

git diff --submodule=diff

Note - This has been introduced with Git 2.14.0

"git diff --submodule=diff" now recurses into nested submodules.

Megaphone answered 8/7, 2017 at 8:58 Comment(1)
yes it does, but when I appliy --name-only it shows only submodule name, so i want changed files inside submod ... but not filecontentFasten
I
4

I'm surprised nobody has said this, but as of v1.8.1 you can do this:

git config diff.submodule diff

and now all git diff commands for two revs will also diff the contents (not just the refs) of submodules.

Ironic answered 14/3, 2022 at 12:30 Comment(0)
B
3

So, the very straightforward script that lists all changes compared to a revision

#!/bin/sh
echo "Listing changes for super module"
git diff $1 --name-only
subs=(`git submodule | awk '{print $2}'`)
for sub in ${subs[*]}; do
   lastrevision=`git diff  $1 $sub | fgrep "Subproject" | head -n1 | awk '{print $3}'`
   cd $sub
   echo "Listing changes for $sub"
   git diff $lastrevision --name-only
   cd ..
done

it takes one argument - revision you want to compare with. Make sure that there is fgrep "Subproject", not fgrep "Submodule".

Blunderbuss answered 26/5, 2012 at 1:15 Comment(4)
Thank you. This will show me the files which have changed since the last commit of the submodules. But how do I get all files which have changed (including submodules) between to revisions of the super-project?Vivianne
So you were committing submodules as well? I guess you will need some sort of a script...Blunderbuss
ProTip™: Save this as git-diff-submodules and run it with git diff-submodulesJohanna
@Johanna What is git diff-submodules?Houseman
V
2

A Windows variant of https://mcmap.net/q/351233/-git-list-of-all-changed-files-including-those-in-submodules by Jamey Sharp would be

@echo off
if NOT %1.==. goto has_rev1

@echo git diff --name-only including submodules
@echo usage:
@echo ^ ^ %~n0 ^<revision1^> [^<revision2^>^|HEAD]
@exit /b 1

:has_rev1
setlocal
set rev1=%1
if %2.==. (set rev2=HEAD) else (set rev2=%2)

call :show_diff %rev1% %rev2%
exit /b
::eof

:show_diff
setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=*" %%l in ('git --no-pager diff --name-only --ignore-submodules^=all --line-prefix^=%3 %1 %2') do set fwds=%%l & set bcks=!fwds:/=\! & echo !bcks! 
endlocal
::git submodule is too slow for this
::for /f "tokens=2" %%d in ('git submodule') do call :subm %1 %2 %%d %3
if exist .gitmodules for /f "tokens=1,3*" %%p in (.gitmodules) do if %%p.==path. call :subm %1 %2 %%q %3
exit /b
::show_diff

:subm
setlocal
for /f "tokens=3" %%r in ('git ls-tree %1 %3') do set rev1=%%r
for /f "tokens=3" %%r in ('git ls-tree %2 %3') do set rev2=%%r

set fwdslash=%3
set bckslash=%fwdslash:/=\%

pushd %bckslash%
call :show_diff %rev1% %rev2% %4%bckslash%\
popd

endlocal
exit /b
::subm

(note that it might need a few more double quotes for spaces in the submodule names to work).

Venepuncture answered 19/2, 2019 at 13:36 Comment(0)
F
0

I use now with git 2.32.0:

git diff --submodule=diff

and parse output with regular expression pattern: "--- a/(.*)"

Fasten answered 19/1, 2022 at 11:17 Comment(3)
Will not work with "Renamed"Isa
thx for the hint.Fasten
will not work for newly added files eitherFasten
A
-1

You can use

git -c color.diff=false diff --submodule=diff HEAD~1 HEAD | sed -n -e s/^diff\ --git\ a\\///p

to just have a list of your files (with HEAD~1 and HEAD as example refs).

I prefer

git -c color.diff=false diff --submodule=diff HEAD~1 HEAD | grep -E "^(diff|Submodule)\ "

to group the files by submodules. Depending on the terminal, it can be important to use the "--no-pager" option, as shown in the following remark.

Remark: I like the complete colored diffs in a file, which can be "htmlized" for presentation afterwards:

git -c color.diff=always --no-pager diff --submodule=diff HEAD~1 HEAD > diffFileName
Anastaciaanastas answered 23/10, 2020 at 11:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.