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.