git: list of all changed files including those in submodules
Solution 1
Update 2017: as I mentioned in "see diff of commit on submodule in gitlab",
-
Git 2.11 (Nov. 2016) introduces
git diff --submodule=diff
Git 2.14 (Q3 2017) will improve that by recursing into nested submodules.
See commit 5a52214 (04 May 2017) by Stefan Beller (stefanbeller
).
(Merged by Junio C Hamano --gitster
-- in commit a531ecf, 29 May 2017)
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+)
Solution 2
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
Solution 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"
.
Solution 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.
Solution 5
A Windows variant of https://stackoverflow.com/a/13169898/5438298 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).
4eyes
Updated on August 15, 2022Comments
-
4eyes over 1 year
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?
-
4eyes almost 12 yearsThank 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?
-
BlacKow almost 12 yearsSo you were committing submodules as well? I guess you will need some sort of a script...
-
Zaz over 7 years
git submodule update --remote --recursive
followed by yourforeach
diff
command shows nothing (because it just runsgit diff
in each submodule). How can we see the diff of the update we just ran? -
Zaz over 7 yearsProTip™: Save this as
git-diff-submodules
and run it withgit diff-submodules
-
VonC over 7 years@Zaz 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 simplegit diff
in the parent repo), you can then go in the submodule, and do agit diff
between those two SHA1. -
Zaz over 7 yearsI thought the questioner was looking for a way to do that automatically.
-
timblaktu over 4 years@Zaz What is
git diff-submodules
? -
CodeMonkey almost 3 yearsI'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.
-
VonC almost 3 years@CodeMonkey Not sure: that would be a good question on its own.
-
CodeMonkey almost 3 years@VonC 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.
-
VonC almost 3 years@CodeMonkey Got it. That seems not very convenient indeed.
-
Nikolai Ehrhardt over 2 yearsyes it does, but when I appliy --name-only it shows only submodule name, so i want changed files inside submod ... but not filecontent
-
user64204 about 2 yearsThis answer is incorrect as question is specific about --name-only which will not work.
-
user64204 about 2 yearsWill not work with "Renamed"
-
VonC about 2 years@user64204 Agreed. That is what the previous comment from CodeMonkey alluded to.
-
Nikolai Ehrhardt about 2 yearsthx for the hint.