Showing Posts From
Git
写个 Bash 自动 git pull:三种姿势和 cron 里的坑
服务器上想自动拉最新代码,写个脚本挂 cron 跑。看着就两行,实际上有几个必吃的坑。 最基础写法 #!/bin/bash cd /www/wwwroot/yourproject || exit 1 git pull|| exit 1:cd 失败就退出,不然当前目录是家目录,git pull 会执行在错误的仓库 保存为 pull.sh chmod +x pull.sh 执行 ./pull.sh更稳的写法:不依赖 cd git -C 可以直接指定仓库路径,省掉 cd 的失败风险: #!/bin/bash git -C /www/wwwroot/yourproject pull origin main同一个脚本要处理多个仓库时特别顺手。 挂 cron 时会踩的坑 */5 * * * * /www/wwwroot/scripts/pull.sh >> /var/log/pull.log 2>&1看着没问题,实际经常挂。原因: 1. SSH 密钥没加载 用户手动跑时有 ssh-agent。cron 里没有,git@github.com 直接拒绝。解法:走 HTTPS + PAT,别用 SSH 或在脚本里显式指定密钥:export GIT_SSH_COMMAND="ssh -i /root/.ssh/deploy_key -o StrictHostKeyChecking=no" git -C /www/wwwroot/yourproject pull origin main2. PATH 太窄 cron 的 PATH 只有 /usr/bin:/bin,找不到自定义安装的 git。crontab 里手动补: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin */5 * * * * /www/wwwroot/scripts/pull.sh3. 分支不明确 裸 git pull 会走当前分支和默认 remote,可能拉到不该拉的分支。永远显式: git -C "$REPO" pull origin main处理本地修改的完整版 生产脚本上还得防几件事: #!/bin/bash set -eREPO=/www/wwwroot/yourproject BRANCH=maincd "$REPO"# 1. 如果本地有修改,暂存(避免 pull 失败) if [[ -n $(git status --porcelain) ]]; then echo "[$(date)] 本地有修改,先 stash" git stash push -m "auto-stash $(date +%s)" fi# 2. 拉最新 git fetch origin "$BRANCH" git reset --hard "origin/$BRANCH" # 直接对齐远程,别 merge# 3. 清空 stash(不还原,防止和拉下来的冲突) git stash clear注意 git reset --hard 会覆盖本地任何修改。这是刻意的——线上机器上不该有手改,任何修改都视为"意外"直接抹掉。要保守就用 git pull --ff-only。 大小写敏感的坑 服务器 Linux 大小写敏感,Windows / macOS 默认不敏感。仓库里同时存在: RiderAuditController.php RiderauditController.phpLinux 上拉下来会真的多出两个文件,Windows 上只能存一个,pull 立刻挂。 解法:清理仓库中的重名文件,用 git rm 保留一个: git rm --cached RiderauditController.php git commit -m "fix: 大小写重复" git push或者临时关掉大小写敏感(治标): git config core.ignorecase true一句话总结 git -C REPO pull origin BRANCH 是最省事的一行。挂 cron 要额外交代 PATH、SSH 密钥、分支名,生产脚本再套一层 reset --hard 防脏树。
