I am attempting to write an update
hook for git that bounces if a submodule is being updated to a commit ID that does not exist in the submodule's upstream repository. To say it another way, I want to force users to push changes to the submodule repositories before they push changes to the submodule pointers.
One caveat:
- I only want to test submodules whose bare, upstream repositories exist on the same server as the parent repository. Otherwise we start having to do crazy things like call 'git clone' or 'git fetch' from within a git hook, which would not be fun.
I have been playing around with an idea but it feels like there must be a better way to do this. Here is what I was planning on doing in the update hook:
- Check the refname passed into the hook to see if we are updating something under
refs/heads/
. If not, exit early. - Use
git rev-list
to get a list of revisions being pushed. - For each revision:
- Call
git show <revision_id>
and use a regular expression that looks to see if a submodule was updated (by searching for `+Subproject commit [0-9a-f]+). - If this commit did change a submodule, get the contents of the
.gitmodules
files as seen by that particular commit (git show <revision_id>:.gitmodules
). - Use the results of 3.1 and 3.2 to get a list of submodule URLs and their updated commit IDs.
- Check this list created in 3.3 against an external file that maps submodule URLs to local bare git repositories on the filesystem.
cd
to the paths found in 3.4 and executegit rev-parse --quiet --verify <updated_submodule_commit_id>
to see if that commit exists in that repository. If it does not, exit with a non-zero status.
- Call
(Note: I believe the results of 3.2 can potentially be cached across revisions as long as the output to git rev-parse --quiet --verify <revision_id>:.gitmodules
doesn't change from one revision to the next. I left this part out to simplify the solution.)
So yeah, this seems pretty complex, and I can't help but wonder if there are some internal git commands that might make my life a lot easier. Or maybe there is a different way to think about the problem?