Git shallow clone stragegy omits remote branches

Summary

When doing shallow fetch clones, not all remote branches are retrieved

Steps to reproduce

In our project, we want to create architecture specific branches from our main release branch. What the CI will do, checkout the current branch (gitlab-runner does this of course by default), and go over a list of available existing architecture branches to update these. To do so, it uses git branch --list --remote "origin/stable/v0/*" | sed -n -r 's|.*origin/stable/v0/||p' to obtain the list of 'v0' named branches. E.g. stable/v0/arm32v7, stable/v0/arm64v8.

However, if git fetch is set with a depth parameter (I haven't confirmed what happens if you set it to 0). We can create a scenario where not all remotes have been retrieved.

The work around for now appears to be either add a git fetch to the CI task (ugly) or (according to the documentation) set the depth to 0.

.gitlab-ci.yml
.git:
  <<: *common_parameters
  image: registry.hub.docker.com/gitscm/git:latest
  before_script:
    - git config --local user.name "${GITLAB_USER_NAME}"
    - git config --local user.email "${GITLAB_USER_EMAIL}"
    - git config --local credential.helper "cache --timeout=2147483647"
    - printf "url=${CI_PROJECT_URL}\nusername=esbs-bot\npassword=${CI_PERSONAL_TOKEN}\n\n" | git credential approve
    - git remote set-url --push origin "https://esbs-bot@${CI_REPOSITORY_URL#*@}"
  after_script:
    - git credential-cache exit

create_release_branches:
  extends: .git
  stage: release
  only:
    refs:
      - /^v\d+\.\d+$/
  except:
    refs:
      - branches # Workaround for gitlab-org/gitlab-ce#27818
  script:
    - git_tag="$(git describe --exact-match --match "v[0-9]*")"
    - git_tag_msg="$(git tag --format="%(contents:subject)%0a%0a%(contents:body)%0a%0a(Auto-created release candidate)" --list "${git_tag}")"
    - |
      git fetch --prune # Added as workaround
      for release_branch in "release" $(git branch --list --remote "origin/stable/v0/*" | sed -n -r 's|.*origin/stable/v0/||p'); do
        echo "Creating release branch '${release_branch}' from '${CI_COMMIT_REF_NAME}' (${CI_COMMIT_SHORT_SHA})"
        git checkout "${CI_COMMIT_SHA}" -b "stable/${CI_COMMIT_TAG:?}/${release_branch}"
        if [ "${release_branch}" != "release" ]; then
          sed -i 's|FROM registry.hub.docker.com/library/alpine|FROM registry.hub.docker.com/'"${release_branch}"'/alpine|g' "Dockerfile"
          git add "Dockerfile"
          git commit --message="${release_branch}: Auto-created release branch 'stable/${CI_COMMIT_TAG:?}/${release_branch}'." --no-edit
          release_prefix="${release_branch}/"
        fi
        git tag --annotate --message="${git_tag_msg:-See tag '${CI_COMMIT_TAG}'}" "${release_prefix:-}${CI_COMMIT_TAG}.0-rc1"
        git push --follow-tags origin "HEAD"
      done

Actual behavior

All remotes are available on the runner, albeit at a shallow depth of the main branch

Expected behavior

Even shallow fetch, should always retrieve all branches, not just the current branch.

Relevant logs and/or screenshots

I'll leave the repo for now, it could be found at https://gitlab.com/esbs/sandbox/package_builder-alpine.git

Proposal

As stated in https://gitlab.com/gitlab-org/gitlab-ce/issues/64686#note_192646764 not fetching all the branches is expected since we are only going far back X commits. As proposed in https://gitlab.com/gitlab-org/gitlab-ce/issues/64686#note_192646765 we should at this notice in the shallow cloining documentation.

Edited Jul 17, 2019 by Steve Xuereb
Assignee Loading
Time tracking Loading