
之前有个同事问我写代码最怕遇到什么。我想了想不是复杂的业务逻辑也不是难查的Bug而是改着改着发现改错了想回到之前的版本却回不去。编辑器里的撤销、CtrlZ那点历史缓存遇到稍微长一点的需求周期就完全不顶用。后来我认真把 Git 用起来之后这个“回不去”的焦虑从此消失了。这篇博文就是一份面向个人使用者的 Git 基本操作笔记从 git 安装、git 配置、git 提交、分支合并、远程仓库协作到平时最常见的报错排查按照我实际使用的路径全部过一遍。不管你是刚入行的新手还是用过 Git 但一直没系统整理过的人都可以直接照着操作。Git 这个名字听起来有点“极客”但核心思想其实特别朴素把项目的每一次变化都记录下来像一个带存档功能的游戏。你可以在任意存档点之间跳转、分叉、合并甚至制造出不同的时间线互不干扰。个人用 Git 最大的好处还不是协作而是两条一是自己写代码时可以随时回退不用再整天复制文件夹保存备份二是配合 Gitee、GitHub 这类远程仓库等于给自己的代码上了个异地备份换电脑之后拉下来就能继续干活。接下来我从安装配置讲起一路讲到常见问题排查全是实操内容没有空泛概念。1. 从零开始安装 Git 并完成基础配置1.1 按系统选择安装方式别下错包Windows 用户最简单直接去 Git 官网下载 Git for Windows 安装包。下载的时候注意区分 32 位和 64 位现在绝大多数机器都是 64 位文件名里一般会带 x64 字样。安装过程一路 Next 就可以唯一建议留意的是默认编辑器选项如果你习惯用 VSCode可以在安装时选到 VSCode或者等装完再用配置命令去改。装完后在任意文件夹空白处点右键菜单里会出现 Git Bash Here这个选项非常实用相当于在 Windows 里模拟了一个干净的 Linux 风格命令行后面我的所有命令都建议在 Git Bash 里执行。macOS 用户有两个选择。如果机器上已经装过 Xcode Command Line Tools那可能系统里已经自带了一个 Git先不用急着装。没有的话直接去官网下载 dmg 安装包也能搞定。另外很多开发者喜欢用 Homebrew一条 brew install git 照样完成安装而且装完通常是最新版本。Linux 用户一般是 apt 或 yum 系Debian/Ubuntu 执行 sudo apt update sudo apt install gitRocky/Fedora 执行 sudo dnf install git。这几种方式没有优劣之分挑你最顺手的环境来。1.2 全局配置提交者的身份信息必须写对安装完成后的第一件事是设置身份信息。Git 的每次提交都会永久记录提交人的名字和邮箱未来看历史时这些信息会一直留在那里。个人项目也是一样别偷懒跳过。git config --global user.name 你的名字 git config --global user.email 你的邮箱 git config --global init.defaultBranch main第一行设置提交时显示的用户名建议用真实的昵称或姓名拼音方便自己以后看日志时一眼认出来。第二行设置的邮箱理想情况下应该和你注册平台账号用的邮箱一致这样推送到 Gitee 或 GitHub 后平台能把提交记录关联到你的账号上。第三行 init.defaultBranch 是我强烈建议加上的一条它把新建仓库的默认分支名从 master 改成 main否则每次 git init 之后都会冒出 master/main 混用的情况虽然不影响使用但看起来非常乱。改完之后可以用 git config --global --list 查看当前所有全局配置确认这三条都出现在输出里就说明基础配置完成。1.3 验证安装是否成功配置完别着急新建仓库先做两个小验证。第一个是 git --version输出类似 git version 2.40.0 这样的信息说明安装成功。第二个是不带任何参数的 git它会列出 git 的常用子命令比如 clone、init、add、commit、branch、checkout 等等。初次接触命令行的读者看到这张列表不要慌后面几节我们把这些命令逐个过一遍。这里补充一个很多人忽略的点git --version 显示的版本号后三位如果是 2.3x 甚至更高就说明你不是在一个极其古老的 Git 版本上工作后面讲的 git switch、git restore 等命令都可以放心用。如果你的 Git 版本低于 2.23那我建议尽早升级因为老版 Git 的命令习惯和现在的新命令差了不少网上很多教程基于新版编写照着敲却报错多半就是版本太老导致命令不存在。2. 搞懂工作区、暂存区与版本库一切命令的基础2.1 三个区域的关系用购物车来理解先看一个简单到有点无聊但特别关键的概念。Git 把一次提交分成三个区域工作区、暂存区、版本库。工作区就是你电脑上实际能看到的那些文件和文件夹暂存区存在于 .git 目录里可以理解成购物车你往里面放什么下一次提交就会包含什么版本库则是 Git 真正保存历史快照的地方执行 commit 之后暂存区里的内容被打包成一次提交永久记录进版本库。日常操作基本上就是这三件事git add 把工作区改动加入暂存区相当于把商品放进购物车git commit 把暂存区内容固化成一次提交相当于结算打包并贴上一个带时间戳的标签git checkout 或 git reset 则相当于从货架上恢复商品。很多新手一开始只背命令不理解为什么要多一个暂存区结果总是漏掉 git add 或者多提交东西。一旦用购物车来类比整个过程就顺了。2.2 用 git status、git diff、git log 掌握全部状态三个命令是日常最高频的组合。git status 告诉你当前仓库处于什么状态哪些文件被改了哪些已经加入暂存区哪个分支上有未推送的提交git diff 看具体改动内容不加参数时显示工作区与暂存区的差异加上 --staged 参数显示暂存区与上一次提交的差异git log 看提交历史加上 --oneline --graph --all 之后会用一行一个提交的格式图形化展示所有分支的关系。git status git diff git diff --staged git log --oneline --graph --all我的建议是在还不熟悉 Git 的时候每次执行 add、commit 之前都习惯性敲一下 git status。别嫌麻烦这个命令的输出就是你的“仪表盘”它会明确告诉你操作进行到哪一步了。等用顺手了这套状态查看命令会成为你的肌肉记忆。2.3 .gitignore 写了却不生效多半是文件已经被追踪热词里有一条“git 的过滤文件 没有作用”这是新手几乎一定会踩的坑。我在刚接触 Git 时也遇到过明明在 .gitignore 里写了 node_modules/git status 却还是能看到这一大堆文件要提交。查了很久才明白.gitignore 只对“尚未被 Git 追踪untracked的文件”生效。如果某个文件在写 .gitignore 之前就已经被 git add 追踪过了那后来再怎么在 .gitignore 里写它也拦不住。解决办法也很直接把该文件从 Git 的追踪记录里移除但保留在磁盘上git rm --cached 具体文件路径如果是一个目录底下的所有缓存可以用 git rm -r --cached 目录路径。执行完之后再把路径写进 .gitignore重新 git add 和 git commit这时 Git 就会跳过它了。另外还要检查一下 .gitignore 的拼写我见过有人把文件名写成了 .gitingore那自然怎么配都没用。匹配规则里需要注意build/ 匹配所有目录下的同名 build 目录而 /build 只匹配仓库根目录下的 build想用通配符的话 *.log 匹配所有 log 后缀文件。3. 日常提交与分支管理从 commit 到 merge3.1 一条完整的本地提交链路个人项目不必像团队项目那样走评审流程但提交链路必须完整。标准顺序是先 git status 看看有哪些改动再 git add 把需要的文件加入暂存区然后 git diff --staged 检查一遍即将提交的内容确认无误后 git commit -m 写清楚本次改动做了什么最后 git log 确认提交成功。git status git add . git diff --staged git commit -m feat: 完成用户登录功能 git log --oneline这里必须提醒一句不建议每次都无脑 git add .。个人项目虽然是你自己说了算但一旦项目变大git add . 很容易把临时的调试文件、日志文件、甚至密钥文件一股脑加进去。我现在的习惯是写一个稳定的 .gitignore把常规忽略项都提前配好然后再用 git add . 才会比较安全。如果想精确控制就 git add 具体的文件路径。3.2 分支的创建、切换与删除Git 的分支本质只是一个指向某次提交的可移动指针创建成本极低。你完全可以把它理解成游戏存档里的不同进度每个分支都代表着一种独立的修改方向。个人项目里我常用的分支命令如下git branch dev # 创建 dev 分支 git switch dev # 切换到 dev 分支 git switch -c feature/login # 创建并切换到 feature/login git branch -d dev # 删除 dev 分支已合并时使用 -d git branch -D dev # 强制删除 dev 分支未合并时用大写 D新版 Git 建议用 git switch 来切换分支语义清晰不易和 git checkout 的多种职责搞混。注意 git branch -d 在分支还有未合并改动时会拒绝删除这是保护机制别为了省事直接上 -D除非你确定这个分支真的不要了。3.3 把 master 上写好的代码转移到 dev 分支热词里有一条“在 master 上写的代码怎样剪切到 dev 上”这个问题本质上取决于代码是否已经提交。如果改动还没提交最简单的方法就是直接切换分支。Git 允许你带着未提交的改动从一个分支切到另一个分支只要目标分支和当前分支在相同位置没有冲突。到 dev 分支后正常 add、commit 即可。但如果切换时报错说某些文件会覆盖目标分支的文件那就先暂存一下git stash push -m 临时保存未提交改动 git switch dev git stash pop如果改动已经在 master 上提交过了那就用 cherry-pick。先找到这次提交的哈希值然后切到 dev 分支把提交复制过来git log --oneline # 找到要移动的提交哈希例如 a1b2c3d git switch dev git cherry-pick a1b2c3d这样 dev 分支就出现了和 master 上一样内容的提交而 master 上的原提交还在。如果你想把 master 也回退掉可以再切回 master执行 git reset --hard 上一个提交的哈希。注意 reset --hard 会丢掉未提交的改动而且会改写历史个人项目可以这么用和别人协作时千万谨慎。我个人更推荐 cherry-pick 而不是 reset宁可让 master 上留着一条提交记录也不要用危险命令删掉已有历史。3.4 合并冲突遇到 别慌分支开发到一定阶段总要合并。git merge 的常规流程是把另一个分支合并到当前分支git switch main git merge dev如果两个分支改了同一个文件的同一段内容Git 无法自己决定取舍就会提示冲突。这时你去打开冲突文件会看到类似下面的内容 HEAD 当前分支的代码 dev 分支的代码 dev遇到这种标记不要慌手动把不需要的部分删掉保留你最终想要的结果并把 、、 这些标记也一并删除。然后执行 git add 冲突文件最后 git commit 完成合并。特别注意冲突解决后必须手动 commit否则 Git 会一直停留在“待提交的合并结果”状态。我踩过的坑是解决完冲突后直接跑了回头看到工作区一堆未提交文件还以为仓库坏了。3.5 在 IDEA 里克隆项目与合并分支虽然我推荐命令行但很多开发者在代码编辑器里会更习惯图形界面。IDEA 的操作和命令行其实一一对应。打开 IDEA 后在欢迎页选择 Get from Version Control填入远程仓库地址即可把项目拉下来。项目打开后右下方会显示当前分支名点开就能看到所有远程和本地分支切换分支图标就在旁边。要合并分支时先切到目标分支比如你想把 dev 合并进 main就先在右下角点 main然后用菜单 VCS - Git - Merge Branches在弹出的窗口里选择 dev点击 Merge 就行。IDEA 里如果出现了冲突也会弹出一个可视化对比窗口左边是本地右边是要合并进来的中间是结果处理起来比命令行更直观。4. 远程仓库玩法clone、push、pull 与免密登录4.1 远程仓库和个人使用有什么关系远程仓库可以理解成放置在代码托管平台上的一个 Git 仓库副本Gitee、GitHub、GitLab 都是常见的托管平台。个人使用者连远程仓库的首要价值是备份和多设备同步。我的一位朋友以前只在本地写代码笔记本硬盘坏了之后所有项目一夜回到解放前。后来他把所有仓库都推到了远程换新电脑后 git clone 一遍半小时恢复所有项目这种安全边际是任何移动硬盘都比不了的。远程仓库和本地仓库之间的操作无非就是推送和拉取。推送是把本地新的提交发给远程拉取是把远程新提交下载到本地。这里不涉及复杂的团队流程个人用的话只要理解几条核心命令就够了。4.2 clone 一个远程仓库到本地git clone 是获取远程仓库最快的方式。命令格式很简单git clone 仓库地址 git clone 仓库地址 自定义目录名执行完 clone 后本地会自动生成一个同名目录里面包含远程仓库的所有历史记录并且自动配置好了一个名为 origin 的远程别名。也就是说 clone 之后你不需要再 git remote add直接就能在目录里 git pull 和 git push。这也是 clone 和“新建项目后手动 remote add”最明显的区别。4.3 本地新建项目推送到远程很多人第一次在平台创建新项目时会遇到这种情况平台给了你一串命令直接复制粘贴就能用。这串命令通常长这样echo # demo README.md git init git add README.md git commit -m first commit git branch -M main git remote add origin gitgitee.com:用户名/仓库名.git git push -u origin main逐条解释一下。git init 在当前目录初始化一个空仓库git add 和 commit 把初始文件提交git branch -M main 把当前分支强制重命名为 main保证和远程默认分支一致git remote add origin 地址 给远程仓库取名为 origin最后 git push -u origin main 是第一次推送的关键-u 参数会把本地 main 分支与远程 main 分支建立关联关联之后以后直接敲 git push 就能推不用再带参数。4.4 SSH 免密配置告别每次输密码用 HTTPS 地址推送时平台一般会要求输入账号密码或访问令牌每次操作都输一遍挺影响心情。更顺手的做法是配置 SSH 密钥配完之后推送和拉取全程免密这也是热词里“git配置gitee密钥”和“ssh认证失败 git”的由来。生成密钥的命令ssh-keygen -t ed25519 -C 你的邮箱生成过程中一直回车使用默认路径就行密码那一步如果不想要就再按一次回车。生成成功后公钥在 ~/.ssh/id_ed25519.pub 里私钥在 ~/.ssh/id_ed25519。用记事本或命令行 cat 查看公钥内容把整段复制到 Gitee 或 GitHub 的 SSH Keys 设置页面里保存即可。然后测试连接ssh -T gitgitee.com ssh -T gitgithub.com如果返回欢迎消息说明配置成功。常见的认证失败原因有三个一是公钥没有完整复制缺了开头或者结尾二是去平台添加公钥时不小心复制成了私钥三是本机存在多个 SSH keysshd 识别不了。排查时只保留一个常用 key 是最省心的方案。之前用过旧版 RSA 加密生成密钥的人用 ed25519 重新生成一次也不麻烦新平台普遍更推荐 ed25519。4.5 push 被拒绝与 fetch、pull 的选择推送被拒绝最常见的情况是远程仓库有本地没有的提交。比如你在另一台机器上推送过代码回到这台机器继续开发后直接 git pushGit 会拒绝并提示 non-fast-forward。这时候需要先把远程的新提交同步下来git fetch origin git rebase origin/main git push或者一条命令等价完成git pull --rebase origin main这里顺便解释 fetch 和 pull 的区别。git fetch 只是把远程的新提交下载到本地更新 origin/main 这样的远程跟踪分支但不会动你正在工作的分支git pull 则是 fetch 之后自动执行一次合并。直接用 pull 省事但会在历史上留下 merge 提交个人项目里我更喜欢 fetch 加 rebase 的写法它能保持历史是一条干净的直线。rebase 的原理是把你的本地提交“搬到”远程最新提交之后重放一遍。整个过程不可怕但如果中途遇到冲突解决完继续 git rebase --continue 即可。4.6 私有仓库推送时的权限逻辑很多人在平台建的是私人仓库担心是不是推送更复杂。其实私人仓库和公开仓库在 push 流程上没有区别区别只在“谁有权限访问”。平台判断权限靠 SSH 公钥或 HTTPS 凭据只要你的账号是仓库创建者或者被加为协作者就能正常推送。个人项目基本一个人操作不需要研究团队权限矩阵认准一件事公钥配好了push 和 pull 就畅通无阻。5. 进阶操作与疑难杂症5.1 git commit --amend补救上一次提交热词里专门有“git commit --amend怎么使用”说明这确实是个高频需求。场景很典型提交完才发现漏了一个文件或者提交注释写错了又或者想把两处改动合并成一次提交。amend 就是修改上一次提交的命令。git add 漏掉的文件 git commit --amend --no-edit--no-edit 表示保留原提交信息不修改。如果想顺便修改提交信息用 -m 参数覆盖git commit --amend -m 新的提交注释需要留意的是amend 会生成一个新提交哈希等于把旧提交替换掉了。如果这个提交已经推送到远程push 时会被拒绝需要强推。强推命令是 git push --force-with-lease相比 git push --force 更安全一点它会检查远程分支是否发生过别人改动。个人项目强推问题不大但养成习惯shared 分支上别用 amend因为一切会改写历史的操作都不适合团队协作环境。5.2 fetch、cherry-pick、revert 三者的区别一次讲清楚这三条热词放一起其实挺容易混。我先放一张对照表后面再细说。命令作用是否创建新提交典型场景git fetch从远程下载提交更新远程跟踪分支不改变当前分支想先看看远程新东西再决定怎么合并git cherry-pick把某个已有提交复制一份到当前分支会生成新提交只想把一个分支的某次改动拿过来git revert撤销某次提交的改动通过反向提交实现会生成新提交撤销已经推送到远程的提交且不破坏历史fetch 和 cherry-pick 乍听都是“拿东西”区别在于 fetch 面对的是远程仓库整体cherry-pick 面对的是本地任意一次具体提交。revert 则是最温和的撤销方式它不动历史只新增一条“反着做的提交”。比如某次提交删了一行代码revert 那次提交就是再加回那行代码。因为历史完整保留多人协作时用 revert 撤销远程提交是最安全的。5.3 submodule 与 worktree什么时候会用到submodule 解决的是“在一个仓库里引用另一个仓库”的问题。最简单的例子你做的一个公共工具库已经被多个项目共享直接在项目里 git submodule add 仓库地址 工具目录就能把这个库拉进来并且记录它对应的 commit 版本。克隆带有子模块的项目后需要执行 git submodule update --init --recursive 才能把子模块内容真正拉下来。这个功能对个人维护多个相关项目很有用但建议初期不要玩得太花等确实有公共代码需要跨项目复用再上。worktree 解决的是“同一仓库不同分支并行开发”的问题。默认情况下你只能在一个目录里检出一个分支想同时看 main 和 dev 两个分支的内容就得复制多个仓库。worktree 允许从同一个仓库扩展出多个工作目录每个目录检出不同分支互不干扰。用法是 git worktree add 目录名 分支名。它和 git branch 的区别在于branch 只是创建或移动指针目录里还是那一份代码worktree 则是一个真实额外的代码目录。个人开发如果经常需要同时对照两个分支的行为worktree 会非常舒服否则先知道有这个功能就够了。5.4 CRLF 换行符和 git bash 复制粘贴小技巧换行符的问题是 Windows 用户的专属烦恼。Windows 的文本文件用 CRLF 结尾Linux 和 macOS 用 LF 结尾如果混用Git 会在 diff 里把整个文件标成改动实际内容却一点没变。解决办法是统一 core.autocrlf 配置。Windows 上建议设置为 true它会在提交时把 CRLF 转为 LF检出时转回 CRLFmacOS/Linux 上建议设置为 input提交时转成 LF但不强制检出格式。git config --global core.autocrlf true # Windows git config --global core.autocrlf input # macOS / LinuxGit Bash 里复制粘贴也和普通终端不一样Windows 下 CtrlC 是中断命令不是复制。在 Git Bash 窗口里复制快捷键是 CtrlInsert粘贴是 ShiftInsert。如果你发现鼠标选中文本后无法复制可以在 Git Bash 的选项菜单里开启 Mouse - Copy on select这样选中即复制右键即粘贴。5.5 大文件提交失败、连接报错怎么办热词里“git 无法提交大文件”也很有代表性。远程仓库通常对单文件大小有限制GitHub 单个文件超过 50MB 会提醒超过 100MB 直接拒绝Gitee 也有类似阈值。更大文件想进 Git常规做法是用 Git LFS 扩展但个人新手其实应该先问自己一个问题这个文件真的需要被版本管理吗如果它是生成出来的日志、模型、安装包或者媒体素材那不该进仓库应该写进 .gitignore。如果已经误提交过大文件git rm --cached 只是不再跟踪历史里依然还占着体积真正清理要用 git filter-repo 这类工具改写历史操作前务必先备份仓库。连接方向的报错也很常见比如 clone 时出现 connection refused。看到这类错误先别急着反复重试。排查顺序一般是确认地址和端口写没写错确认目标仓库在平台上能正常访问最短路径测一下curl 仓库地址或 ping 对应域名检查防火墙或安全软件是否拦截了 Git 进程。有时候换一个网络环境就好了这通常意味着问题不在电脑本身而是在网络链路上。另外如果你是在 Windows 的 Git Bash 里执行命令突然遇到 open /dev/null or dup failed 这种报错多半是当前终端环境文件描述符出了问题最简单的方法是重开一个干净的 Git Bash 窗口再执行刚才的命令。6. 常见问题速查表与个人使用心得6.1 一张表解决 90% 的日常问题问题现象原因解决方案push 被拒绝 non-fast-forward本地落后于远程git pull --rebase 后再 pushcommit 注释写错了提交信息有误git commit --amend -m 新注释提交时发现漏了文件暂存区不完整git add 文件 后 git commit --amend --no-edit.gitignore 不生效文件已被 Git 追踪git rm --cached 文件再写 .gitignore合并出现冲突同一段内容在不同分支被修改手动处理标记后 git add git commit切换分支时未提交改动干扰工作区不干净git stash 保存切换后 git stash pop远程仓库每次要输密码没有配置免密配置 SSH 公钥并添加到平台公钥配置后认证失败公钥未复制完整或多 key 冲突重新生成并确保只配置一个有效 keyclone 连接失败地址错误/端口不通/网络链路异常检查地址、测网络、换环境再试CRLF 警告换行符两端不一致按系统配置 core.autocrlf大文件提交失败超出平台限制用 LFS 或从版本库中移除终端报 open /dev/null 错误Git Bash 环境异常重开终端窗口重试6.2 聊几点个人经验一段段排下来Git 的基本操作其实没有想象中那么多。真正常用的命令一只手数得过来status、add、commit、push、pull、switch、merge。复杂命令如 submodule、worktree 是锦上添花用不着的时候不需要知道。但我还是建议每个人在正式开始项目前花半天时间把命令行这一套走通因为图形界面虽然好上手一旦遇到冲突、强推、变基这些场景最后还是离不开命令行。我给新手的三个建议。第一提交的粒度尽量小而完整。一个功能点一次提交注释里写清楚做了什么而不是攒一大堆之后再写一句“fix bug”。这样做的好处是以后想用 git revert 精准撤掉某一个功能时你会发现历史清晰到让人感动。第二养成多看 git status 的习惯。Git 的大部分命令都不会直接报错它们只是把当前状态展示给你状态看得懂操作就基本不会错。第三对拿不准的命令先备份仓库。Git 命令本身没有“确认按钮”reset --hard、push --force 这类命令一旦执行恢复成本很高。我在执行有风险的操作之前一般先复制一份仓库目录或者 git branch 临时建个备份分支给自己留条退路。最后再分享一个小细节。我每次开新项目第一件事不是急着写代码而是先 git init 并做一次空的初始提交。别小看这个空提交它意味着从项目诞生的第一秒钟起所有后续操作都有了一个最初的参照点。调试到崩溃、改到面目全非、需要回到最开始重新出发时你会感谢那个一开始就养成的习惯。Git 学习曲线看似有点陡但翻过前面这几个基本操作之后后面几乎全是复利。