我一直觉得,Git 命令速查这件事,难点从来不是“记不住”,而是“不知道在什么场景下该用哪一条”。新人往往只熟练 clone、commit、push 三板斧,一旦遇到分支冲突、提交提错、误删文件、推送被拒,就只能干瞪眼,甚至憋出“删掉本地仓库重新 clone”这种伤敌一千自损八百的土办法。这篇手册就是按真实开发流程来组织的,从安装配置、日常提交、分支合并,到远程协作、撤销回滚、排查问题,最后再加上几个高频疑难杂症的处理套路。不按字母表背命令,而是按“你现在想干什么、Git 会怎么执行、命令之间为什么这么选”来写,争取让你看完之后不是收藏吃灰,而是真的能少搜几次。
1. 先把 Git 环境整理干净:安装、Bash 与首次配置
很多人以为 Git 装上就能用,结果第一条 commit 就卡在 user.email 没配置,或者 Windows 上换行符悄悄变了,等到代码合并时才发现整个文件被标记成改动。环境这步偷懒,后面全是债。
1.1 不同系统的安装与 Git Bash 的真实作用
Windows 上最常用的是 Git for Windows,装完系统会多出一个 Git Bash 入口。Git Bash 不只是“能敲 git 命令的黑色窗口”,它自带了一套 bash 环境,里面有 ssh、grep、sed、awk、find 这些工具。这意味着你在 Windows 上也能用 Linux 风格的命令处理问题,比如批量改文件、写简单脚本分析日志,这对排查仓库异常非常有帮助。
macOS 用户可以直接用 Homebrew 装:
bash复制brew install git
Linux 用户按发行版选包管理器:
bash复制# Debian / Ubuntu
sudo apt update && sudo apt install git -y
# CentOS / RHEL / Fedora 系
sudo dnf install git -y
装完先别急着 clone 项目,用下面命令确认版本和安装路径都没问题:
bash复制git --version
which git
如果你平时用 VSCode、IntelliJ 这类 IDE,终端里使用的 Git 路径最好和系统命令行一致,否则可能出现“命令行能用、IDE 里提示找不到 git”的割裂问题。
1.2 第一次使用 Git 前必须设置的配置项
Git 的提交记录里包含作者信息,这个信息不是自动从系统账号读取的,必须手动配置。不配置的话,很多情况下 Git 会直接拒绝提交,要么就会弹出一个让你补全信息的编辑器。
bash复制git config --global user.name "你的名字"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase false
第四条 pull.rebase false 是我的个人偏好。它表示执行 git pull 时默认走 merge,而不是 rebase。对新手和多数团队协作场景来说,pull 默认 merge 的语义更容易理解,也不会悄悄改写本地提交。如果你喜欢线性历史,后面可以再根据团队约定改成 true。
在 Windows 上建议额外配置换行符自动转换:
bash复制git config --global core.autocrlf true
在 macOS 和 Linux 上则建议:
bash复制git config --global core.autocrlf input
原因是 Git 仓库内一般存的是 LF 换行,而 Windows 本地文件常用 CRLF。不配置的话,Windows 用户可能每次拉取提交都会看到一堆“纯换行符差异”,文件内容明明没动,却整行标红。这个配置就是让 Git 帮你做本地换行符转换,仓库里依然保留 LF,世界太平。
编辑器也可以顺手设一下,避免提交时进入 Vim 不知道怎么退出:
bash复制git config --global core.editor "code --wait"
上面这行把默认编辑器设成 VSCode,--wait 表示等编辑器关闭后才继续执行命令。不想用 VSCode 的话,也可以换成 notepad 或你自己常用的编辑器。
1.3 配置作用域与查看方式
Git 配置分三层,优先级从低到高分别是 system、global、local。规律很简单:范围越小,优先级越高。
| 作用域 | 使用场景 | 配置文件位置 |
|---|---|---|
| system | 整台机器所有用户 | 安装目录下的 etc/gitconfig |
| global | 当前系统用户所有仓库 | ~/.gitconfig |
| local | 只对当前仓库生效 | .git/config |
用下面的命令可以查看当前仓库最终生效的所有配置,以及每一项来自哪个文件:
bash复制git config --list --show-origin
如果只是临时想给某个命令指定一个配置,也可以不修改任何文件,直接在命令后面加 -c 参数,例如:
bash复制git -c user.name="临时名字" commit -m "test"
这种方式在跑自动化脚本、切换提交身份时非常实用,不会污染全局配置。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 每天重复最多的本地快照命令:status、add、commit、diff
Git 的日常工作流本质上是在操作三个区域:工作区(你本地看到的文件)、暂存区(index,也叫索引)、版本库(HEAD 指向的提交)。大部分命令的差异,都来自“三个区域之间到底同步了哪个”。
2.1 最稳妥的本地提交流程
我见过很多同事喜欢上来就 git commit -am "xxx",图省事。但 -a 参数有一个隐患:它会把所有已跟踪文件里发生修改的部分自动加入暂存区,但不会处理新增的未跟踪文件。
新手阶段我建议老老实实走完整流程:
bash复制git status
git diff
git add <file1> <file2>
git diff --cached
git commit -m "feat: 完成登录模块"
先看 status,确认当前改动范围;再 git diff 看工作区还没暂存的内容;git add 只把你确认过的文件放进去;提交前再用 git diff --cached 看一遍“即将提交的快照”到底是什么。这样虽然多打几个字,但能避免把调试日志、临时配置、错误代码一股脑提交进去。
git status 如果觉得输出太长,可以加 --short 或 -s:
bash复制git status -s
输出里每行第一列是暂存区状态,第二列是工作区状态。比如 M 表示已修改,?? 表示未跟踪,A 表示已添加到暂存区,D 表示已删除。看懂这个后,再配合 git diff,日常改动情况基本一眼就能扫完。
2.2 三个 diff 命令别搞混
本地改动排查是 Git 最实用的能力,三条命令针对三个不同比较范围:
bash复制# 工作区 vs 暂存区:还没 add 的改动
git diff
# 暂存区 vs 最近一次提交:已经 add、将要提交的改动
git diff --cached
# 工作区 vs 最近一次提交:所有未提交的改动
git diff HEAD
提交之后想看看这次提交改了什么,用:
bash复制git show --stat HEAD
git show HEAD
--stat 只显示文件变更统计,git show HEAD 会连带展示补丁内容。需要快速复盘刚才提交干了啥时,这两条比 git log 更直接。
2.3 删除、移动和停止跟踪文件
删除文件时,光用系统命令 rm file 不会让 Git 自动感知,必须再 git add 一下,或者直接用 Git 自己的删除命令:
bash复制git rm old-file.txt
git commit -m "chore: remove old-file"
如果是想“让 Git 不再跟踪这个文件,但保留本地文件”,比如误把 .env 配置文件提交了,需要的是:
bash复制git rm --cached .env
echo ".env" >> .gitignore
git commit -m "chore: stop tracking .env"
很多人在 .gitignore 里写了规则,却发现文件仍然被跟踪,原因就是这个文件早就被 Git 纳管了。.gitignore 只对未跟踪文件生效,已经跟踪的文件必须先 git rm --cached,让 Git 从版本控制里移除它。
移动文件也一样:
bash复制git mv old-name.md new-name.md
git commit -m "docs: rename file"
如果已经直接用系统命令改了文件名,Git 通常也能识别出重命名,提交后配合 git log --follow 就能跟踪文件的历史变更。
2.4 .gitignore 实战排查
.gitignore 写错了是最让人摸不着头脑的问题。看到 ?? node_modules/ 时,先确认你的忽略规则是否真的匹配了路径。常见坑是只写了 node_modules 没写斜杠,它本意是忽略所有叫 node_modules 的文件或目录,理论上也够用,但为了明确,建议写成:
gitignore复制node_modules/
dist/
*.log
.env
.DS_Store
怎么验证某条规则到底匹配了哪些文件?用这个命令:
bash复制git check-ignore -v dist/index.js
它会告诉你具体是 .gitignore 里的哪一行规则命中了该文件。排查“为什么没忽略”比肉眼猜规则可靠得多。
3. 分支不是复制代码,是指针移动:创建、切换与合并
要理解分支操作,首先得打破一个直觉:Git 分支并不是把代码复制一份,它只是一个指向某个提交对象的可移动指针。每次 commit,Git 会把当前所有文件内容打包成一个快照,并记录父提交是谁,然后把这个新提交挂到当前分支指针下面。这个设计是所有分支操作的基础。
3.1 创建、切换和查看分支
老一点的命令都有两种写法:
bash复制# 传统写法
git checkout -b feature/login
# 新版写法,语义更明确
git switch -c feature/login
switch 是 Git 2.23 引入的,和 checkout 功能重叠,但 switch 只负责分支切换,不用承担恢复文件等其他职责,命令意图更清楚。我日常更喜欢:
bash复制git branch # 查看本地分支
git branch -a # 查看包含远程跟踪分支在内的全部分支
git switch - # 切回上一个分支
git switch -c fix/567 # 创建并切换
分支命名规则建议统一,比如 feature/订单功能、fix/登录报错、release/v1.2。规范的分支名在自动化部署和 code review 工具里会省很多事。
3.2 merge 和 rebase 到底选谁
这是 Git 最核心也最容易被误解的问题。
假设你在 feature/login 分支上提交了 2 个新 commit,同时 main 分支被别人推进了。此时主线历史已经分叉:
git merge main会把 main 的最新提交合并到你当前分支,并产生一个合并提交(merge commit)。它的优点是保留真实历史,不会改写原有提交;缺点是提交图会出现分叉点,log 看起来不那么线性。git rebase main会把你当前分支基于 main 之后新做的 2 个提交“摘下来”,重新依序应用在 main 最新的提交之后。优点是提交历史变成一条直线,看起来清爽;缺点是提交哈希会变化,相当于改写了历史。
我的建议是:个人 feature 分支还没推到公共远端时,用 rebase 保持整洁;公共分支或已经多人共用的分支,用 merge 更安全。合并前可以先加参数控制行为:
bash复制git merge feature/login
git merge --ff-only feature/login # 只允许快进合并,不允许产生合并提交
git merge --no-ff feature/login # 强制生成合并提交,便于回溯分支归属
3.3 冲突处理:别慌,先看文件再动手
冲突的本质是“两边的修改都影响了同一批行,Git 不知道听谁的”。执行合并或者 rebase 时看到冲突提示后,第一件事不是乱改,而是看哪些文件冲突了:
bash复制git status
git diff --name-only --diff-filter=U
--diff-filter=U 的意思是只显示冲突未解决的文件。打开冲突文件,你会看到类似这样的内容:
code复制<<<<<<< HEAD
当前分支的内容
=======
被合并分支的内容
>>>>>>> feature/login
手动把 <、=、> 这些标记删掉,保留你要的最终内容,然后保存文件,再执行:
bash复制git add 冲突文件
git merge --continue
如果是 rebase 过程冲突,则对应的继续命令是:
bash复制git add 冲突文件
git rebase --continue
不管是什么流程,发现自己搞不定了,最稳妥的退路是中断操作,回到操作前的状态:
bash复制git merge --abort
# 或
git rebase --abort
--abort 会把工作区恢复到执行合并或 rebase 之前的样子。只要没有手动乱提交或乱删分支,这个命令一般都能救你回来。
3.4 cherry-pick 远比你想象的常用
很多时候我并不想做一个完整分支合并,只想把某一个提交单独拿过来,比如线上紧急修复了一个 bug,要同步到 release 分支,用:
bash复制git cherry-pick a1b2c3d4
a1b2c3d4 就是那个提交的哈希前缀。要是同时想拿好几个提交,也可以一次性把它们都写上:
bash复制git cherry-pick a1b2c3d4 e5f6a7b8
cherry-pick 本质上也是把提交复制到一个新位置,会生成新的提交哈希。它适合小范围挑选提交,不适合频繁当分支合并的替身。
4. 多人协作绕不开的远程仓库链路:remote、fetch、pull、push
只要超过一个人开发,Git 的价值就从“本地版本控制”升级成“协作协议”。很多推送失败、历史错乱的问题,都出在没搞清楚本地分支和远程跟踪分支之间的关系。
4.1 clone 之后 remote 是什么
执行 git clone 后,Git 会自动把远端地址保存在本地,名字默认叫 origin:
bash复制git remote -v
git remote show origin
查看远端信息会让你明白 push 和 pull 的默认去向。开源仓库参与贡献时,常见做法是把源仓库设为 upstream:
bash复制git remote add upstream https://example.com/original/repo.git
git remote -v
之后你就可以把主仓库的新代码取下来同步:
bash复制git fetch upstream
git merge upstream/main
4.2 本地分支和远程跟踪分支的配对
本地仓库里会记录一个“远程跟踪分支”,例如 origin/main,它表示“我最后一次从远端看到 main 的样子”。注意,它不会随着别人推送就自动更新,只有执行 fetch 或 pull 后才会刷新。
查看本地分支和远程分支的关联关系:
bash复制git branch -vv
如果输出里本地分支后面没有 [origin/xxx],说明它没和远程分支建立跟踪关系。第一次推新分支时,最重要的一条命令是:
bash复制git push -u origin feature/login
-u 是 --set-upstream 的简写,含义是“推送这次内容,同时把本地分支和远端对应分支绑定”。之后你在这个分支上直接敲 git push 或 git pull,Git 就知道该和谁对齐了。
4.3 fetch 和 pull 不是一个东西
git fetch 只把远端提交下载到本地对应的远程跟踪分支,比如更新 origin/main,但不会动你当前的工作区。git pull 的本质是先 fetch,再合并或变基。
如果你本地 main 落后于远端,直接执行:
bash复制git pull
等价于:
bash复制git fetch origin
git merge origin/main
想要更可控,可以分两步做。尤其是本地已经有未提交改动时,先 fetch 看清楚远端变动,再考虑怎么处理,比盲目 pull 安全得多。
4.4 push 被拒和 force push 的正确用法
推送被拒最常见的原因是“本地提交落后于远端”。此时 Git 会提示你先 pull。处理套路一般是这样:
bash复制git fetch origin
git rebase origin/main
git push
如果 rebase 过程中有冲突,就用前面说的方式解决。这种方式比直接 merge 再推更能保持当前分支线性。
还有一种情况是你确实想用本地历史覆盖远端,比如对已经 rebase 过的本地分支做强制推送。注意,别用 git push --force,要用带安全阀的:
bash复制git push --force-with-lease
--force-with-lease 会先检查远端在你最后一次 fetch 之后有没有被其他人更新。如果远端已经被别人推了新内容,它会拒绝推送,防止你误把别人的提交冲掉。这是我参与多人项目时唯一推荐的强推方式。
删除远端分支的命令不常用,但需要清理时是这样的:
bash复制git push origin --delete feature/old-branch
4.5 远程操作和本地命令的配合序列
真正的团队协作流其实是一个非常标准的循环:
bash复制git switch main
git pull
git switch -c feature/task-123
# 写代码、提交若干次
git push -u origin feature/task-123
提交时要尽量拆分逻辑。不要一个分支攒了五六个不相关的改动再一次性推送。这样做 code review 的人会非常痛苦,你自己回滚的时候也无从下手。
5. 回滚和撤销也分场景:reset、revert、amend、reflog
有人说 Git 最强大的地方不是能后悔,而是能“反复后悔”。但用错撤销命令,也可能把队友的提交搞没。所以要先分清你要撤销的提交到底有没有推送到公共远端。
5.1 已推送的提交用 revert,而不是 reset
如果某个提交已经推送到远端,并且其他同事也基于它继续开发了,最安全的回滚方式是新增一个反向提交:
bash复制git revert a1b2c3d4
revert 不会删除原提交,而是在历史后面追加一个新提交,把那次改动的效果反着应用一遍。这样仓库历史是完整向前的,其他人 pull 也不会遇到历史被改写的冲突。想回滚某个合并提交时,revert 还需要指定主分支线,参数更复杂一点:
bash复制git revert -m 1 merge-commit-hash
日常非必要不建议对已经推送的合并提交做 revert,更容易把后续提交状态搞乱。
5.2 reset 的三个模式
reset 会把当前分支指针回退到指定提交,它有三个模式,区别在于“回退时动几个区域”。
bash复制git reset --soft HEAD~1 # 只移动分支指针,暂存区和工作区都不动
git reset --mixed HEAD~1 # 默认行为,移动指针并清空暂存区,但保留工作区
git reset --hard HEAD~1 # 三个区域全部回到目标提交的状态
举个例子:你刚提交了一次包含敏感配置的 commit,还没推送,想撤销这次提交并保留文件修改,可以这么用:
bash复制git reset --soft HEAD~1
此时 HEAD 回到上一个提交,但你刚才提交的文件改动全都留在暂存区。你再调整内容后重新 git add 和 git commit 就行。
如果连暂存状态都不想要,只想让这些改动回到工作区:
bash复制git reset HEAD~1
--hard 是最危险的模式,它会把工作区里未提交的修改一并丢弃。除非你非常确定那些内容都不需要了,否则少碰。
5.3 提交写完后悔了:amend
提交信息写错,或者提交后发现漏了一个文件,在还没推送到远端时,可以用 amend 修正:
bash复制git add 漏掉的文件
git commit --amend
执行后会用当前暂存区内容,替换上一个提交生成一个新提交。它不是“修改”提交内容,而是生成一个全新的提交并替换原指针。如果原本那个提交已经推送到远端,amend 之后本地和远端历史就分叉了,这时候再推送就必须 force push,所以要尽早 amend。
5.4 reflog 是最后的后悔药
git reset --hard 误操作后,大部分人第一反应是“完了”,但 Git 还留着一份本地操作日志,叫 reflog。它记录的是 HEAD 指针每一次移动的历史,包括 reset、checkout、commit、merge 等操作。
bash复制git reflog
输出类似:
code复制a1b2c3d HEAD@{0}: reset: moving to HEAD~1
e5f6a7b HEAD@{1}: commit: feat: ...
如果你刚刚硬重置回到了 a1b2c3d,但发现自己原本的提交 e5f6a7b 不见了,直接再重置回去:
bash复制git reset --hard e5f6a7b
只要 reflog 里还有记录,分支被删、提交被重置,大概率都能找回来。如果连 reflog 都过期了,还可以用:
bash复制git fsck --lost-found
这个命令会扫描仓库里所有未被任何引用指向但依然存在的对象,然后帮你找回孤儿提交。
5.5 新命令 restore 的正确打开方式
Git 2.23 后,restore 承担了 checkout 的部分职责,专门负责文件级别的恢复。
丢弃工作区某个文件的修改:
bash复制git restore README.md
从暂存区恢复到工作区(也就是取消 add):
bash复制git restore --staged README.md
从某个历史提交恢复文件到工作区:
bash复制git restore --source=HEAD~1 README.md
相比 checkout 多义性,restore 的语义非常明确:restore 就是恢复文件,别的不管。新项目里我建议优先用它。
6. 查历史、定位问题和抽查别人代码的组合用法
遇到线上 bug,第一件事不是去日志系统里翻,而是用 Git 查“这段代码从哪一次提交开始变成这样的”。掌握 log、diff、blame 的用法,排错效率会高很多。
6.1 log 的完整打开方式
最常用的看历史命令其实是一条“带图”的:
bash复制git log --oneline --graph --all --decorate
--oneline 压缩成一行显示,--graph 用字符画出分支结构,--all 显示所有分支,--decorate 在提交旁标记分支名和标签。很多图形化工具的提交图,本质上就是把这条命令的结果做了可视化。
按条件过滤历史:
bash复制# 最近 10 条
git log -10
# 某个人改过的提交
git log --author="zhang"
# 最近一周的提交
git log --since="1 week ago"
# 提交信息里包含关键词
git log --grep="登录"
# 查看某个文件的历史
git log -- README.md
想在历史里精确找出“某行代码是哪个提交引入的”,用 pickaxe 搜索:
bash复制git log -S "oldFunctionName" --oneline -- file.js
-S 会找出增加或删除该字符串次数发生变化的提交。这条命令在排查“谁把某工具函数删了”这种问题时有奇效。
6.2 diff 在不同场景下的准确姿势
除了日常本地 diff,代码评审里最常用的是比较两个分支的差异:
bash复制git diff main feature/login
这个命令展示的是两个分支当前状态的完整差异。有时候你只想知道 feature 分支相对于它从 main 分叉之后改了什么,不想把 main 上本来就有的差异也带进来,可以用三点语法:
bash复制git diff main...feature/login
三点符表示:先找到 main 和 feature/login 的共同祖先提交,再从这个共同祖先到 feature/login 的最新提交做比较。理解这点后,看 PR 差异时不再被无关文件干扰。
想只显示改动文件清单:
bash复制git diff --stat
git diff --name-only
6.3 blame 不是用来追责的,是用来理解上下文的
执行:
bash复制git blame -L 20,40 src/utils/validator.js
会显示这个文件第 20 到 40 行,每一行最后一次是谁在哪个提交修改的。很多人把 blame 当成追责工具,其实它最好的用法是“找到改动这一行的那次提交,然后去看那次提交的 message 和完整 diff”。比如:
bash复制git show <commit-hash>
这比直接问同事“这段代码啥意思”高效得多,因为 commit message 和提交 diff 已经包含了当时的修改意图。
7. 临时切换现场但不想提交:Stash、Worktree 与文件清理
你是不是经常遇到这种时刻:手上功能写了一半,线上突然报 bug,要立刻切到别的分支改个紧急补丁。强制切换的时候 Git 可能提示你“本地改动会被覆盖”。这时候 stash 和 worktree 是你的两个得力助手。
7.1 stash 的正确用法
git stash 的功能是把当前工作区的改动暂存起来,让你回到一个干净的工作区状态。最常用的命令组合:
bash复制git stash push -m "登录功能开发到一半"
git stash list
git stash pop
pop 会把最近一次 stash 的改动恢复到工作区,同时从 stash 列表里删除。如果你不想删除记录,只想恢复,用 git stash apply。
有两个容易被忽略的参数:
bash复制# 把未跟踪文件也一起暂存
git stash push -u -m "包含新增文件"
# 只暂存指定文件
git stash push -- src/App.tsx
默认情况下 git stash 不会处理未跟踪文件,如果你新建的文件还没 add,stash 完它还会留在原地,这时切分支反而可能出问题。加上 -u 会更干净。
stash 列表里存多了之后,用以下命令清点:
bash复制git stash list
git stash show stash@{0}
git stash drop stash@{0}
git stash clear
7.2 worktree:让多个分支并行干活
stash 的缺点是同一时间只能有一个工作现场。如果想把一个仓库同时检出到多个分支,并且互不干扰,用 worktree:
bash复制git worktree add -b hotfix/urgent ../hotfix-checkout
这条命令会在当前仓库旁边创建一个新目录 ../hotfix-checkout,同时基于当前 HEAD 新建并切换到 hotfix/urgent 分支。之后你可以在这个目录里改 bug,原目录继续开发功能,两个目录共用同一个 .git 对象库,互不污染。
用完后清理:
bash复制git worktree list
git worktree remove ../hotfix-checkout
worktree 特别适合 release 分支需要维护、你又不想反复 stash 切分支当精神分裂症患者的场景。
7.3 清理工作区里多余的文件
分支切换后看到一堆临时文件、构建产物,可以用 clean 命令清理,但一定要先看“干跑”结果:
bash复制git clean -nd
-n 表示只列出会被删除的文件,不会真删。确认无误后执行:
bash复制git clean -fd
-f 强制删除,-d 连未跟踪的空目录一起删。如果你想连 .gitignore 里忽略的构建产物也一并清掉,可以加 -x,但这个东西慎用,相当于把当前目录的“非仓库内容”大扫除,误操作成本很高。
8. 实战高频疑难杂症:免密、乱码、异常目录与提交规范
前面七章把主干命令跑完了,剩下的这节是从实战问题里提炼出来的“高频杂症”。每个问题都是我见过不止一次被问到的。
8.1 git 免密到底怎么配
推代码时每次都要输入账号密码,是最容易劝退新人的体验。免密的本质是让 Git 帮你保存凭据,或者改用 SSH 密钥认证。
如果你习惯用 HTTPS 协议,先配置凭据助手:
bash复制git config --global credential.helper store
store 模式会把用户名密码明文存在 ~/.git-credentials,安全要求高的环境不推荐。更好的做法是用缓存模式,让它存一段时间:
bash复制git config --global credential.helper 'cache --timeout=3600'
这个配置表示一小时内存住凭据,但通常只对当前会话有效,重启后可能要重新输入。
我个人的偏好是直接改用 SSH 密钥。流程也不复杂:
bash复制ssh-keygen -t ed25519 -C "you@example.com"
cat ~/.ssh/id_ed25519.pub
把 id_ed25519.pub 里的内容复制到代码托管平台的 SSH key 设置里,然后把本地仓库远端地址切换为 SSH 格式:
bash复制git remote set-url origin git@example.com:username/repo.git
git remote -v
之后执行:
bash复制ssh -T git@example.com
如果能收到欢迎信息,就说明认证通道已经通了。SSH 方式不需要反复输入账号密码,也天然比明文 store 更安全。
8.2 中文文件名变成乱码的修复
很多人在终端执行 git status 时,看到中文文件名被转义成 \345\274\200\345\217\221 这样的八进制序列。原因是 Git 默认会对非 ASCII 字符做转义。解决方法是:
bash复制git config --global core.quotepath false
配置后中文文件名就能正常显示。Windows 上如果 log 中文信息还是乱码,可以顺带检查终端编码是否为 UTF-8。这个问题不解决,不影响 Git 内部数据,但会让你在排查文件时非常痛苦。
8.3 误提交了 node_modules 或 .env 之后的抢救流程
这种情况几乎每个人都犯过。处理流程很清晰:
bash复制git rm -r --cached node_modules
git rm --cached .env
echo "node_modules/" >> .gitignore
echo ".env" >> .gitignore
git commit -m "chore: remove build artifacts from version control"
git push
其中 --cached 的意思是“让 Git 停止跟踪它,但保留本地文件”。推送之后,远端仓库里的历史记录中仍然存在这些文件对象,如果是敏感信息,还要进一步清理历史或者直接轮换密钥。处理完之后,可以把这次的教训写进团队规范里,避免重复踩坑。
8.4 关于 .git 目录的几种常见误会
.git 目录里装着 Git 的全部核心数据,包括对象数据库、引用、配置、钩子、索引等。日常开发除了跑 git 命令会自动更新它之外,尽量不要手动进去改文件。
网上有个关键词叫“git 目录泄露”,意思是站点把 .git 目录暴露到公网,别人可能据此还原源码。作为开发者,我们需要知道的是:不要把 .git 目录提交进任何代码仓库,也不要在公网静态目录里放置可被直接访问的 .git 内容。如果怀疑自己的仓库异常,正确的自检手段是:
bash复制git fsck
git gc
git fsck 会检查对象库的完整性,git gc 执行垃圾回收和对象压缩。这两个命令是 Git 自身的健康管理工具,不是手术刀,但它们能解决很多仓库表现异常的问题。
8.5 值得长期遵守的提交信息规范
命令背得再熟,提交信息乱写,协作体验也会很差。一个能直接照搬的格式是:
code复制<type>(<scope>): <subject>
<body>
type 常用值包括:
- feat:新功能
- fix:修 bug
- docs:文档
- style:格式调整
- refactor:重构
- perf:性能优化
- chore:构建、依赖等杂项
实际提交示例:
bash复制git commit -m "fix(login): 修复验证码过期后提示不清晰的问题"
git commit -m "feat(order): 新增订单导出功能"
规范的提交信息不仅方便同事 review,也是后续自动生成 changelog、按 type 筛选历史的基石。我在团队里一直强调:提交信息是写给人看的,不是完成命令的附赠品。
8.6 最后一点调整心态的小建议
我见过一些开发者计算机基础很好,却在 Git 面前特别没自信,原因只有一个:他们试图靠“背命令”解决 Git,而不是靠“理解模型”解决 Git。只要你能记住 Git 有工作区、暂存区、版本库三个区域,分支不过是指针,reflog 是最后的保险,大部分命令即使忘了具体参数,也能通过 git help 或者 git <命令> -h 重新想起来。真正值钱的不是命令清单,而是面对异常时知道该查哪条命令、该保留什么状态、该避免什么操作。这篇手册里的每一条命令我都按实际使用频率筛选过,建议你把终端打开,每个场景亲手跑一遍,比收藏十遍都管用。
