Git 常用命令
Git 是最常用的分布式版本控制系统。
安装
Windows
bash
# 下载安装包
# https://git-scm.com/download/win
# 安装后验证
git --versionmacOS
bash
# 通过 Homebrew 安装
brew install git
# 或通过 Xcode Command Line Tools
xcode-select --installLinux
bash
# Debian/Ubuntu
sudo apt-get install git
# CentOS/Fedora
sudo yum install git基础配置
bash
# 设置用户名
git config --global user.name "你的名字"
# 设置邮箱
git config --global user.email "[email protected]"
# 设置默认分支名
git config --global init.defaultBranch main
# 设置换行符(Windows 用户推荐)
git config --global core.autocrlf true
# 查看配置
git config --list日常操作
创建仓库
bash
# 初始化新仓库
git init
# 克隆远程仓库
git clone https://github.com/user/repo.git查看状态与差异
bash
git status # 查看工作区状态
git status -s # 简洁模式(M 修改 A 新增 D 删除)
git diff # 查看未暂存的修改
git diff --staged # 查看已暂存的修改(对比上一次 commit)提交代码
bash
# 添加所有文件到暂存区
git add .
# 添加指定文件
git add filename.txt
# 添加指定目录
git add src/
# 提交
git commit -m "feat: 添加新功能"
# 添加并提交(仅限已跟踪文件的修改,跳过 git add)
# ⚠️ 不能暂存新文件(untracked),新文件仍需先 git add
git commit -am "fix: 修复 bug"分支操作
bash
# 查看分支
git branch
# 查看所有分支(含远程)
git branch -a
# 创建新分支
git branch feature-name
# 切换分支(推荐使用 git switch)
git switch feature-name
# 创建并切换到新分支
git switch -c feature-name
# 合并分支
git merge feature-name
# 删除已合并的分支
git branch -d feature-name
# 强制删除分支
git branch -D feature-name💡
git checkout也能切换分支,但git switch(Git 2.23+)语义更清晰,专门用于分支切换。
远程操作
bash
# 查看远程仓库
git remote -v
# 关联远程仓库
git remote add origin https://github.com/user/repo.git
# 推送到远程
git push origin main
# 推送并设置上游分支(首次推送后可简写 git push)
git push -u origin feature-name
# 拉取远程更新(= fetch + merge)
git pull origin main
# 拉取并变基(避免多余的合并提交)
git pull --rebase
# 获取远程更新(不合并)
git fetch origin撤销操作
撤销工作区修改(未 add)
bash
# 恢复单个文件
git restore filename.txt
# 恢复所有修改
git restore .撤销暂存(已 add 未 commit)
bash
# 取消暂存单个文件
git restore --staged filename.txt
# 取消暂存所有
git restore --staged .撤销提交(已 commit)
bash
# 撤销提交,保留修改在暂存区
git reset --soft HEAD~1
# 撤销提交,保留修改在工作区
git reset --mixed HEAD~1
# 撤销提交,丢弃所有修改(不可恢复,慎用)
git reset --hard HEAD~1修改最后一次提交
bash
# 修改提交信息
git commit --amend -m "新的提交信息"
# 追加文件到上一次提交(不改信息)
git add forgotten-file.js
git commit --amend --no-editgit revert(安全撤销已推送的提交)
什么是 git revert?
git revert 会创建一个新的提交,用来"反转"指定提交的修改。与 git reset 不同,revert 不会改变历史,而是新增一个"反向提交",适合撤销已推送到远程的代码。
什么时候用 revert 而不是 reset?
- 已推送到远程的提交,用 revert(不改变历史,不影响其他人)
- 未推送的本地提交,用 reset(可以修改历史)
bash
# 撤销指定提交(创建一个新的反向提交)
git revert <commit-hash>
# 撤销最近一次提交
git revert HEAD
# 撤销但不自动提交(可以修改后再提交)
git revert --no-commit <commit-hash>
# 撤销多个连续提交
git revert <older-hash>..<newer-hash>
# 撤销合并提交(-m 1 表示保留主分支的内容)
git revert -m 1 <merge-commit-hash>reset / revert / restore 三者区别
| 命令 | 作用对象 | 是否改变历史 | 典型场景 |
|---|---|---|---|
git reset | 分支指针(HEAD) | 是(本地)/ 否(远程未推送) | 撤销本地提交、整理提交历史 |
git revert | 提交记录 | 否(新增反向提交) | 撤销已推送到远程的提交 |
git restore | 工作区 / 暂存区 | 否 | 撤销文件修改、取消暂存 |
使用场景对比:
场景 1:刚写完代码,还没 git add
→ git restore filename.txt(撤销工作区修改)
场景 2:已经 git add,还没 git commit
→ git restore --staged filename.txt(取消暂存)
场景 3:已经 git commit,但还没推送到远程
→ git reset --soft HEAD~1(撤销提交,保留修改)
场景 4:已经推送到远程,需要撤销
→ git revert HEAD(安全撤销,不影响其他人)⚠️
git reset --hard会丢失未提交的修改,无法恢复。操作前建议先git stash备份当前工作。
高级操作
暂存工作区
bash
# 暂存当前修改(切换分支时很有用)
git stash
# 查看暂存列表
git stash list
# 恢复最近一次暂存并删除记录
git stash pop
# 恢复最近一次暂存(保留记录)
git stash apply
# 删除最近一次暂存
git stash drop
# 清空所有暂存
git stash clear查看日志
bash
# 查看提交日志
git log
# 简洁模式(最近 10 条)
git log --oneline -10
# 图形化显示分支
git log --graph --oneline --all
# 查看某个文件的修改历史
git log -p filename.txt
# 查看某次提交的详细内容
git show <commit-hash>
# 查看每一行是谁改的
git blame filename.txt变基(Rebase)vs 合并(Merge)
什么时候用 rebase?什么时候用 merge?
简单说:
- rebase:把你的提交"搬"到目标分支的最新提交后面,保持提交历史是一条直线
- merge:把两个分支合并,会产生一个"合并提交",历史会分叉再合并
# rebase 后的历史(线性):
A - B - C - D' - E' (D' 和 E' 是你的提交"搬"过来的)
# merge 后的历史(有分叉):
A - B - C - F(合并提交)
\ /
D - E什么时候用 rebase?
- 你自己的功能分支,还没有其他人基于它开发
- 想保持提交历史干净、线性
- 整理提交记录(比如把 5 个小提交合并成 1 个)
什么时候用 merge?
- 公共分支(如 main、develop),因为 rebase 会改变提交历史,影响其他人
- 想保留完整的合并记录(知道哪些提交是在哪个分支上做的)
bash
# 将当前分支变基到 main(保持提交历史线性)
git rebase main
# 交互式变基(合并、修改、删除最近 3 次提交)
git rebase -i HEAD~3⚠️ 不要对已推送到远程的公共分支执行 rebase,会导致其他人的代码冲突。
Cherry-pick
什么是 cherry-pick?
cherry-pick 是"摘樱桃"的意思。假设你在 feature-A 分支上提交了一个紧急修复,但 feature-A 还没开发完不能合并到 main。这时候可以用 cherry-pick 把那个"修复提交"单独"摘"到 main 分支上。
什么时候用?
- 紧急 bug 修复需要从开发分支提取到生产分支
- 某个分支上的某个提交很有用,想应用到其他分支
- 不想合并整个分支,只需要其中的某次提交
bash
# 将指定提交应用到当前分支
git cherry-pick <commit-hash>
# 应用多个提交
git cherry-pick <hash1> <hash2>
# 应用但不自动提交(可以修改后再提交)
git cherry-pick --no-commit <commit-hash>解决合并冲突
bash
# 合并时出现冲突,手动解决后
git add <conflicted-files>
git commit
# 放弃本次合并
git merge --abort
# 放弃本次 rebase
git rebase --abort冲突文件的标记:
<<<<<<< HEAD
当前分支的内容
=======
要合并的分支内容
>>>>>>> feature-name标签管理
什么是标签?为什么要用标签?
标签就像是给某个提交贴一个"书签",通常用于标记发布版本(如 v1.0.0、v2.1.3)。
为什么要用标签?
- 方便回溯:想看 v1.0.0 版本的代码是什么样的,直接
git checkout v1.0.0 - 发布记录:配合 GitHub/Gitee 的 Release 功能,自动生成版本更新日志
- 部署管理:CI/CD 可以根据标签自动触发发布流程
什么时候打标签?
- 每次发布新版本时(npm publish 前、部署生产环境前)
- 重要的里程碑节点
bash
# 查看标签
git tag
# 创建轻量标签(只是一个指针,不推荐)
git tag v1.0.0
# 创建附注标签(推荐,包含标签信息)
git tag -a v1.0.0 -m "版本 1.0.0:新增用户登录功能"
# 推送标签到远程
git push origin v1.0.0
# 推送所有标签
git push origin --tags
# 删除标签
git tag -d v1.0.0二分查找(bisect)
用二分法快速定位哪个提交引入了 bug:
bash
# 开始二分查找
git bisect start
# 标记当前版本有 bug
git bisect bad
# 标记某个版本没有 bug
git bisect good v1.0.0
# Git 会自动 checkout 中间版本,你测试后标记:
git bisect good # 这个版本没问题
git bisect bad # 这个版本有问题
# 找到问题提交后,结束查找
git bisect reset
# 自动化(用脚本自动测试)
git bisect start HEAD v1.0.0
git bisect run npm test从历史中删除文件
bash
# 误提交了大文件或敏感文件,从历史中彻底删除
pip install git-filter-repo
git filter-repo --path src/assets/large-file.mp4 --invert-paths
git push --force-with-lease # ⚠️ 仅在远程未被他人更新时才允许 force push⚠️
git push --force会覆盖远程历史,影响所有协作者。推荐使用--force-with-lease(仅在远程未被他人更新时才允许 force push)。执行前必须通知所有协作者。
前端项目常用 Git 工作流
分支命名规范
main(或 master) → 生产环境代码
develop → 开发环境代码
feature/xxx → 功能分支(如 feature/user-login)
fix/xxx → 修复分支(如 fix/token-expire)
hotfix/xxx → 紧急修复(如 hotfix/crash-on-payment)
release/x.x.x → 发布分支(如 release/1.2.0)前端项目典型工作流
bash
# 1. 从 develop 创建功能分支
git switch develop
git pull origin develop
git switch -c feature/user-login
# 2. 开发完成后提交
git add src/views/Login.vue src/api/auth.ts
git commit -m "feat(auth): 添加用户登录功能"
# 3. 推送到远程并创建 PR
git push -u origin feature/user-login
# 4. PR 合并后清理本地分支
git switch develop
git pull origin develop
git branch -d feature/user-login前端项目 .gitignore 完整配置
bash
# 依赖目录
node_modules/
# 构建产物
dist/
build/
.output/
# 环境变量(敏感信息)
.env
.env.local
.env.*.local
# 系统文件
.DS_Store
Thumbs.db
# 日志
*.log
npm-debug.log*
# 编辑器
.vscode/
.idea/
*.swp
*.swo
# TypeScript 缓存
*.tsbuildinfo
# Vite 缓存
.vite/
# 测试覆盖率
coverage/
# 反向规则(虽然 *.log 被忽略,但保留 important.log)
!important.log
# 忽略某个目录下所有文件但保留目录本身
logs/*
!logs/.gitkeep常见报错及解决方案
fatal: not a git repository
bash
# 原因:当前目录不是 Git 仓库
# 解决:初始化或切换到正确的目录
git init
# 或
cd /path/to/your/projectfatal: remote origin already exists
bash
# 原因:已经关联了远程仓库
# 解决:先删除再重新关联
git remote remove origin
git remote add origin https://github.com/user/repo.giterror: failed to push some refs
bash
# 原因:远程有本地没有的提交(远程代码更新了)
# 解决:先拉取远程更新再推送
git pull --rebase origin main
git push origin mainCONFLICT (content): Merge conflict in xxx
bash
# 原因:两个分支修改了同一文件的同一位置
# 解决:
# 1. 打开冲突文件,找到 <<<<<<< HEAD 标记
# 2. 手动选择保留哪个版本(或合并两者)
# 3. 删除冲突标记(<<<<<<<、=======、>>>>>>>)
# 4. 标记冲突已解决
git add <conflicted-file>
git commitfatal: refusing to merge unrelated histories
bash
# 原因:两个仓库没有共同的提交历史
# 解决:添加 --allow-unrelated-histories 参数
git pull origin main --allow-unrelated-historieserror: Your local changes would be overwritten
bash
# 原因:本地有未提交的修改,切换分支会丢失
# 解决:先暂存修改
git stash
git switch <other-branch>
# 切换回来后恢复
git switch <original-branch>
git stash pop