简化的故事是,我们在多个服务器上安装了一个站点(例如QA,Prod)。 Git 设置为每个环境的另一个分支/标签,并且我们有适用于所有环境的通用部署脚本,以使事情变得简单。脚本正在获取所需的分支/标记,然后运行以下命令:
GIT_CHECKOUT="${1:-develop}"
git clean --force --quiet
git fetch --all
git pull --all
git checkout $GIT_CHECKOUT
我们对此有一些问题:
- 由于我们想同时支持分支和标签,因此我们同时使用
git pull
和git 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