There is a bug, that updates for any changes that are not causing new creation dates (like comment edits) are discarded. Because the update time is not checked, only the creation date. It is probably safer to always overwrite items in the cache by keying on the id.
As I'll switch to reviewing another more important PR before this is finished I'll add some general comments I had.
This seems like it implements generic git functionality, so why not use one…
Can be merged, previous review was in error. Inline comments can be addressed in followup.
I don't think this is intended as this doesn't do everything to handle a repo add issue. Everything below in this function is dead code, due to the return above. This needs to be adressed before merge.
There is no comparison before the return that this is expected, is that a mistake?
The difference between this and the above is not understandable from the name. The above is GitDirectoryListFiles and this is GitDirectoryListFilesAndSubmodulesRecursively? Also maybe it is better to move the distinction (recursive, include files, include directories, include submodules) into the arguments.
Move these into run() and remove the global calls, to not duplicate them from main.go and actually test them?