我在 CI 管道中的存储库的分离头中遇到了一些问题。在管道的构建阶段,我运行一个脚本,该脚本更改特定文件。更改此文件后,将其推送到存储库。
before_script:
- git config --global user.name "Bot"
- git config --global user.email "[email protected]"
- git status
script:
- npx ts-node ./generate.ts
- git push "https://git:${GIT_PUSH_TOKEN}@${CI_REPOSITORY_URL#*@}" "HEAD:main"
- git status
运行脚本给我输出
Fetching changes with git depth set to 50...
Initialized empty Git repository in /builds/fKSu5-y_/0/project/.git/
Created fresh repository.
Checking out 9b4a88be as main...
$ git status
HEAD detached at 9b4a88be
$ git push "https://git:${GIT_PUSH_TOKEN}@${CI_REPOSITORY_URL#*@}" "HEAD:main"
To https://gitlab.domain.com/project.git
9b4a88b..98be83e HEAD -> main
$ git status
HEAD detached from 9b4a88b
我不明白为什么 before_script 中的第一个
git status
已经给了我一个分离的头。
我认为管道通过初始获取创建了一个独立的存储库。所以问题是如何以正确的方式处理我的推送。 在我的发布阶段,我正在运行
semantic-release
,如果我执行之前的推送,它会因为头部分离而失败。如果我禁用推送,语义发布将按预期工作。但我当然需要推动。我不明白,我做错了什么。
更新
在 before_script 中添加
git checkout main
给我第一个 git status
预期的结果。但在推送命令之后,我仍然有分离的头 - 我不明白。
$ git checkout main
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'
$ git status
On branch main
Your branch is up to date with 'origin/main'.
$ git push "https://git:${GIT_PUSH_TOKEN}@${CI_REPOSITORY_URL#*@}" "HEAD:main"
To https://gitlab.domain.com/project.git
336b065..8299e43 HEAD -> main
$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
尽管推送的所有内容都在发布状态下工作
semantic-release
仍然不起作用。我确实明白:The local branch main is behind the remote one, therefore a new version won't be published.
我不明白为什么 before_script 中的第一个
已经给了我一个分离的头。git status
我认为管道通过初始获取创建了一个独立的存储库。
你是对的,GitLab CI 确实会签出特定的提交,而不是某个分支。但是,您可以将
git checkout "$CI_COMMIT_REF_NAME"
添加到您的 before_script
:
before_script:
- git config --global user.name "Bot"
- git config --global user.email "[email protected]"
- git checkout "$CI_COMMIT_REF_NAME"
- git status
我花了很多时间尝试解决同样的问题,最后发现还有git策略:https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-strategy
当设置
fetch
时,它会重新使用本地工作副本(如果不存在,则回退到克隆)。所以这就是为什么它第一次对我起作用,然后它停止工作并且我的签出分支落后并且前面的提交数量随着另一次提交而增加的原因。
那么解决方案就很简单了。您只需将
GIT_STRATEGY
变量定义为 clone
。
variables:
GIT_STRATEGY: clone
还有我的工作
publish
工作示例:
publish:
stage: publish
rules:
- if: $CI_COMMIT_BRANCH == "master"
when: manual
variables:
GIT_STRATEGY: clone
script:
- git checkout -b $CI_COMMIT_BRANCH
- echo "define what you want to change"
- 'git commit -am "your commit message" || echo "No changes to commit"'
- git push --set-upstream origin $CI_COMMIT_BRANCH
您还可以在全局变量或管道配置中定义
clone
策略https://docs.gitlab.com/ee/ci/pipelines/settings.html#choose-the-default-git-strategy。
这可能会对某人有所帮助。基于gitlab。
分离状态实际上是有意为之的,因为跑步者是专门 旨在使用特定提交(即 触发了管道)。当签出特定提交时, 然后存储库被认为处于“分离头”状态。
这是我的管道中的一个示例,在更改一些文件后,它将它们推送到 master(在新存储库中将 master 更改为 main)。
git remote set-url origin http://$user:[email protected]/<group>/<group>/$service.git
git add <file that changed>
git config --global user.email "<user email>"
git config --global user.name "<user name>"
git commit -m "Updated service $service"
git push -o ci.skip origin HEAD:master
-o ci.skip
- 推送到存储库后停止运行另一个管道。
在 gitlab 中,您可以执行以下操作从 gitlab 变量中选择默认分支:
git push -o ci.skip origin HEAD:$CI_DEFAULT_BRANCH
要显示所有变量,请将
CI_DEBUG_TRACE: "true"
添加到变量部分。
解决方案:
git switch $CI_COMMIT_REF_NAME
git reset --hard $CI_COMMIT_SHA
确保重置回当前提交。 或者您可以在旧的提交管道上运行最新的分支更改。