
最近好几个朋友来问我 Git 安装的事情每次我都是同一句话装 Git 本身很简单真正麻烦的是装完之后那一堆配置和使用习惯。很多人照着网上的教程装完git --version也出来了结果一上手就撞墙——SSH 认证失败、换行符把整个文件搞出上千行 diff、提交大文件被远端拒绝、明明写了.gitignore却还在跟踪一堆不该跟踪的文件。这些坑我几乎全部踩过一遍而且可以说大部分问题不是出在“用”的时候而是出在“装”和“配”的环节。这篇就按我自己实际操作的顺序走一遍先把 Git 解决什么问题讲清楚再分平台过安装细节然后是装完必做的四件事最后是日常高频命令和疑难杂症排查。不管你用的是 Windows、macOS 还是 Linux都能照着做。文章里的选项、命令、排查思路都是真实项目里验证过的不是从文档里抄出来的。1. 装 Git 之前先弄明白它到底解决什么问题1.1 没有版本控制的日子是什么样我说个真实场景。以前团队里有人用 SVN有人直接用文件夹备份项目目录里一堆final_v1、final_v2、最终版、真的最终版。到了上线前一天谁都不知道哪个文件是新的。更惨的是两个人同时改一个文件后保存的人把先保存的人的工作覆盖掉改了半天的工作说没就没。这不是个别现象。只要代码量超过一个“能记进脑子里”的量级靠人工管理版本一定会出错。Git 解决的就是这件事它给每一次改动拍一张快照哪天改崩了一条命令就能回到任意历史节点。团队里每个人各自改各自的最后合并冲突了也能看到双方改了什么而不是互相覆盖文件。另外一个容易被忽视的价值是追踪“为什么”。git log里每一行提交都带作者、时间和提交说明。我后来做项目复盘、排查线上 bug很多线索就是从提交历史里翻出来的。没有版本控制这些信息基本靠人脑记忆时间一长就没了。1.2 Git 的几个关键概念用大白话讲如果你第一次接触 Git别上来就背命令先把几个概念过一遍后面所有操作都围绕它们转。工作区你电脑上能看到的那些文件。暂存区一个临时存放改动的地方相当于“准备提交的清单”。git add就是把改动放进清单里。本地仓库你电脑上.git目录里保存的完整历史每次git commit就是往这个历史里写一个快照。远程仓库托管在 GitHub、Gitee 或公司服务器上的仓库副本用来多人协作和备份。git push是往远程传git pull是从远程拉。分支可以在同一条时间线上分出另一个平行的开发线互不影响最后再用git merge合回来。生活化理解就一句话分支是平行世界合并是把两个平行世界的结果整合成一个。Git 是分布式的意思是每个人本地的仓库都包含全部分支的全部历史不联网也能看提交记录、也能做提交。这一点和 SVN 那种必须连服务器的集中式版本控制完全不同。装完 Git 之后你实际上是在自己电脑上拥有了一整套完整的历史数据库。1.3 你的使用场景决定了安装选项安装 Git 之前先想清楚你接下来大概会在什么场景里用它。我一般把用户分成三类纯单机使用只是自己写代码、存版本不连远程仓库。这种情况安装向导里大部分选项默认就可以。配合 GitHub / Gitee 使用需要配置 SSH 密钥、远程仓库关联、凭据管理后面第 3 章的配置基本都要做。配合 IDE 使用很多人用 IntelliJ IDEA、VS Code 内置的 Git 功能。IDE 本质上是调用命令行的 Git所以安装时 PATH 环境变量必须选对否则 IDEA 里会报“Cant use Git”之类的问题。这篇文章按最常见的组合来讲Windows 或 macOS 本机 Git Bash 命令行 GitHub/Gitee 远程仓库 IDEA 图形界面辅助。安装的时候多花两分钟把选项选对后面能省下半天折腾时间。2. Windows / macOS / Linux 三平台安装实操2.1 Windows官网下载与安装选项逐个选明白Windows 安装 Git 我推荐只从官网下载不要从各种“软件园”下载站拿那些打包版本经常会捆绑垃圾软件或者改环境变量。打开 git-scm.com首页会自动识别你的系统直接点下载 64-bit Git for Windows Setup 就行。安装向导里真正需要动脑子的选项就那么几个我逐个说一遍。安装路径默认是C:\Program Files\Git一般不用改。如果你的电脑有权限限制或者就是不喜欢路径里带空格可以改成C:\Git但要注意改成短路径后后续 PATH 也要跟着变。Select Components选择组件这里建议把Git Bash Here和Git GUI Here都勾上。这两个选项会在右键菜单里加上入口在文件夹里右键就能直接打开 Git Bash 或者图形提交界面后面用起来非常顺手。.gitignore模板那个选项作用不大无所谓选不选。Default branch name默认分支名新版本安装向导会让你选默认分支名推荐改成本地默认分支名为main。当然如果你公司里所有仓库都用master那也可以保持一致这个纯看团队习惯不用纠结。Adjusting your PATH environmentPATH 环境变量这一步是新手踩坑最多的。三个选项分别是Use Git from Git Bash only只在 Git Bash 里能用 git 命令cmd 和 PowerShell 里用不了。不推荐因为后面用 IDEA 时可能找不到 Git。Git from the command line and also from 3rd-party software命令行和第三方软件都能用 git这是官方推荐也推荐选这个。Use Git and optional Unix tools from Command Prompt除了 git还把一堆 Unix 工具比如find、sort塞进 cmd有概率覆盖 Windows 自带同名命令不建议。换行符处理方式这个选项我单独用一个小节讲因为它影响面特别大。Windows 默认文本换行是 CRLF回车换行而 Linux/macOS 用的是 LF只有换行。如果不做转换同一个文件在不同平台上打开Git 会认为文件内容变了。安装向导里三个选项Checkout Windows-style, commit Unix-style line endings默认检出时转成 CRLF提交时转成 LF。适合在 Windows 上开发、团队跨平台的场景。Checkout as-is, commit as-is不转换。适合单平台项目但跨平台协作容易产生换行符差异。Checkout Unix-style, commit Unix-style检出和提交都用 LF。适合你明确知道服务器和队友全是 Linux 的场景。实测下来绝大多数情况用默认的第一个选项最稳。等你理解了换行符原理之后再根据团队实际改也行。我见过有人选了第二个选项结果同事在 macOS 上拉下来整个文件 diff 全是红色的其实就是换行符不一致导致的。剩下的终端模拟器选项默认选 MinTTY 就行它比 Windows 自带控制台好用。Credential Manager 保持勾选后面用 HTTPS 协议推送时它会帮你在系统里记住凭据实现免密。全部选项确认后安装完成在开始菜单里能找到 Git Bash、Git CMD、Git GUI 三项。想省事的读者也可以用 Windows 包管理器直接一行安装适合习惯命令行的场景winget install --id Git.Git -e --source winget装完同样建议按 2.4 节验证一下。2.2 macOS两条路选一条macOS 上装 Git 有两种主流方式我都试过。第一种是安装 Xcode Command Line Tools苹果官方提供的命令行工具包。在终端里执行xcode-select --install它会弹窗提示安装等一段时间就装好了里面自带 git。好处是和系统集成度高坏处是版本可能比较旧有些新特性用不了。如果你只是偶尔用一下 Git这条路足够。第二种是用 Homebrew 安装适合想长期用、想保持最新版的人brew install git装完可以用which git确认一下路径。比较老的 brew 环境会装在/usr/local/bin/gitApple Silicon 的 Mac 装在/opt/homebrew/bin/git。如果发现which git出来的是系统自带的路径检查一下 PATH 顺序保证 brew 的 bin 目录排在系统路径前面。有些公司电脑没有管理员权限brew install可能会失败这时候可以直接去官网下载 macOS 安装包git-scm.com/download/mac图形化安装完就能用不需要 sudo 权限。2.3 Linux包管理器一行命令搞定Linux 是 Git 的老家安装基本就是一条命令的事。Debian/Ubuntu 系sudo apt update sudo apt install git -yCentOS/RHEL 7 及以前用 yum8 及以后用 dnf# CentOS 7 sudo yum install git -y # CentOS 8 sudo dnf install git -y需要注意系统自带的包管理器版本可能偏老。比如 Ubuntu 20.04 仓库里的 Git 可能是 2.25 左右而最新版已经到 2.4x 了。对于绝大多数开发场景仓库自带版本完全够用。如果确实需要新版那就走编译安装但编译之前要装好依赖autoconf、curl-devel、expat-devel、gettext-devel、openssl-devel这些。实际体验下来为追新版本去编译安装性价比很低除非你有明确的功能需求。2.4 安装完先跑这三个命令确认不管哪个平台装完都建议依次执行三个命令确认安装没问题git --version这条命令出来类似git version 2.xx.x.windows.x说明核心安装没问题。# Windows 用 where gitmacOS/Linux 用 which git where git # 或者 which git这条确认 Git 的可执行文件在哪里也能看出 PATH 环境变量是否生效。如果提示找不到 git多半是 PATH 没配置好或者终端窗口没重开。git config --list这条列出当前生效的配置。这时大概率是空的因为还没设置过任何东西能看到几条默认值也正常。接下来就进入可用的第一步——配置。3. 安装后必做的四件事账号、密钥、换行符、默认分支3.1 配置用户名和邮箱commit 才有人认领很多人装完 Git 直接就开始提交结果遇到这个报错Author identity unknown *** Please tell me who you are. Run git config --global user.email youexample.com git config --global user.name Your NameGit 的每次提交都必须记录作者是谁不设置就只能一直卡壳。按照提示执行git config --global user.name 你的名字 git config --global user.email 你的邮箱这里有两件容易被忽略的小事。第一邮箱尽量用你注册 GitHub/Gitee 时用的邮箱这样提交记录能和你账号对上。GitHub 对提交邮箱还有隐私保护策略用 noreply 邮箱也可以看个人偏好。第二--global参数意味着这个配置对当前电脑上的所有仓库生效。配置优先级是仓库内的.git/config--global全局配置 系统级配置。如果你在某些特定仓库里需要用不同身份比如个人仓库和公司仓库分开可以不带--global在那个仓库目录里单独执行一遍。查看当前生效的完整配置git config --list修改的话直接重新执行设置命令覆盖想删除某一项把参数换成--unset就行。3.2 SSH 密钥配置实现免密推送的核心用 HTTPS 协议访问远程仓库当然可以但每次 push 都要输用户名和密码或令牌很烦。更优雅的方案是配置 SSH 密钥配置好后推送拉取完全免密。生成密钥的推荐算法是 Ed25519比传统的 RSA 短、快、安全。在 Git Bash 或终端里执行ssh-keygen -t ed25519 -C 你的邮箱一路回车就行。默认会生成在~/.ssh/id_ed25519和~/.ssh/id_ed25519.pub。查看公钥内容把整段复制出来。Windows 下可以这样clip ~/.ssh/id_ed25519.pubmacOS 下pbcopy ~/.ssh/id_ed25519.pub然后去平台添加GitHub右上角头像 → Settings → SSH and GPG keys → New SSH key。Gitee设置 → 安全设置 → SSH 公钥。把复制的内容粘贴进去标题随意。添加完之后测试连接ssh -T gitgithub.com看到类似Hi xxx! Youve successfully authenticated的提示就说明连接通了。Gitee 对应的测试命令是ssh -T gitgitee.com。如果你同时用 GitHub、Gitee 还有公司内网 GitLab同一个密钥放多个平台是可以的一个公钥可以添加在多个平台上。但如果你的公司内网服务器不支持 Ed25519 算法那就生成一个 RSA 密钥备用ssh-keygen -t rsa -b 4096 -C 你的邮箱还有一种情况是电脑上有多组密钥比如个人电脑和公司电脑、不同平台用不同密钥这时候需要写~/.ssh/config来做区分。我自己的配置大致长这样Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519_gitee写好之后对不同的 Host 会自动使用对应的密钥不用手动切换非常省事。实测中 80% 的“SSH 认证失败”问题都出在密钥没配置好或者多密钥指向错误上后面第 5 章会专门讲排查步骤。3.3 全局配置建议换行符和中文显示除了用户名和邮箱建议顺手做几项全局配置都是日常使用中真实踩过坑后的经验。换行符配置取决于你的平台# Windows 上推荐 git config --global core.autocrlf true # macOS/Linux 上推荐 git config --global core.autocrlf inputcore.autocrlf true的含义是检出代码时自动把 LF 转成 CRLF提交时自动把 CRLF 转回 LF。这样做的好处是你在 Windows 上编辑代码、其他队友在 macOS/Linux 上编辑代码仓库里存的始终是 LF不会出现“整文件被判定为改动”的尴尬。input的含义是提交时把 CRLF 转成 LF但检出时不主动转保持原本内容。再执行一条很实用的配置git config --global core.quotepath false这是让中文文件名和中文路径正常显示。Git 默认会把非 ASCII 字符转义成\xxx的八进制格式打开这条配置后git status里就能直接看到中文文件.md而不是一串转义字符。这个问题在 Windows 上尤其常见不做配置的话看到中文文件名全是乱码。还有两条建议顺手配掉git config --global init.defaultBranch main git config --global push.default simpleinit.defaultBranch main让新仓库默认分支名是main省得每次还要手动改分支名。push.default simple是 Git 2.0 之后的默认安全行为只推送当前分支到同名的远程分支避免误推所有分支。3.4 关联远程仓库把本地代码推到 GitHub / Gitee本地仓库和远程仓库关联的核心命令是git remote。先在 GitHub 或 Gitee 上新建一个空仓库不勾选 README、.gitignore 那些初始化文件免得历史不干净复制仓库的 SSH 地址然后执行git remote add origin gitgithub.com:你的用户名/仓库名.gitorigin只是远程仓库的默认名字约定俗成你也可以叫别的名字但建议保持默认。关联之后推送本地代码git branch -M main git push -u origin main第一条把当前分支重命名为main如果还没改的话第二条推送并建立远程分支的关联关系。加上-u之后以后在这个分支上直接git push、git pull就可以了不用每次写全远程名和分支名。查看关联情况git remote -v这里会出现两个地址一个 fetch 一个 push内容一样。如果你看到的是 HTTPS 地址说明之前用的是 HTTPS 协议。两种协议可以混用但日常体验差别明显。我也顺便说明一下热词里常见的“git 设置代码库 token”如果用 HTTPS 方式现代 Git 支持用 personal access token 代替密码第一次 push 时输入一次 token凭据管理器会记住之后也免密。但对比之下SSH 密钥配置一次长期有效体验更干净。我的建议是统一用 SSH。4. 日常高频操作从第一次提交到分支合并4.1 完整走一遍提交流程假设你现在有一个新项目目录里面有代码文件第一次想用 Git 管理起来。进入项目目录后执行git init这条命令会创建.git目录本地仓库就建立起来了。然后看一下当前状态git status这时会显示一堆未跟踪的文件。初次提交前先暂存再提交是 Git 最基本也最重要的使用习惯。执行git add README.md git add src/git add的作用是把改动放进暂存区。为什么不能直接提交工作区的所有文件因为暂存区允许你只提交一部分改动比如这个文件内容还没写完可以先把另一个文件单独提交这样历史记录更干净。我之前见过有人只用git add .一把梭结果把临时文件、密钥、构建产物全都提交进去了后面清理非常痛苦。确认暂存内容没问题后提交git commit -m init: 添加项目初始代码提交信息要写清楚这一点再怎么强调都不过分。我自己写提交信息的原则是别人看这条信息就能知道这次改动解决了什么问题。比如fix: 修复登录接口返回码错误就比update好一百倍。查看历史git log --oneline --graph带--graph可以看到分支图形提交历史像一棵树一样展开直观理解“分支”是怎么回事。日常开发中我推荐形成一个肌肉记忆改完代码先git status看看改了哪些文件再git diff确认具体改动内容没问题再git add和git commit。很多人直接提交等 push 之后才发现把调试用的日志代码也提交上去了还得再补一个 revert纯属多绕了一圈。4.2 分支、合并与冲突处理分支是 Git 最核心的能力之一。开一个新分支开始开发不影响主分支上的稳定代码。创建并切换分支git switch -c feature/login这条命令相当于git branch feature/login加git checkout feature/login两步。Git 2.23 之后推荐用git switch语义更清晰。切回主分支用git switch main在新分支上提交若干改动之后切回主分支把新分支合并进来git merge feature/login如果两个分支改的是同一文件的同一区域Git 会报冲突。冲突文件里会出现这样的标记 HEAD 这是主分支的版本 这是 feature/login 分支的版本 feature/login处理方式很朴素打开文件把这几个标记行删掉手动保留下你要的最终内容然后git add这个文件再git commit完成合并提交。关于git merge和git rebase的区别我多说两句。merge会生成一个合并节点保留两条分支原本的走向历史看起来像网状。rebase是把当前分支的提交“重放”到目标分支顶端历史变成一条直线很干净。但 rebase 会改写提交哈希适用于还没 push 的本地提交。对于已经推到远程的分支不要随意 rebase否则队友拉取时会碰到一串莫名其妙的冲突。平时用 IDEA 写代码的同学可以在 IDEA 里操作分支合并底部工具栏 VCS → Git → Branches选择要合并的分支点 Merge or Rebase。图形界面里能直观看到哪些文件冲突、哪些文件被谁改了。另外 IDEA 从远程拉取已有项目也很简单File → New → Project from Version Control粘贴仓库地址选好目录就能克隆下来。很多人问“IDEA 怎么合并分支”“IDEA 怎么拉取 Git 项目”其实就是这两条路径比命令行还要直白。有个常见报错值得单独提一下fatal: refusing to merge unrelated histories这个错误通常发生在一个新初始化的本地仓库和一个远程仓库历史不相关时。比如你本地已经提交了代码远程仓库也初始化了 README两边没有公共提交合并就会触发这个保护机制。确认你是故意要合并两个不相关仓库的话加参数git pull origin main --allow-unrelated-histories但使用前要想清楚这会把两边完全不相关的历史强行拼在一起容易产生不可预期的文件覆盖。4.3 修改历史amend、revert、cherry-pick 怎么用开发过程中经常会有“刚才提交写错了”的后悔药时刻。三种常用操作我说清楚。git commit --amend用于修改最近一次的提交。比如提交信息手误打错字或者漏掉了一个文件想补进去git commit --amend -m fix: 修复空指针异常改后如果你已经git add了额外的改动直接执行git commit --amend --no-edit会用暂存区内容替换上一次提交同时保留原来的提交信息。这里的红线是只对本地的、还没推送到远程的提交使用 amend。如果已经 push 了amend 之后历史就分叉了你再强推会搞乱队友的工作区。git revert用于安全地撤销某个已经推送的提交。它不是把历史删掉而是生成一个新的反向提交把你指定的那次改动抵消掉git revert 提交哈希这样做的最大好处是不改写历史所有协作者的仓库都不会因为这次回滚而出现冲突。撤销线上 bug 修复时我优先用 revert 而不是 hard reset。git cherry-pick用于把某一次提交单独挑到当前分支上来常用于“这个修复在 main 上已经做了但我现在的 release 分支也需要同样修复”的场景git cherry-pick 提交哈希这里要特别解释一下热词里问的“git pick 和 fetch 有什么区别”。cherry-pick是把某个明确的提交“复制”到当前分支它操作的是单次提交本地会生成一个全新的提交。fetch是把远程仓库的最新提交记录和对象下载到本地但完全不合并、不改变你的工作区。它们是完全不同层面的命令名字上容易混淆但使用场景没有重叠。区分的关键是问自己一句话我是想让某个改动出现在当前分支用 cherry-pick还是只想看看远程有没有更新用 fetch说到 fetch 就顺便把 pull 讲透。git pull git fetch git merge。如果你不想贸然把远程改动合并到本地可能先想看看远程改了什么就先git fetch然后git log origin/main查看差异确认没问题再手动git merge origin/main。我平时在团队协作时的习惯是先 fetch 再 merge而不是直接 pull好处是可以拦住很多没做完的半成品提交。4.4 .gitignore 过滤文件形同虚设问题出在这热词里有一条叫“git 的过滤文件 没有作用”这个坑我当年入坑时也踩过现象是明明在.gitignore里写了node_modules/执行git status之后node_modules还是出现在未跟踪列表里。原因其实一句话就能讲明白.gitignore只对未被跟踪的文件生效已经被 Git 跟踪的文件不受它控制。如果你之前已经把node_modules或者某个配置文件提交进了仓库之后再在.gitignore里写它的规则Git 会无视这条规则因为文件“已经在库里了”。正确的处理方式是先把已跟踪的文件移出跟踪列表再提交一次变更git rm -r --cached node_modules--cached参数的意思是只从 Git 索引里移除不影响磁盘上的文件。执行完再git status你会发现 node_modules 变成了未跟踪状态这时候.gitignore的规则就生效了。最后提交一次改动把这次变更固化为历史。.gitignore的写法也有几个容易混淆的点。比如# 忽略根目录下的 build 目录 /build # 忽略任意层级的 build 目录 build/ # 忽略所有 .log 文件 *.log # 但保留重要日志 !important.log规则里/开头的路径锚定仓库根目录不带/的会匹配任意层级。!表示排除。这里还要提一个红线级别的建议不要把密钥文件提交到仓库里再用 .gitignore 去忽略。很多人会把.env、config.yml这种带数据库密码的文件先git add了再补写进 .gitignore。问题是只要这条记录进了历史.gitignore只能保证未来不再跟踪之前的提交里永远留着这个文件的快照任何人 clone 后都能用git log翻出来。安全做法是一开始就不 add或者用后面第 5 章说的 filter-repo 把历史里的敏感文件彻底抹掉。5. 常见问题与疑难杂症排查实录这部分内容是我在帮助同事和网友排查 Git 问题时遇到的真实案例整理成速查形式按优先级从高到低排列。5.1 SSH 认证失败排查步骤报错长这样gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository.按照这个顺序逐项排查效率最高。先确认公钥是否真的添加到了平台上。执行cat ~/.ssh/id_ed25519.pub复制输出的内容到 GitHub/Gitee 的 SSH 公钥设置页面检查是否一致。很多时候是添加时漏掉了一个字符或者把没复制全的公钥贴上去了。再看密钥是否被 ssh-agent 加载。Windows 的 Git Bash 里经常出现这个情况密钥文件存在但 ssh-agent 没有加载它。执行ssh-add -l如果输出The agent has no identities就先启动 agent 并加载密钥eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519加载成功后再测试ssh -T gitgithub.com如果还是不行用调试模式跑一遍看详细日志ssh -vT gitgithub.com日志里会打出走了哪个私钥文件是否能从服务端得到响应。重点看有没有出现Offering public key并且后面跟的是不是gitgithub.com对应的密钥。如果是基本能定位到密钥路径或者配置问题。我有一次排查了很久最后发现是~/.ssh/config里给 GitHub 指定了错误的IdentityFile导致系统一直拿公司内网的密钥去认证 GitHub把配置改对之后立刻就通了。还有一个 Windows 下常见的隐藏坑如果 Git 是用管理员权限安装的系统生成的密钥文件权限可能被 Windows 锁定导致 SSH 无法读取。处理方式是打开文件属性确保当前用户有完全控制权或者直接重新生成一份密钥放到用户目录下的~/.ssh。5.2 大文件提交失败的解决方案推送时遇到这种报错很经典remote: error: File xxx.zip is 150.00 MB; this exceeds GitHubs file size limit of 100.00 MB先说清一个前提Git 工具本身没有硬性的大文件限制限制来自托管平台。GitHub 单文件上限 100MBGitee 同样在 100MB 量级。但更值得说的是把大文件放进 Git 仓库本身就是一件不划算的事Git 每次提交都会保存文件快照一个大文件的多个版本会把仓库撑到几个 GB克隆一次慢到怀疑人生。解决方案分情况。如果大文件不需要版本管理比如构建产物、安装包、数据库导出备份正确做法是不入库。通过.gitignore规则排除掉需要分发时放到对象存储或者共享网盘。如果大文件确实需要纳入版本管理用 Git LFSLarge File Storage。大致流程是# 安装 Git LFS如果之前没用过 git lfs install # 跟踪指定类型的大文件以 psd 素材为例 git lfs track *.psd # 把 .gitattributes 提交到仓库 git add .gitattributes git commit -m chore: 使用 Git LFS 管理大文件 # 之后正常 add/commit/push git add design.psd git commit -m feat: 添加设计稿 git pushLFS 的原理是把大文件本体存到远端 LFS 服务器仓库里只保存一个指针文件。克隆时按需下载大文件内容从而保持主仓库体积可控。团队使用 LFS 时要确保每个人都执行git lfs install否则 checkout 时只拿到指针文件解不开实际内容。如果大文件已经在历史里了问题就比较麻烦。删除当前文件再提交历史里还是有这个文件仓库体积并不会变小。处理手段是重写历史比如git filter-repo。这里要强调重写历史会把所有涉及提交的哈希全部改变必须和团队所有人确认好没人有其他本地分支再操作否则会互相污染。实际操作中我宁愿重新建立一个干净仓库重新推开发代码也不轻易对多人协作的仓库执行历史重写。保险的办法是从源头堵住在团队仓库里加一个 pre-commit hook提交时检查暂存文件是否超过约定大小比如 50MB超了就拒绝提交。这个规则对防止“手滑提交大文件”非常有效。5.3 .git 目录泄露的排查与防护“git 目录泄露”是搜索引擎里出现频率很高的词我说说从开发者角度应该怎么理解和应对。背景是如果把项目目录直接放在 Web 服务器的静态文件根目录下访问者可以通过/.git/config、/.git/HEAD等方式访问到 .git 目录里的内容进而把整个代码仓库从服务器上拉下来。自查方式是直接访问自己的站点域名看这两个路径是否有响应https://你的域名/.git/HEAD https://你的域名/.git/config如果返回 200 并且能看到ref: refs/heads/main或一堆配置项说明你的开发库被公开了。防护手段分三个层面。第一Web 服务器层面禁止访问.git目录。以 Nginx 为例在站点配置里加这段规则location ~ /\.git { deny all; return 403; }Apache 可以在.htaccess里加类似规则。第二部署路径层面不要把仓库根目录直接当成 Web 根目录部署时只发布构建产物到静态目录。第三代码层面确保仓库里没有硬编码的密钥检查git log历史中有没有出现过密码和 token。如果已经泄露了第一时间是轮换所有可能被翻出来的密钥、密码、Access Token然后处理敏感历史。推荐用git filter-repo把包含敏感信息的文件从整个历史里清除掉重新推送。需要特别说明即使删除了 .git 目录的访问权限只要历史里还保留着密钥文件这个泄露风险就依然存在所以“清历史”比“封目录”更重要。顺带说一句网上确实有人用“git 目录泄露”这个漏洞去下载别人的源码但作为开发者把重点放在“怎么防”“怎么查”上才是正路。5.4 其他高频报错速查表这几个报错是日常开发中出现频率最高的我整理成表格仅供参考应对思路也都是实测好用的。报错信息常见原因处理方式Please tell me who you are未配置 user.name / user.email执行第 3.1 节的配置命令git open /dev/null or dup failed: No such file or directory常见于 Windows 下 Git 环境异常、磁盘空间不足或终端会话异常先重启 Git Bash清理临时目录确认磁盘剩余空间足够仍不行就以管理员权限重装 Gitfatal: refusing to merge unrelated histories两个仓库没有共享历史确认意图后加--allow-unrelated-historiesLF will be replaced by CRLF换行符配置不一致按第 3.3 节设置core.autocrlffatal: Not a git repository在非仓库目录执行了 Git 命令先用git status确认当前目录是否在仓库内远程 push 时提示认证失败密钥未配置或凭据过期按第 5.1 节排查 SSHHTTPS 场景检查 tokenerror: src refspec main does not match any本地还没有名为 main 的分支或分支名不一致先git branch -M main再 push还有一个高频词“git submodule”也简单说明。git submodule用于在一个仓库里引用另一个仓库的某个固定提交版本。适用场景是你的项目依赖了另一个 Git 仓库的特定版本希望把这个仓库作为一个子目录托管进来。相关命令是git submodule add gitgithub.com:xxx/lib.git lib git submodule update --init --recursive子模块用起来比普通目录麻烦属于“不到必要不引入”的机制大多数项目用包管理器解决依赖就够了不需要上 submodule。6. 常用命令速查表与给新手的几点建议6.1 高频命令速查表把几个核心操作整理成速查表方便对着敲。操作命令说明初始化仓库git init在当前目录建立 Git 仓库查看状态git status显示工作区和暂存区的变更情况暂存文件git add 文件名把文件改动加入暂存区提交git commit -m 提交说明把暂存区内容固化为一次提交查看历史git log --oneline --graph查看提交历史带图形化分支展示查看改动git diff查看尚未暂存的详细差异创建并切换分支git switch -c 分支名一步完成创建新分支和切换切换分支git switch 分支名切换到已有分支合并分支git merge 分支名把指定分支合并到当前分支关联远程git remote add origin 地址关联远程仓库推送到远程git push -u origin main首次推送并建立关联之后直接git push拉取更新git pull从远程拉取并合并暂存未完成的工作git stash临时保存当前修改恢复用git stash pop撤销工作区改动git restore 文件名把文件恢复到最近一次提交状态取消已暂存的文件git reset HEAD 文件名从暂存区移除不改动工作区内容6.2 三条实战建议结合我这几年的使用经验给刚入门的读者三条建议不算什么高深的原理都是教训换来的。第一条提交信息认真写。团队协作里一个清晰规范的提交说明比代码注释还重要。回滚、查 bug、做版本发布全靠提交信息定位范围。我自己习惯的格式是“类型 简述”feat: 添加用户注册接口、fix: 修复支付回调重复通知、chore: 升级依赖版本。坚持一段时间你会发现回滚和排查效率明显提升。第二条每个提交只做一件事。别把“改了样式、修了 bug、优化了接口”混在一个提交里。一旦线上出问题要回滚混在一起的提交就非常难取舍——回滚了有 bug 的提交样式改动也一起没了。拆开提交虽然麻烦一点但后端可维护性的收益远大于那几秒钟的省事。第三条从第一天就用.gitignore。初始化仓库的时候就写好忽略规则把node_modules/、target/、*.log、.env这些提前排除掉。如果等到仓库跑了一阵子再来补就会出现第 4.4 节说的“已跟踪文件不受 ignore 控制”的尴尬还要额外做一次解除跟踪的提交。第一天安装 Git 时顺手把模板配上后面一直受益。最后再说一点个人体会。Git 安装真的只是半小时的事真正决定你使用体验的是装完之后的配置和长期养成的工作习惯。我见过太多人安装了半年还在用 HTTPS 地址配密码提交信息随手写“aaa”每次合并远程代码都靠猜冲突怎么处理。这些问题都不是大问题但会持续地、缓慢地消耗你的时间。把这篇文章里的配置一次做完、命令多敲几遍后面开发就能把 Git 当背景板用不用再为工具本身分神。