我已经开始使用 gitHub 来管理每天在我的工作站上运行的生产脚本的开发过程(通过 cron)。
确保最新有效生产版本运行的一种方法是在git checkout运行目标脚本之前在生产目录中运行一个。我想知道它是否可以在生产脚本中完成(即检查这是不是最新版本,如果不是,git checkout如果是,什么都不做并运行)
我已经开始使用 gitHub 来管理每天在我的工作站上运行的生产脚本的开发过程(通过 cron)。
确保最新有效生产版本运行的一种方法是在git checkout运行目标脚本之前在生产目录中运行一个。我想知道它是否可以在生产脚本中完成(即检查这是不是最新版本,如果不是,git checkout如果是,什么都不做并运行)
当然可以这样做,例如(未经测试):
git fetch &&
ahead=$(git rev-list --count master..origin/master) &&
case "$ahead" in
0) ;; # run normally
*) echo "I seem to be out of date"
git merge --ff-only || { echo "update failed, quitting"; exit 1; }
exec <path-to-script>;;
esac
# ... normal part of script here
但这也几乎可以肯定是错误的做法。而不是这样做,安排一个工作 - 一个脚本 - 包括:
git fetch && git merge --ff-only && exec <path-to-script>
该脚本可以存在于同一个存储库中。这是一个单独的脚本,它的工作是更新到位——如果没有什么可做的,它是一个空操作(它说“已经是最新的。”然后退出 0 = 成功)——然后运行另一个脚本,不管它是否更新。这提供了一个清晰的目的分离:一个脚本更新;一个脚本运行;自我更新和 oops-now-I-have-to-quit-because-maybe-my-code-is-different 并没有什么奇怪的组合。
请注意,添加--quiet到git merge --ff-only抑制“已经是最新的”。消息,如果您的 cron 版本在有输出时通过电子邮件将输出发送给您,这可能会有所帮助。(如果您的 cron 版本不这样做,它可能应该升级到可以这样做的版本。)所以您可能真的想要:
git fetch && git merge --ff-only --quiet && exec <path-to-script>
fetch 和 merge 是git pull默认情况下执行的操作,但git pull它是一个旨在由人类运行的程序。Git 将其各种程序分为所谓的瓷器和管道,瓷器命令是为人类准备的,而管道命令是用于编写脚本的。Git 在这里的划分是相当不完善的:一些命令既是管道又是瓷器,并且缺少一些品种(例如,git log是瓷器,但它的某些功能没有管道命令)——但在某种程度上你可以,坚持这种模式通常是明智的。
如果它可能有用,这是我现在使用的 python 脚本。我在 . 之后立即从 vim 调用它commit。
#!/bin/python3
"""
This script syncs development -> production branches
Both directories are connected to the same repository
Assume projectP (for production) and projectD (for development)
"""
####################################################
# Modules
####################################################
import git
####################################################
# Globals
####################################################
theProjectD = "path_to_projectD"
theProjectP = "path_to_projectP"
####################################################
# Code
####################################################
# push & merge develop to main from the develop directory
repo = git.Repo(theProjectD)
repo.remotes.origin.push()
repo.git.checkout('main')
repo.git.merge('develop')
repo.remotes.origin.push()
repo.git.checkout('develop')
# fetch latest version of main in the production directory
repo = git.Repo(theProjectP)
repo.remotes.origin.fetch()
repo.remotes.origin.pull()