3

I have a git repo where feature branches are merged into a master branch, and there are version tags on some of these merge commits. Jenkins builds the master branch from a shallow clone, but needs to use the version numbers in the tags, so there's some depth:

git fetch --depth=10 origin +refs/heads/master:refs/remotes/origin/master +refs/tags/v*:refs/tags/v*

The strange thing is that sometimes git describe on the HEAD picks a very old version number. Now I understand that there could be degenerate commit graphs where a 10-deep shallow clone would miss important edges. For example this one:

     F1-----------------------F2-----------------------F3    feature branch
    /                                                    \
v1.0---{ 20 commits here }---v2.0---{ 20 commits here }---M  master branch

The shallow clone would not contain the complete path between the commit with the v2.0 tag and the tip of master, M, so git describe M would only find the v1.0 tag, which is at a mere 4 commits depth. Similarly, it could happen that there's a version tag in the history of both of the parents of the commit M, but the path between the version tags is not completely fetched, so git describe cannot determine which is the newer tag, and picks the wrong one.

But this doesn't seem to be the case when this problem actually happens: locally cloning the repo the same way as Jenkins does always retrieves the complete graph between v1.0 and M, and git describe uses the v2.0 tag as expected. I don't know how the local repository on Jenkins looks like when the problem happens, as the workspace is wiped by the time I could investigate. But shouldn't git describe be deterministic? How come that I cannot even reproduce the problem? Why is it happening only on shallow clones, if the relevant subgraph of the involved commits is always fully fetched?

  • 2
    I would add `git log --oneline --graph --decorate --all` inside your Jenkins recipe, that way you would see exactly what it's working with. Basically, yes, you can look at the local repository on Jenkins by adding the inspection code in your recipe itself. You should be able to see the output of those commands in the CI logs. – joanis Sep 12 '22 at 14:45
  • My hypothesis is that it's doing the shallow clone in its own way which might not be exactly the same as the command you ran on your local machine, and that git log command I provided should give you enough information to verify that. – joanis Sep 12 '22 at 14:46
  • Worth mention: Jenkins is written in Java and there is a Java implementation of Git (JGit) and some Jenkins operations may use this *instead of* Git, leading to odd interoperability issues. These tend to happen only with lesser-used features. Meanwhile, though, there's also some sort of obscure bug in "git describe" that I don't think has been properly characterized or fixed yet. – torek Sep 12 '22 at 22:27
  • @torek I don't think JGit would be an issue here. When the initial fetch happens, Jenkins logs to the console the git version: `> git --version # 'git version 2.37.1'` which looks OK. All other git operations in the pipeline are done from `bash`, so no JGit there. – Dániel Szoboszlay Sep 12 '22 at 22:46
  • @joanis That's a good idea, I'll save the graph as an artefact. It may take a while though until the problem turns up again though... – Dániel Szoboszlay Sep 12 '22 at 22:51

0 Answers0