简体   繁体   English

gitlab ci 管道中的分离头 - 如何正确推送

[英]Detached head in gitlab ci pipeline - how to push correctly

I got some problems with a detached head for my repository in a CI pipeline.我在 CI 管道中为我的存储库分离头时遇到了一些问题。 In the build stage of the pipeline I am running a script, which changes a specific file.在管道的构建阶段,我正在运行一个脚本,它会更改一个特定的文件。 After changing this file get pushed to the repository.更改此文件后,将推送到存储库。

before_script:
  - git config --global user.name "Bot"
  - git config --global user.email "ci@domain.com"
  - git status
script:
  - npx ts-node ./generate.ts
  - git push "https://git:${GIT_PUSH_TOKEN}@${CI_REPOSITORY_URL#*@}" "HEAD:main"
  - git status

Running the script give me the output运行脚本给我 output

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

I do not understand why the first git status in the before_script already gives me a detached head.我不明白为什么 before_script 中的第一个git status已经给了我一个超然的头脑。

I think the pipeline creates a detached repository by initial fetching.我认为管道通过初始提取创建了一个分离的存储库。 So the question is how to handle my push in a correct way.所以问题是如何以正确的方式处理我的推送。 In my release stage I'm running semantic-release which fails because of detached head if I do the previous push.在我的发布阶段,我正在运行semantic-release ,如果我执行之前的推送,它会因为头部分离而失败。 If I disable the push, semantic release is working as expected.如果我禁用推送,语义释放将按预期工作。 But of course I need the push.但我当然需要推动。 I do not see, what I am doing wrong.我看不出,我做错了什么。


Update更新

Adding git checkout main in the before_script give me for the first git status the expected result.在 before_script 中添加git checkout main给我第一个git status预期的结果。 But after the push command I still have the detached head - which I do not understand.但是在 push 命令之后我仍然有分离的头 - 我不明白。

$ 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)

Although everything the push is working on the release state semantic-release is still not working.尽管推送在版本 state 上工作的所有内容,但semantic-release仍然无法正常工作。 I do get: The local branch main is behind the remote one, therefore a new version won't be published.我确实得到: The local branch main is behind the remote one, therefore a new version won't be published.

I spend a lot of time to try to resolve the same problem and finally I found that there are git strategy: https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-strategy我花了很多时间尝试解决同样的问题,最后我发现有 git 策略: https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-strategy

When there is set fetch then it re-uses the local working copy (and falls back to clone if it doesn't exist).当有 set fetch时,它会重新使用本地工作副本(如果它不存在,则回退到克隆)。 So this is the reason why it worked me for the first time and then it stopped working and my checkouted branch was behind and number of commits ahead increased with another commit.所以这就是为什么它第一次对我有用然后它停止工作并且我的签出分支落后并且前面的提交数量随着另一个提交而增加的原因。

Then the solution is pretty easy.那么解决方案就很简单了。 You just need to define the GIT_STRATEGY variable to clone .您只需要将GIT_STRATEGY变量定义为clone

variables:
  GIT_STRATEGY: clone

And my working publish job example:我的工作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

You can also define clone strategy in global variables or pipeline configuration https://docs.gitlab.com/ee/ci/pipelines/settings.html#choose-the-default-git-strategy .您还可以在全局变量或管道配置中定义clone策略https://docs.gitlab.com/ee/ci/pipelines/settings.html#choose-the-default-git-strategy

I do not understand why the first git status in the before_script already gives me a detached head.我不明白为什么 before_script 中的第一个git status已经给了我一个分离的头。

I think the pipeline creates a detached repository by initial fetching.我认为管道通过初始获取创建了一个分离的存储库。

You are right, GitLab CI does checkout a specific commit as opposed to a certain branch.你是对的,GitLab CI 会检查特定的提交而不是某个分支。 You could however add git checkout "$CI_COMMIT_REF_NAME" to your before_script :但是,您可以将git checkout "$CI_COMMIT_REF_NAME"到您的before_script

before_script:
  - git config --global user.name "Bot"
  - git config --global user.email "ci@domain.com"
  - git checkout "$CI_COMMIT_REF_NAME"
  - git status

This might help someone.这可能会帮助某人。 Based on gitlab.基于 gitlab。

The detached state is actually intended, as the runner is specifically designed to checkout the repository using a specific commit (the one that triggered the pipeline).分离状态实际上是有意的,因为运行器专门设计用于使用特定提交(触发管道的提交)检出存储库。 When a specific commit is checked out, the repository is then considered to be in a "detached HEAD" state.当检出特定提交时,存储库将被视为处于“分离的 HEAD”状态。

Here is an example from my pipeline that after changing some files, it pushes them to master (change master to main in new repos).这是我的管道中的一个示例,在更改某些文件后,它将它们推送到 master(在新存储库中将 master 更改为 main)。

git remote set-url origin http://$user:$token@gitlab.com/<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 - is to stop running another pipeline after push to pipeline. -o ci.skip - 是在推送到管道后停止运行另一个管道。

In gitlab you can do below to select the default branch from gitlab variables:在 gitlab 中,您可以执行以下操作以从 gitlab 变量中选择默认分支:

git push -o ci.skip origin HEAD:$CI_DEFAULT_BRANCH

To show all variables add CI_DEBUG_TRACE: "true" to variables section.要显示所有变量,请将CI_DEBUG_TRACE: "true"添加到变量部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM