I have repo structured in the following way:
|- project/
| |- tools/
| |- toolchain/
| |- linux/
| |- windows/
| |- code/
| |- shared/
|
Where tools
, code
and shared
are submodules. Also /toolchain/linux
and /toolchain/windows
are submodules too.
The problem is I want to switch in code
for a specific commit. To build my code I need to sync all other submodules with that commit (let's say toolchain for linux was updated and I can't build old code with latest toolchain). How to do it in git?
You need to find the corresponding commit in the superproject project
and check it out; it then will recursively check out all submodules to their stored commits.
The following code requires Unix tools (sh
, xargs
, awk
).
This pipeline
git rev-list @ code/ |
xargs -I @ sh -c "echo -n '@ '; git rev-parse @:code"
prints a list of pairs of commits IDs: a commit from the superproject where the submodule was changed, and the commit of the submodule. Filter it by the required commit in the submodule and print the commit from the project
:
git rev-list @ code/ |
xargs -I @ sh -c "echo -n '@ '; git rev-parse @:code" |
awk '$2=="$commitID_from_code" {print $1}'
Now let's automate checkout:
git rev-list @ code/ |
xargs -I @ sh -c "echo -n '@ '; git rev-parse @:code" |
awk '$2=="$commitID_from_code" {print $1}' |
xargs -r git checkout --recurse-submodules
Or git switch --detach --recurse-submodules
instead of git checkout
.
Will do nothing if the pipeline didn't find the specified commit.