首页 / 经验库 / 正文

自建 Git 服务器:本地与生产环境部署

阅读:139 更新:2026-06-30 ¥0.9

搭建自建 Git 时,常会遇到本地能推送、生产环境却无法拉取,或因目录不为空、私钥未绑定导致部署失败的问题。本文适合使用多台服务器部署项目的开发者,整理 Git 服务器创建仓库、本地初始化、生产环境免密拉取,以及新项目复用旧私钥的完整步骤。看完可快速完成项目代码的首次部署和后续更新。

实践参考 预计落地30-60 分钟 减少试错2-4 小时 适用前提可 SSH 登录服务器

截图说明

适用:Git 服务器、开发电脑、生产服务器是不同机器;通过 SSH 私钥推送和拉取,不需要重复输入密码。

约定:

GIT_HOST=<Git服务器IP或域名>
PROJECT=<项目名>
REPO="git@${GIT_HOST}:/home/git/repos/${PROJECT}.git"
例如项目名为 demo-api,仓库地址就是:
git@<Git服务器IP>:/home/git/repos/demo-api.git

---

1. Git 服务器首次部署

以下命令在 Git 服务器 执行。

apt update
apt install -y git

id git >/dev/null 2>&1 || adduser --disabled-password --gecos "" git

install -d -o git -g git -m 755 /home/git/repos
install -d -o git -g git -m 700 /home/git/.ssh
touch /home/git/.ssh/authorized_keys
chown git:git /home/git/.ssh/authorized_keys
chmod 600 /home/git/.ssh/authorized_keys

---

2. 配置 SSH 私钥,免密码访问 Git

开发电脑与生产服务器各自生成一把私钥。私钥不要复制、不要发给别人。

2.1 本地开发电脑生成私钥

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_git -N "" -C "local-git"
cat ~/.ssh/id_ed25519_git.pub

复制输出的整行公钥。

2.2 生产服务器生成部署私钥

ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519_git_deploy -N "" -C "production-git"
cat /root/.ssh/id_ed25519_git_deploy.pub

复制输出的整行公钥。

2.3 将公钥加入 Git 服务器

Git 服务器 执行:

nano /home/git/.ssh/authorized_keys

把本地公钥、生产服务器公钥各粘贴一行后保存,再执行:

chown git:git /home/git/.ssh/authorized_keys
chmod 600 /home/git/.ssh/authorized_keys

---

3. Git 服务器创建新项目仓库

以下命令在 Git 服务器 执行:

PROJECT=<项目名>

sudo -u git git init --bare /home/git/repos/${PROJECT}.git

例如:

sudo -u git git init --bare /home/git/repos/demo-api.git

---

4. 本地项目初始化并首次推送

以下命令在 本地项目目录 执行:

cd <本地项目目录>

git init
git branch -M main

git config --local core.sshCommand "ssh -i ~/.ssh/id_ed25519_git -o IdentitiesOnly=yes"
git remote add origin git@<Git服务器IP>:/home/git/repos/<项目名>.git

git add -A
git commit -m "初始化项目"
git push -u origin main

以后本地提交:

git add -A
git commit -m "本次修改说明"
git push origin main

---

5. 生产环境首次拉取项目

以下命令在 生产服务器 执行。

目标目录必须为空。先进入目标目录,再执行最后带 . 的克隆命令:

APP_DIR=/home/www/web/<项目目录名>

mkdir -p "$APP_DIR"
cd "$APP_DIR"

GIT_SSH_COMMAND='ssh -i /root/.ssh/id_ed25519_git_deploy -o IdentitiesOnly=yes' \
git clone -b main git@<Git服务器IP>:/home/git/repos/<项目名>.git .

让当前项目以后永久使用这把私钥:

git config --local core.sshCommand "ssh -i /root/.ssh/id_ed25519_git_deploy -o IdentitiesOnly=yes"

git status
git remote -v

以后生产环境更新:

cd /home/www/web/<项目目录名>
git pull --ff-only origin main
生产服务器和 Git 服务器不是同一台时,不能使用 /home/git/repos/xxx.git 作为拉取地址;必须使用 git@<Git服务器IP>:/home/git/repos/xxx.git

---

6. 新项目复用以前项目的私钥配置

不需要重新生成私钥,只需创建新裸仓库,然后读取旧项目的 core.sshCommand

6.1 Git 服务器创建新裸仓库

PROJECT=<新项目名>

sudo -u git git init --bare /home/git/repos/${PROJECT}.git

6.2 本地新项目复用旧项目配置

OLD_PROJECT=<旧项目本地目录>
NEW_PROJECT=<新项目本地目录>

SSH_COMMAND="$(git -C "$OLD_PROJECT" config --get core.sshCommand)"

cd "$NEW_PROJECT"

git init
git branch -M main
git config --local core.sshCommand "$SSH_COMMAND"
git remote add origin git@<Git服务器IP>:/home/git/repos/<新项目名>.git

git add -A
git commit -m "初始化项目"
git push -u origin main

查看旧项目具体使用的私钥:

git -C <旧项目本地目录> config --show-origin --get core.sshCommand

6.3 生产服务器新项目复用旧项目配置

SSH_COMMAND="$(git -C /home/www/web/<旧项目目录> config --get core.sshCommand)"

APP_DIR=/home/www/web/<新项目目录>
mkdir -p "$APP_DIR"
cd "$APP_DIR"

GIT_SSH_COMMAND="$SSH_COMMAND" \
git clone -b main git@<Git服务器IP>:/home/git/repos/<新项目名>.git .

git config --local core.sshCommand "$SSH_COMMAND"
git status

---

7. 两个常见问题

7.1 destination path '.' already exists and is not an empty directory

当前目录不是空的,先确认:

pwd
ls -la

不要在 /home/www/web 目录执行:

git clone ... .

7.2 Permission denied (publickey)

检查当前项目使用的私钥:

git config --get core.sshCommand

并确认对应的公钥已经加入 Git 服务器:

/home/git/.ssh/authorized_keys

8. 生产环境与 Git 服务器同一台:本地路径免密拉取

此场景不需要 SSH 私钥、不需要 authorized_keys、不需要 core.sshCommand。生产目录直接从本机裸仓库拉取代码。

8.1 已有裸仓库,首次部署项目

假设裸仓库已存在:

/home/git/repos/<项目名>.git

以下命令在同一台服务器执行:

mkdir -p /home/www/web/<项目目录名>
cd /home/www/web/<项目目录名>

# 当前目录必须为空;最后的 . 表示代码直接拉到当前目录
git clone -b main /home/git/repos/<项目名>.git .

git status
git remote -v

以后更新:

cd /home/www/web/<项目目录名>
git pull --ff-only origin main

8.2 新项目同机部署流程

# 1. 在 Git 服务器创建裸仓库
sudo -u git git init --bare /home/git/repos/<新项目名>.git

# 2. 本地开发电脑初始化、提交并推送代码(按第 4 节)

# 3. 同机生产目录首次拉取
mkdir -p /home/www/web/<新项目目录>
cd /home/www/web/<新项目目录>

git clone -b main /home/git/repos/<新项目名>.git .

8.3 同机项目权限建议

代码仓库由 root 管理,执行 git pull 也使用 root

chown -R root:www-data /home/www/web/<项目目录名>

CI4 项目只有 writable/ 需要给 PHP 写入:

mkdir -p /home/www/web/<项目目录名>/writable

chown -R www-data:www-data /home/www/web/<项目目录名>/writable
chmod -R 775 /home/www/web/<项目目录名>/writable
若出现 detected dubious ownership,通常是项目目录属于 www-data,但当前用 root 执行 Git。先按上面的所有者规则修正,再执行 git statusgit pull

完整内容为付费内容

购买后可查看完整排查步骤、关键配置和补充说明。