Search code examples
gitversion-controlgit-submodules

Generate patch of uncommitted changes for git repo and submodules


I have a git repo foo that has several submodules in their own folders bar and baz (the actual repo is eclipse.platform.releng.aggregator). I need to generate patches for changes to those repos.

I can generate a patch with git --no-pager diff > file.patch which is fine for changes to foo but doesn't report changes in the bar or baz, the submodules.

Using git submodule --quiet foreach --recursive git --no-pager diff > file (cribbed from this answer) nearly works but the diffs don't include the names of the folders the subrepos live in.

Presently I work round this by hacking the paths into the patches by hand but that only works for simple patches and the scripting solutions I can think of (e.g. getting the subrepo names from git, changing to the folders, generating the patches in folders) mean I can't use a simple git apply to reapply the patches later.

Is there a way to get git to diff the subrepos directly rather than through foreach so the generated patches can be simply applied?


Solution

  • With the clue offered by @larsks I managed to find the following one liner which does what I need:

    git submodule --quiet foreach --recursive 'export NAME="${PWD##*/}"; git --no-pager diff --src-prefix="a/${NAME}/" --dst-prefix="b/${NAME}/"'
    

    This adds the folder name of the subfolders into the patch generated with git diff so I can just run git apply in the parent folder even if the patch spans more than one of the submodules. Note however that it only works because my submodules are all one folder below the main repo folder. That could be overcome if needed by changing the code used to set NAME to something a little more clever.