← 返回文章列表

Git这一块

文集 未归档 共 2 篇

目录

引言

自始至终,我的所有项目基本上都是自己一个人在Windows端构建的,似乎已经成了路径依赖。直到这个暑假,我重新搭起在线平台,在对图形化界面搭建服务器便携性的留恋之中,毅然决然地转向Ubuntu服务器,用着不熟悉的ssh、命令行,解放出服务器的CPU与内存资源,重新构建着对服务器运维的认知。

更换路径、走出舒适区不仅意味着重新学习、打破固有经验,更意味着更广阔的前景、更多的机遇。

这种现象也在我Git的学习上体现出来。

构建

因为是一个人运维,我之前并不认为Git这种版本管理对我很有帮助。直到组会上的师兄提到信息学方向的基本素质是使用Git,我才打算开始将已建立的项目转入Git。在实际的使用中,终于熟悉了这种曾经陌生的操作,提高了自己管理项目乃至与以后与他人共同完成项目的能力。

首先是安装Git。ssh登录Ubuntu服务器后运行:

sudo apt-get install git

(Windows端需要到官网下载手动安装,记得添加到环境变量)

在任意平台安装后都要进行配置:

git config --global user.name "yourname"
git config --global user.email "you@example.com"

我的在线平台代码很大,因此一开始我不想将项目克隆下来,只是在服务器上建立了开发区/home/ubuntu/develop与生产区/home/ubuntu/program。

裸仓库构建

Git需要一个裸仓库存放版本信息与接收开发侧推送、一个remote仓库接收裸仓库钩子推送并投入使用、若干个其他仓库用来作开发。

于是我先在两个代码区的根目录(/home/ubuntu/)创建裸仓库,然后部署钩子(在收到push后将更新自动推送到remote仓库并执行重新部署等功能)

cd /home/ubuntu/
git init --bare project.git
# 建议在裸仓库执行一次下面的命令,保证上游分支是main:
git --git-dir=/home/ubuntu/project.git symbolic-ref HEAD refs/heads/main

cd /home/ubuntu/project.git/hooks

vim post-receive

然后编辑post-receive钩子:

#!/bin/bash
# 生产目录路径
WEB_PATH="/home/ubuntu/program"

# 强制更新生产目录代码
git --work-tree=$WEB_PATH --git-dir=/home/ubuntu/project.git checkout -f

# 进入生产目录,执行更新后的脚本(如重启服务)
cd $WEB_PATH
# 如果有必要,可以在这里执行:
# npm install --production
# composer install --no-dev
# php artisan migrate
# sudo systemctl restart your-service

echo "✅ 生产环境已更新到最新提交"
echo "→ 重启 project.service"
if sudo -n /bin/systemctl restart project.service 2>/dev/null; then
    echo "→ 服务已重启"
else
    echo "⚠️  自动重启失败,请手动执行: sudo systemctl restart project.service"
fi

#当然,project.service需要自己配置。

赋予脚本执行权限:

sudo chown -R ubuntu:ubuntu /home/ubuntu/program
chmod +x /home/ubuntu/project.git/hooks/post-receive

生产仓库构建

生产仓库在正确配置钩子后会自动更新,不需要手动处理;

开发仓库构建

在开发区建立开发仓库,并remote到裸仓库:

# 1.进入开发仓库
cd /home/ubuntu/develop

# 2.初始化文件夹的git
git init

# 3.连接裸仓库
git remote add origin /home/ubuntu/project.git

# 4. 提交本地代码到主分支
git add .
git commit -m "首次提交"

# 5. 推送到服务器(注意:首次推送需指定上游分支)
git push -u origin main
# 如果默认分支是 master,则改为 git push -u origin master

推送成功后,你会看到终端输出 post-receive 钩子执行的信息,此时访问网站根目录,代码已经更新。

非服务器端开发

当然,你可以在自己的本地电脑继续开发,但是要先安装Git,并确保可以使用密码或密钥ssh登录你的服务器:

首次从服务器到本地构建:

git clone ubuntu@your_server_ip:/home/ubuntu/project.git

这样你就有了一个本地的开发仓库。

维护

部署完成后,只需要在开发区改代码,改完后使用git push到裸仓库,就可以完成带版本管理、可追溯的安全更新。

# 1. 本地修改代码后,提交
git add .
git commit -m "修复了某个Bug"

# 2. 推送到服务器(自动触发部署)
git push origin main

# 3. 服务器网站立即更新,无需再登录服务器操作

与此同时,还可以有:

git remote add github https://github.com/yourname/your-project.git
git push -u github main

这样你的代码同时拥有 GitHub 备份 + 服务器部署,双保险。(警告:涉嫌机密的源文件请自备其他备份服务器,不要上传github)

breathe & tips

后文与个人经验没什么关系,由聪明的大肥鱼直接提供。

总之,使用过程中由遇到任何问题,不要吝啬token咨询大肥鱼/.

版本管理

前面的部署流程解决了“代码怎么从开发端到生产端”的问题,但 Git 更核心的价值在于版本管理:每一次提交都是一个可回溯的快照,出问题时能快速定位、回滚、对比。下面按日常使用频率从高到低整理。

查看历史与差异

# 查看提交历史(简洁一行)
git log --oneline --graph --decorate

# 查看某次提交改了什么
git show <commit-hash>

# 查看工作区与暂存区的差异
git diff

# 查看已暂存、即将提交的差异
git diff --cached

# 查看某文件的历史修改
git log -p -- filename

--graph --decorate 在有多分支时特别有用,能直观看到分支合并关系。

回滚与撤销

这是最容易出错的部分,按“影响范围从小到大”排列:

# 1. 撤销工作区某个文件的修改(未 add)
git restore filename

# 2. 撤销已 add、但未 commit 的文件
git restore --staged filename

# 3. 修改最近一次 commit 的信息或内容
git commit --amend

# 4. 撤销最近一次 commit,但保留改动在工作区
git reset --soft HEAD~1

# 5. 撤销最近一次 commit,改动回到未暂存状态
git reset --mixed HEAD~1

# 6. 彻底丢弃最近一次 commit 及其改动(危险)
git reset --hard HEAD~1

如果提交已经推到裸仓库并触发了部署,不要用 reset --hard 后强推,因为那会改写历史,其他 clone 过的仓库会冲突。更安全的做法是用一次新的提交来抵消

git revert <commit-hash>
git push origin main

revert 会生成一个反向提交,历史保留,部署也会自动回退到正确内容。

分支管理

个人项目也建议至少保留两条线:

  • main:稳定、可部署的版本
  • dev:日常开发,功能验证后再合并到 main
# 创建并切换到 dev 分支
git checkout -b dev

# 在 dev 上开发、提交
git add .
git commit -m "新增某功能"
git push -u origin dev

# 功能稳定后合并回 main
git checkout main
git merge dev
git push origin main

如果裸仓库的 post-receive 钩子只检出 main,那么推 dev 不会触发部署,这正好符合“开发分支不影响生产”的预期。等合并到 main 后再推送,才会更新生产区。

标签:标记重要版本

每次生产环境大更新、或对外发布一个稳定版本时,打个标签:

# 创建带说明的标签
git tag -a v1.0.0 -m "首个稳定版本"

# 推送标签到裸仓库
git push origin v1.0.0

# 查看所有标签
git tag

# 查看标签详情
git show v1.0.0

标签的好处是:以后要回滚到某个已知稳定版本,可以直接:

git checkout v1.0.0

或者基于标签拉一个修复分支:

git checkout -b hotfix/v1.0.1 v1.0.0

忽略文件

项目里总有些文件不该进版本库,比如日志、缓存、本地配置、密钥。在项目根目录建 .gitignore

# 日志
*.log
logs/

# 缓存
__pycache__/
*.pyc
.cache/

# 本地配置与密钥
.env
config.local.*
*.pem
*.key

# 依赖目录
node_modules/
venv/
.venv/

# 编辑器
.vscode/
.idea/

已经误提交的文件,先加进 .gitignore,再从版本库移除:

git rm --cached filename
git commit -m "移除误提交文件"

注意:git rm --cached 只从版本库移除,本地文件保留。

与部署的配合

结合前文的钩子机制,日常版本管理流程可以固定为:

# 1. 在 dev 分支开发
git checkout dev
git add .
git commit -m "描述本次改动"

# 2. 推送到裸仓库(不触发部署,如果钩子只检出 main)
git push origin dev

# 3. 验证无误后合并到 main
git checkout main
git merge dev

# 4. 打标签(可选,重要版本)
git tag -a v1.1.0 -m "发布 v1.1.0"

# 5. 推送到裸仓库,触发自动部署
git push origin main
git push origin v1.1.0

这样,开发、版本记录、部署三条线互不干扰dev 负责迭代,main 负责稳定,标签负责里程碑,裸仓库的钩子负责把 main 的最新内容同步到生产区。

出问题时的排查顺序

生产环境异常时,按这个顺序查:

# 1. 看当前生产区对应哪个提交
cd /home/ubuntu/program
git --git-dir=/home/ubuntu/project.git --work-tree=/home/ubuntu/program log --oneline -1

# 2. 看裸仓库的部署日志(如果钩子里加了日志)
tail -n 50 /home/ubuntu/project.git/deploy.log

# 3. 确认裸仓库 HEAD 指向的分支
git --git-dir=/home/ubuntu/project.git symbolic-ref HEAD

# 4. 对比生产区与裸仓库的差异
git --git-dir=/home/ubuntu/project.git --work-tree=/home/ubuntu/program status

如果确认是某次提交引入的问题,用 git revert 生成反向提交并推送,钩子会自动把生产区回退到正确状态,全程不需要手动登录服务器改文件。

后记

这个网站的markdown编辑就是靠与后端分开的content git实现的,可以看到编辑历史、进行前后端分离的管理。

总之用的好的git不比不用git差/.