Friday, 25 November 2016

Gerrit, Jenkins and git submodules

In our lab, we use git repositories hosted with Gerrit and Jenkins as a CI system. When working with git submodules, a change in a submodule is most often associated with a change in the super project. When pushing both of them to Gerrit with
cd submodule
git push origin HEAD:refs/for/master
cd ..
git push origin HEAD:refs/for/master
the build fails on Jenkins because it is not able to find the used submodule revision in the downloaded data for the submodule.

The reason boils down to git fetch only downloading refs/heads/*, while the uncommitted changes in Gerrit are at refs/changes/*

No reason to despair though, because you can actually tell git fetch to download all kinds of refs:
git submodule foreach git config \ 
  remote.origin.fetch "+refs/changes/*:refs/remotes/origin/changes/*"
git config \
  remote.origin.fetch "+refs/changes/*:refs/remotes/origin/changes/*"
git fetch 
git submodule update
Now, all changes from Gerrit are available locally.

For Jenkins, disabling the internal submodule handling and adding the following lines to the build scripts is good enough:
git submodule update --force --init --remote
git submodule foreach git config --replace-all \
  remote.origin.fetch "+refs/changes/*:refs/remotes/origin/changes/*" "changes"
git submodule foreach git fetch
git submodule update
Because the git log output can become a bit overwhelming with all the refs, using an alias with the following parameters results in a reduced log with only the refs that are actually included in a branch
log --graph --decorate --pretty=oneline --abbrev-commit  --exclude=*/changes/* --all
You can still get a log with all refs by manually adding another --all at the end.

No comments:

Post a Comment