在我们的 CD 作业中进行防弹 Git 结帐



简化的故事是,我们在多个服务器上安装了一个站点(例如QA,Prod)。 Git 设置为每个环境的另一个分支/标签,并且我们有适用于所有环境的通用部署脚本,以使事情变得简单。脚本正在获取所需的分支/标记,然后运行以下命令:

GIT_CHECKOUT="${1:-develop}"
git clean --force --quiet
git fetch --all
git pull --all
git checkout $GIT_CHECKOUT

我们对此有一些问题:

  • 由于我们想同时支持分支和标签,因此我们同时使用git pullgit fetch并且git pull在分离的头部模式下失败,这有效,但它会向我们的日志抛出不相关的错误
  • 有时结帐失败是因为环境肮脏(通常它发生在我们不知道是什么原因的情况下发生的,因为没有人在这些环境中手动更改文件)

我看了一下 Jenkins 的做法,它看起来像这样:

> git fetch --tags --progress https://myrepo.com/repo.git +refs/heads/*:refs/remotes/origin/*
> git rev-parse origin/mytag^{commit}
> git rev-parse mytag^{commit}
> git config core.sparsecheckout
> git checkout -f hash-of-commit
> git rev-list --no-walk hash-of-commit

最后,问题:

  • 部署时我们应该只在分离的头部模式下工作吗?这听起来确实是一个更稳定的解决方案。

  • 这项任务有"配方"吗?这是一项非常常见的任务,尽管如此,我找不到任何在线食谱来使用您自己的 bash 脚本来完成它

在"分离的 HEAD"上,您在尝试拉动时出现错误是有道理的......因为拉动使用上游分支来合并...如果你在分离的 HEAD 上,你将没有上游分支。执行git fetch应该足以更新本地的远程信息。如果您真的想结账并且不想关心您是否有肮脏的环境,您可以尝试gir reset --hard

这就是我要做的:

git clean --force --quiet
git fetch --all
git checkout --detach # disconnect from whatever branch I was working on
git reset --hard $GIT_CHECKOUT

唯一的问题是您不会在本地移动任何内容(例如,没有本地分支随远程分支一起移动)。

我的看法是这样的(未经测试):

GIT_CHECKOUT="${1:-develop}"
# cleanup *every* untracked file and dir
git clean --force -d -x --quiet
# undo every change to untracked files - might disturb update
git reset --hard HEAD
# now the working tree should be *pristine*
# update all tracking branches and tags
git fetch --all --tags
git checkout --detach
# delete any local branch
git for-each-ref --format="%(refname:strip=2)" refs/heads |xargs -r git branch -D
# checkout
git checkout $GIT_CHECKOUT

最新更新