尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Git命令场景化实战:从版本控制原理到日常开发高手指南

Git命令场景化实战:从版本控制原理到日常开发高手指南 我一直觉得Git 这东西有个特别尴尬的阶段网上教程看了不少add、commit、push这几个命令也会敲可真到了项目里遇到“改错了想回退”“分支搞得一团乱”“远程仓库连不上”这些场景大脑还是一片空白只能老老实实打开浏览器重新搜一遍。这份笔记其实就是我自己的学习记录目标只有一个** 把 Git 命令从“背下来”变成“按场景查表”**。我整理的都是日常开发里最高频的操作配合每个场景背后的原理和坑这样下次手忙脚乱的时候翻一眼就知道该敲哪条命令以及为什么是这条命令。如果你刚接触 Git或者和我之前一样——“命令认识我我不认识命令”那这篇笔记应该能帮你省掉不少瞎折腾的时间。我会尽量用直白的说法把原理讲清楚也会把我在真实项目里踩过的坑一并写出来这些可都是文档里不会告诉你的东西。1. 先搞清楚 Git 到底解决了什么问题从“命名灾难”说起在我们聊具体命令之前我觉得有必要先花两分钟聊聊 Git 存在的意义。搞清楚这个后面所有命令内存负担能减轻一半。1.1 没有版本管理时的“命名地狱”我最早写代码的时候项目文件夹长这样毕业论文_final.doc 毕业论文_最终版.doc 毕业论文_最终版2.doc 毕业论文_再也不改了.doc 毕业论文_改完这版真的不改了.doc是不是很熟悉没有版本管理工具的时候我们只能靠文件名来区分不同阶段。问题是这种办法根本说不清楚“最终版2”和“最终版1”到底改了什么俩人合作的时候更是一场灾难——你改你的我改我的最后合并根本不知道谁覆盖了谁。Git 解决的就是这个问题它像一个“时光机 无限容量的差异记录器”把每一次修改都记录成一个带时间戳、带作者、带修改说明的快照。你随时可以回退到任何一个历史状态也可以把不同人的修改合并到一起还能知道每一行代码是谁在什么时候因为什么改的。1.2 Git 的存储思维快照不是备份这里有个关键认知Git 不是简单地做“文件备份”。备份是整份复制——你存了十份磁盘占用就是十分而 Git 每次提交commit保存的是一个“快照”它记录的是** 那一瞬间所有文件的完整状态**。只不过 Git 做了优化文件没变的部分它不会重复存储只存一个指针指向上一个版本变了的文件它压缩后存起来。所以 Git 仓库再大.git目录通常也是可控的这就是为什么你能放心地提交成百上千次而不必担心磁盘爆掉。这个“快照”思维其实贯穿了 Git 的所有操作尤其是后面要讲的checkout、reset理解了快照就理解了它们为什么是那个行为。1.3 我的推荐学习路线场景驱动网上有海量的 Git 命令表照着敲一遍很快忘光因为命令脱离了场景。我后来换了个思路** 只记“我什么时候会用到什么”**。高频场景其实就那么几个把改好的文件记录下来 →addcommit看看到底改了什么 →statusdifflog改错了想反悔 →restore/reset/revert多条线并行开发 →branchmerge/rebase和远程仓库同步 →push/pull/clone下面几章我会按这个顺序把这些命令逐一拆开讲每条命令都会说清楚“什么时候用”“为什么这么用”“有什么坑”。2. 环境配置那点事装好 Git 以后最易被忽略的隐形坑很多人装完 Git 就直接开干结果第一行命令就报错或者每次 push 都让你输密码烦到不行。这个阶段其实有四个小步骤做一遍能省下后面无数事。2.1 安装三句话说完Windows去官网下载安装包一路 Next。唯一要注意的是安装时会有个“调整 PATH 环境变量”的选项务必选“Git from the command line and also from 3rd-party software”不然有些终端工具里找不到 git 命令。macOS装 Homebrew 的话直接brew install git不想装 Homebrew装 Xcode Command Line Tools 也行它会自带 Git。LinuxDebian/Ubuntu 系sudo apt install git。CentOS/RHEL 系则是sudo yum install git。装完验证一下git --version能输出版本号就说明装好了。这一步很简单但确实是后面所有操作的地基。提示我见过不少新手装完 Git命令提示符不刷新直接去敲git报“不是内部或外部命令”。别急着重装关掉终端再开一个或者重启一下终端工具多半就好了。2.2 配置身份不配置不许提交Git 设计上有个强制要求每次提交必须带着作者信息否则它不让你提交。所以第一件事是配置用户名和邮箱git config --global user.name 你的名字 git config --global user.email 你的邮箱这里有个坑我从同事身上见过太多次GitHub、GitLab、Gitee 这类平台上的账号邮箱和你本地配置的邮箱最好是同一个。不然你提交的记录在平台上是两个毫无关联的人贡献图和代码统计全乱了。我个人建议直接查一下自己远程仓库里绑定的邮箱配置成一样的。想确认配置有没有生效执行git config --list就能看到。还有一种情况公司项目可能会要求你覆盖全局配置那就在具体项目里不加--global给该仓库单独配置git config user.name 公司内部名字 git config user.email 公司邮箱2.3 第一次 commit 编辑器把 vim 基础命令补上当你在终端里敲git commit不带-m参数时Git 会打开一个文本编辑器让你填提交说明。系统默认的编辑器通常是 vimLinux / macOS 上尤为常见。很多新手在这一步直接卡死进去之后不知道怎么输入、不知道怎么保存退出最后直接关掉终端一脸懵。你只需要记住这三组命令就能毕业按i进入输入模式这时候才能打字写提交说明写完后按Esc退出输入模式再输入:wq回车表示保存并退出w是 write写入q是 quit退出。如果中途不想改了用:q!强制不保存退出。但说实话日常提交通常我都是直接git commit -m 提交说明这样压根不用进 vim。揪着 vim 不放的场景是你忘了写-m或者需要写多行提交说明。不过既然入了 Git 的门vim 这三板斧还是值当记一下的。关于编辑器也可以一开始就换成你熟悉的那个比如 VS Codegit config --global core.editor code --wait。这样以后忘带-m弹出的就是 Visual Studio Code编辑体验会友好很多。2.4 免密配置别在密码验证上浪费时间我最早做 pull / push 时每次都要输账号密码烦到怀疑人生。后来才知道可以把本机的 SSH 公钥配置到远程仓库平台上之后所有操作都免密清爽。具体三步# 1. 生成密钥对如果没有的话 ssh-keygen -t rsa -b 4096 -C 你的邮箱执行后它会问你把密钥存哪儿、要不要设密码直接一路回车就行。这时候会在~/.ssh/下生成两个文件id_rsa私钥自己留好和id_rsa.pub公钥可以给别人。# 2. 查看公钥内容 cat ~/.ssh/id_rsa.pub把输出的那一长串复制下来。然后打开你的 GitHub / GitLab 平台找到SSH Keys或Deploy Keys的设置页面粘贴保存。# 3. 验证是否配置成功 ssh -T gitgithub.com如果你用的是 GitHub会看到类似Hi username! Youve successfully authenticated的提示。之后克隆仓库时记得选 SSH 地址而不是 HTTPS 地址格式是gitgithub.com:用户名/仓库名.git。这里有个高频坑** 用 HTTPS 克隆的仓库配了 SSH 公钥也不免密**。因为 HTTPS 走的是账号密码或 token 验证跟 SSH 密钥是两套体系。解决方法git remote set-url origin gitgithub.com:用户名/仓库名.git把远程地址改成 SSH 形式即可享受免密。还有个相关的小问题有些新人配置了 SSH 密钥但还是报“Permission denied (publickey)”。多半是密钥文件路径没对上。Git 默认去~/.ssh/找id_rsa如果你生成的时候改了文件名或者把密钥放到了其他地方Git 找不到自然认证失败。解决办法是在~/.ssh/config里写清楚Host github.com HostName github.com User git IdentityFile ~/.ssh/你的密钥文件名注意私钥文件千万不要提交到 Git 仓库里也不要发给任何人。它就是你远程账户的钥匙。泄露了钥匙别人就能以你的名义改代码后果不轻。3. 提交记录的基本操作三个区域搞明白add / commit 不会再含混刚开始用 Git 的人最常困惑的就是git add和git commit到底什么区别为什么不能一步到位。这背后其实是 Git 的“三个区域”设计清楚了之后很多命令不用背也推理得出来。3.1 三个区域工作区、暂存区、版本库打个比方你写文章工作区Working Directory就是你的桌面文件到处都是改了一半的稿子也摊在上面。暂存区Staging Area / Index像一个“待提交清单”你挑了几页干净的稿子把它们放进一个信封准备寄出去。版本库Repository就是收件箱。信封寄出去的那一瞬间这些稿子才正式被收录、编号、归档。对应到命令上git add 文件名→ 把工作区的修改放进暂存区加入“待提交清单”git commit -m 说明→ 把暂存区里的东西一次性归档到版本库形成一个不可变的快照commitgit status→ 查看现在工作区和暂存区各处于什么状态很多人问为什么非要分两步直接 commit 不行吗这设计其实非常实用——你一个下午改了 5 个文件很可能它们属于 3 个不同的逻辑改动。你可以只把“修复登录 bug”的两个文件add进来提交一次再提交“调整页面样式”的另外三个文件这样历史记录就条理清晰。这就是“暂存区”存在的核心意义** 让你能够精细控制每次提交包含哪些内容**。3.2 日常三连status、add、commit在一个项目里我日常眼熟的命令流程是这样的# 1. 先看状态 git status # 2. 看具体改了啥 git diff # 3. 把需要的文件加进暂存区 git add index.html git add src/utils.js # 4. 提交 git commit -m 修复用户列表的加载卡顿问题git status输出里有两块信息非常直观Changes not staged for commit表示文件有改动但还没addChanges to be committed表示已经add进暂存区、正等着commit。刚学 Git 的同学看这个输出基本就能清楚自己操作到哪一步了。如果改动的文件很多想全部加入暂存区可以git add .当前目录及子目录所有改动或者git add -u仅跟踪已跟踪文件的所有改动不包括新增文件。我日常偷懒常用git add .但拆提交时就会手动逐个add保证每次 commit 的颗粒度合适。git diff也值得拆一下git diff→ 看工作区改动还没add的部分git diff --cached→ 看暂存区跟上一个提交之间的差异也就是你准备提交的内容git diff HEAD→ 工作区 暂存区合起来跟最近一次提交的差异看 diff 的输出习惯之后提交前扫一眼能很大程度上避免“把调试用的console.log一起提交上去”这种尴尬。3.3 git log把历史记录读出花来提交记录一旦多了默认的git log输出会刷满屏幕。我常用的几个参数组合# 一行显示一条清爽很多 git log --oneline # 带分支拓扑看清各分支分叉合并 git log --oneline --graph --all # 查看指定文件的历史 git log --oneline -- 文件名--oneline会把每个提交压成一行左边是缩写 hash右边是提交说明。配合--graph分支的走向看得一清二楚尤其适合处理复杂分支时用。3.4 改完才发现提交说明写错了commit --amend这个命令我一开始完全不知道后来在群里看到别人提了一句才去查。它解决的是这样一个场景你刚git commit -m 修复bug马上发现说明写得太笼统或者文件里忘了一个空格再或者漏提交了一个小文件——但你不想为此再产生一条“补丁式”的提交记录。# 修改最近一次提交的说明 git commit --amend -m 修复用户列表加载卡顿并补充边界处理 # 或者把忘提交的文件加进去再合并到上一次提交 git add 忘提交的文件 git commit --amend --no-edit--amend实际效果是** 把当前暂存区的内容跟最近一次提交合并生成一个全新的提交替换掉旧的**。最后 Git 历史里看不到原来那条只看到新的一条。前提是这“最近一次提交”还没推送到远程。如果你已经git push了再--amend会改变提交 hash远程和本地历史就“分叉”了要推上去必须用git push --force强制覆盖这在多人合作的分支上非常危险——会把别人基于旧提交拉的分支统统弄乱。所以老规矩** 本地刚写完觉得不爽就 amend推上远程了就老老实实开新一轮提交**。3.5 撤销的艺术restore、reset、revert 怎么选这可能是 Git 命令里最让人头大的一片因为它牵涉到“撤销到什么位置”。我把它们拆成三个场景来讲场景一工作区改乱了想回到没改之前git restore 文件名这个命令会把工作区文件恢复到暂存区/最近提交的状态。注意未add的改动会被直接丢光恢复不了操作前确认一下。场景二已经 add 进暂存区想移出来但保留改动git restore --staged 文件名这个非常常用我经常一不小心git add .把所有文件都加进去了但实际上只想提交其中一半。用这条命令把不该提交的文件从暂存区“挪”出来改动还在工作区乖乖躺着。场景三已经 commit 想回退历史这里要看你是想“彻底删除”还是“保留记录地反悔”git reset --soft HEAD~1软回退。只移动 HEAD 指向工作区和暂存区的内容全都保留。相当于撤销了一条提交记录但所有改动还在重新整理后再次提交。git reset --mixed HEAD~1默认模式。回退到上一个提交并且暂存区被清空但工作区改动还在。适合你发现自己提交错了一堆东西想重新整理的场景。git reset --hard HEAD~1硬回退。彻底回到上一个提交的状态工作区所有未提交的改动全部被删除。这条命令每执行一步都是“不可逆的”我建议只在确定这些改动都不需要的时候才用。三者的区别我用这个表格记命令工作区暂存区版本库提交历史--soft保留保留回退--mixed默认保留清空回退--hard清空清空回退而当你已经把提交推送到远程、其他人可能已经拉取时不管reset还是amend都会引发同步问题。这时候该用的是git revert commit-hash。它是** 创建一条“反向提交”**把你之前那次提交做的改动撤销掉生成一条新记录历史不会被改写。多人协作时这是最安全、最体面的撤销方式代价是历史上会多出两条记录原来的 反向的看着不够“干净”但安全第一。4. 分支操作的正确姿势合并一次你就全懂了分支是 Git 最核心也最强大的设计没有之一。很多新手怕分支总觉得是高级玩法但其实只要理解了“分支只是指针”这个本质就没什么神秘的了。4.1 分支到底是个什么东西你可以把分支理解成一根“可移动的便签”贴在某次 commit 上。每提交一次当前分支指针就跟着往前挪一格。比如你从main分支上切出一个新分支dev它俩一开始指向同一个 commit。之后你在dev上提交了两次dev往前走main还停在原地。这就是“两条开发线互不干扰”的本质——** 两个指针指向的位置不同而已**。4.2 创建、切换、删除一气呵成# 查看所有分支带 * 的是当前分支 git branch # 创建新分支并切换过去最常用 git checkout -b feature/login # 只创建不切换 git branch feature/login # 切换分支 git checkout feature/login # 新版 Git 推荐用下面这个语义更明确 git switch feature/login # 删除分支 git branch -d feature/login这里有个必须记住的坑** 切换分支前先保证工作区是干净的要么提交了要么 stash 了**。否则你在分支 A 没提交的改动会因为 checkout 一起“漂移”到分支 B 去轻则两个分支间内容串味重则直接因为冲突拒绝切换。如果确实有改到一半不想提交的文件又需要立刻切分支处理问题可以git stash # 把所有未提交改动存到一个临时区域 git checkout 其他分支 # 处理完了切回来 git stash pop # 恢复之前存起来的改动stash这个命令我一度觉得冷门但真正忙起来的时候救过我好几次命。忘了就查git stash list想清空可以git stash clear但小心——那是真没了。4.3 合并fast-forward 和三方合并把一条分支的修改并入另一条用merge# 先切到你“想要收编别人改动”的分支 git switch main # 把 dev 分支的改动合并进来 git merge dev合并的时候Git 会分两种情形第一种fast-forward快进合并。当 main 自 dev 分叉出去后没有任何新提交也就是 dev 领先于 main 一条直线Git 只需要把 main 指针直接移到 dev 的位置即可历史还是一根直线干净利落。第二种三方合并merge commit。当 main 也有自己的新提交两条线在分叉后各自往前走Git 就必须找到“共同的祖先提交”和双方的最新状态尝试融合出一个新提交。这个场景下一旦同一行的代码两边都改了Git 就没办法自动决定于是报冲突conflict。很多新手遇到冲突就慌其实处理方法很固定。4.4 冲突不可怕完整走一遍假设main分支和feature/login分支都改了README.md的同一行merge 时你会看到CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.打开README.md里面会有这样的标记 HEAD 这是 main 分支上的内容 这是 feature/login 分支上的内容 feature/login HEAD到之间是当前分支的内容到之间是正要合并进来的分支内容。你手工编辑这个文件决定最终保留哪一段、删除哪些标记然后git add README.md git commit -m 解决 README 冲突合并两个分支的改动合并冲突就用这三步** 手工改文件 → add → commit**。没有魔法也不需要高级命令。唯一要留神的是解决冲突时别把别人的改动整个覆盖掉了逐行确认后再提交。多经历几次你甚至会习惯这种“可控的人工裁决”。如果你问merge和rebase怎么选我的态度是** 团队协作的分支上优先 merge保证历史真实可追溯个人开发或清理本地提交时可以用 rebase 让历史更线性**。Rebase 是“把一条分支上的提交拾起来、重新在另一条分支的顶端按顺序重放一遍”看着历史是直线但相当于改写了提交记录所以公共分支上别乱用。4.5 删除分支的 -d 与 -Dgit branch -d 分支名只允许删除“已经被合并过”的分支这是安全保护。如果你想删的是一个还没合并、改动只有自己知道的本地分支Git 会拒绝并提示error: The branch xxx is not fully merged.这时候需要用-D强制删除git branch -D 分支名我自己的体会是-d拒绝时先别急着-D确认一下这个分支真的没用了。万一是该 merge 到你所在分支而你忘了 merge那-D会把整条改动丢进回收站找不回来。宁可先切过去看一眼git log再决定动不动手。5. 远程仓配的经典连环坑从 clone、push 到 SSH 认证失败本地玩得再花哨最终还是要跟远程仓库打交道。这一段的命令不多但坑是真的多。我按一个项目的诞生顺序来讲。5.1 从零连接一个远程仓库git remote假如你在 GitHub / GitLab / Gitee 上新建好了一个空仓库本地也已经有项目了连接的方式# 把远程仓库地址命名为 origin约定俗成的默认名 git remote add origin gitgithub.com:用户名/仓库名.git # 查看连接情况 git remote -v # 如果发现地址填错了想改 git remote set-url origin 新地址 # 如果想删掉远程关联 git remote remove origin这里最容易被忽略的git remote add origin只是建立了一个“远程仓库的快捷方式”它本身不会推送任何代码。刚建完仓库的新手容易误以为已经“上传”了一看远端还是空的就犯嘀咕。真正的上传靠的是下面这条# -u 表示首次建立本地 main 分支与远程 origin/main 的跟踪关系 git push -u origin main第一次推送时加-u以后在这个分支上只需git pushGit 就知道推送给谁了。5.2 把远程仓库拉到本地clone、pull、fetch最常见的开始方式是克隆已有仓库git clone 仓库地址 git clone 仓库地址 自定义目录名克隆下来的项目带有完整的 Git 历史。之后日常同步git pull很多人对pull和fetch的区别也懵。其实git pullgit fetchgit merge。fetch只是把远端最新提交下载到本地存在origin/main这条远程跟踪分支上** 不动你工作区的代码**而pull会自动接着执行合并把你的本地分支跟远端同步。建议初期就记pull好了等你需要精细化控制同步过程时再拆分用fetch。有冲突的时候pull也会直接报冲突解决方式和 merge 冲突完全相同——手工改、add、commit。5.3 SSH 认证失败一次完整的排查链路“SSH 认证失败”“Permission denied (publickey)”是 GitHub 新手区的经典疑难杂症。我把自己排查这类问题的经验写成固定套路供你照着走第一步确认协议。先看你的克隆地址git remote -v如果输出是https://github.com/...那认证走的是 HTTPS 体系SSH 密钥根本不会参与你折腾半天公钥都没用。要么改用 SSH 地址要么配 HTTPS 的 token。第二步确认密钥存在且路径正确。ls -la ~/.ssh/看看没有id_rsa和id_rsa.pub不确定就先重新生成一份然后确认是否把.pub的内容粘到了平台的 SSH Keys 设置里。第三步测试连接。ssh -T gitgithub.com你能看到Hi xxx!就说明认证通了看到 permission denied 就继续往下走。第四步检查 ssh-agent 和 config。有些场景下密钥不在默认路径或系统没自动加载密钥手动指定一把试试ssh-add ~/.ssh/你的密钥文件名 ssh -T gitgithub.com第五步看具体报错信息里的关键词。比如port 22: Connection refused这类就说明确实连不上服务器排查方向直接从“认证”转向“网络连通性”了。我建议每次排查都从git remote -v看协议开始别一上来就重装 Git八成不是 Git 的问题。5.4 Git LFS大文件别往普通仓库里塞Git 的设计偏向保存文本源代码。你往仓库里放一个几百 MB 的设计稿、数据集、二进制安装包仓库会越拉越慢.git目录飞速膨胀。Git LFSLarge File Storage就是用来处理大文件的替代方案——它把大文件的实际内容存到远端专用的存储服务里Git 仓库里只放一个轻量的指针文本。# 1. 装 LFS git lfs install # 2. 标记要追踪的大文件后缀/路径 git lfs track *.psd git lfs track *.zip git lfs track assets/ # 3. 提交 .gitattributesLFS 会生成或让你更新它 git add .gitattributes git commit -m 配置 LFS 追踪大文件 # 之后正常 add / commit / push 即可我踩过的坑是** 配置 LFS 之前误把大文件直接git add进普通仓库过**结果历史记录已经被大文件的完整内容污染哪怕后来删了文件、提交新的版本.git目录里的旧记录依然占着空间。要清理这种事后的“历史遗留大文件”得用git filter-branch或git filter-repo重写历史又复杂又有风险。所以最佳策略永远是** 项目一开始就决定好哪些资源要走 LFS**。还有个高频问题同事问我“git lfs clone 为什么卡住”。其实git clone遇到 LFS 仓库时Git 会并发从 LFS 存储下载大文件网络慢或者平台限流看起来就是一直卡在某个百分比。可以试试GIT_LFS_SKIP_SMUDGE1 git clone 仓库地址先跳过 LFS 文件下载拿到源码之后按需用git lfs pull下载大文件。这样至少能先把代码看起来不至于整个克隆进程卡死。5.5 仓库里的敏感信息这是底线问题热词里有“git 目录泄露如何下载”这个背后的本质其实是个很严肃的安全问题——** 如果项目根目录的.git文件夹被发布到了公开可见的位置等于把整个仓库历史、所有分支的源码甚至历史密钥都泄露出去了**。对开发者来说反过来的教训更值得记永远不要把这个目录暴露给不该看到的人也永远不要把.env、密钥文件、数据库密码这类敏感内容提交进去。Git 提供了一套防线最基础的是.gitignore和提交前的自查敏感配置文件一律加进.gitignore提交前用git status和git diff扫一眼看有没有意外带进去的文件一旦发现敏感信息已经被推到远程不要再指望“删掉再提交一次”能抵消痕迹——历史记录里全在。需要立刻更换密钥、凭证并把旧的信息作废真需要擦除历史的情况下用git filter-repo这类工具重写历史后强制推送我不建议展开讲任何“如何从泄露目录里捞东西”的操作这里只有一句忠告** 管好自己的提交物敏感信息绝不入库密钥泄露即刻作废重换**。这是每个拿 Git 做开发的人都该有的基本素养。6. 踩坑笔记过滤文件不生效以及那些“疑难杂症”最后一章我来盘点几个我身边反复出现的“Git 疑难杂症”基本都属于“上网搜了半天才发现是某个小配置问题”的类型。6.1 .gitignore 写了却不生效都是缓存惹的祸太经典了。你把.gitignore配好加上node_modules/、.env但执行git status时这些文件还在列表里冒头或者还是被git add .加了进去。核心原因**.gitignore只对“还没被 Git 跟踪”的文件生效**。如果某个文件在此之前已经被git add或git commit过Git 已经把它的元信息记在索引里了之后再写.gitignore拦不住它。解决办法是把它从 Git 的索引里移除但保留本地文件git rm -r --cached . git add . git commit -m 应用 .gitignore 规则清理已跟踪文件的缓存第一条命令会把所有文件从暂存索引移除工作区不动再add .时 Git 会重新读取.gitignore不该跟踪的从此就安分了。顺带一提.gitignore写法的几个常见误区node_modules匹配的是任何层级下的同名目录/node_modules只匹配根目录下的以/结尾表示只匹配目录*通配符不匹配路径分隔符**才可以跨目录。这些细节在排错时非常管用。6.2 大小写改名的文件Git 死活不认你在 Windows 或者 macOS 默认文件系统上干活把readme.md重命名成README.md然后git status发现 Git 无动于衷提交记录里看不出来。这是文件系统“大小写不敏感”的锅。Git 默认配置core.ignorecase的值是 true它会把单纯的大小写变化当成“没变化”。解决办法是显式告诉 Git 这次变化git mv README.md readme.md git mv readme.md README.md git status或者更简单粗暴临时把配置改掉让 Git 开始敏感比较大小写git config core.ignorecase false但注意这个改动会影响当前仓库的大小写敏感性改完之后对存量文件的处理要格外小心建议只在确实需要重命名大小写的场景下临时开启。6.3 换行符CRLF/LF引发的“整个文件都变了”惨案Windows 上写的代码一行结束用的是CRLF回车换行Linux/macOS 是LF换行。如果你在 Windows 上改了某个文件的一个小地方提交到 GitHub同事在 Linux 上打开 diff 一看整份文件全红了——原因是 Git 把换行符也当作改动一起比对了。解决方案是配置 Git 的换行符自动转换# Windows 上 git config --global core.autocrlf true # Linux / macOS 上 git config --global core.autocrlf input原理不展开讲记住这个对照配置即可。true意味着检出代码时把 LF 转成 CRLF适配 Windows 编辑器提交时把 CRLF 转回 LF保证仓库里存的都是 LF。input意味着不转换检出的只保证提交时统一为 LF。如果你的团队已经有存量代码饱受换行符之苦更靠谱的做法是给仓库加一个.gitattributes文件按文件类型显式声明换行规则* textauto *.js text eollf *.sh text eollf *.bat text eolcrlf.gitattributes的优先级高于个人配置能强制全团队保持一致强烈建议项目初始就加上。6.4 我关于“学习 Git 不靠硬背”的最后一点建议这几章写下来我最大的体会是Git 命令本身不难难的是把命令和场景对应起来。我自己的做法是维护一张“场景卡”遇到新问题就往里加两条现在已经积累了厚厚一沓“想回到上一个提交的状态但不想丢改动” →git reset --soft HEAD~1“提交到本地但发现不该提交” →git reset --mixed HEAD~1“改到一半想切分支” →git stashgit stash pop“想撤销已推送的某次提交” →git revert hash“想合并多条连续提交记录” →git rebase -i HEAD~n“误删分支想找回” →git reflog配合git branch 分支名 hash“只想暂时保存某个文件到远程但不进本地仓库” → 这种场景就去查git archive或者干脆别用 Git 干这事git reflog值得单独提一嘴它是 Git 的“操作日志”记录了你每一次 HEAD 移动的历史。即使git reset --hard搞丢了提交只要没到垃圾回收的时限都能通过git reflog找回那个 hash。学 Git 的新人知道这个能少哭几回。至于“命令行提交代码”这件事说实话一开始也别过度追求命令行全家桶配上 VS Code 的 Git GUI、或专门的可视化工具日常操作确实舒服很多。但我始终坚持** 命令行是理解 Git 底层逻辑最好的方式**图形化工具点几下完成的事你可能完全不知道背后发生了什么等出问题时无从下手。先把命令行这套过一遍再回去用图形工具心里会踏实得多。
返回列表