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差/.