
Git 和 GitHub 这一对组合几乎是每个写代码的人绕不开的第一道坎。我带过不少新人发现真正的分水岭不是搞懂分支模型也不是分清 merge 和 rebase而是第一次把本地文件稳稳当当地推到 GitHub 上。这个过程里会冒出一堆看着吓人的报错——Permission denied、failed to push some refs、RPC failed; curl 56、refusing to merge unrelated histories、GH001 Large files detected……每一条都够刚上手的人卡上半天最后干脆把仓库删了重来。这篇就把我在实际项目里踩过的 GitHub 上传文件常见错误做一次完整梳理。每一条都会讲清楚三件事它为什么会出现、怎么快速判断是哪一类问题、以及具体的修复命令和后续规避方式。内容以实操为主命令都能直接复制执行适合刚配好环境的新手对照排查也适合老手在某个报错面前临时翻出来看一眼。文中涉及的所有方案都基于公开、通用的 Git 与 GitHub 官方能力不依赖任何第三方工具。1. 上传失败到底卡在哪一层1.1 一次 push 背后究竟发生了什么很多人排查问题的效率低根源在于把 push 当成一个整体动作报错一来就整段整段地搜。实际上git push被拆成了好几个独立阶段每个阶段失败的表现完全不同。先在脑子里建一条链路你在工作区改文件 →git add把改动写进暂存区 →git commit在本地对象库里生成一个 commit 对象 →git push把这个对象以及它引用的所有 tree、blob 打包通过 remote 里记录的地址发给远端 → 远端做认证 → 远端检查你这个包能不能干净地接在当前分支末尾 → 接收并更新 ref。这条链路上任何一环断了都会报错而且报错关键词是高度模式化的。比如不是内部或外部命令必然是第一环之前的环境问题Permission denied必然在认证环节rejected / non-fast-forward必然在远端校验环节curl 56 / early EOF / Timed out必然在数据传输环节。你只要能一眼把报错归到某一环排查范围立刻从整个 Git缩到一个小环节。还有个容易被忽略的点git push默认推的是当前分支到同名远端分支等价于git push origin 当前分支:同名远端分支。当本地分支叫master而远端默认分支是main时你会看到src refspec main does not match any这种让人发懵的提示——它不是网络问题也不是权限问题纯粹是名字对不上。1.2 把报错按四层归类我习惯把所有上传相关的报错分成四层遇到问题先归类再动手比盲目搜错误码快得多。层级典型报错关键词本质原因排查入口本地环境层command not found、不是内部或外部命令、Please tell me who you areGit 没装、PATH 没配、身份没设git --version、git config --list认证授权层Permission denied、Authentication failed、403、Support for password authentication was removed密钥没配、凭据过期、账号无权限ssh -T测试、检查令牌与协作权限仓库状态层rejected、non-fast-forward、unrelated histories、GH001本地与远端历史分叉、历史里混入大文件git status、git log --oneline网络传输层Timed out、RPC failed、curl 56、early EOF、Connection reset链路不稳、包过大、协议协商失败GIT_CURL_VERBOSE1看握手过程这张表建议存下来。我做了这么多年绝大多数传不上去都能塞进这四格里剩下极少数是 GitHub 侧的服务波动等十几分钟重试就好。提示排查顺序永远是先本地、再认证、再状态、最后网络。反过来查你会在网络参数上折腾一晚上结果发现只是忘了git add。2. 本地环境没配好就动手的报错2.1 git 命令根本找不到最典型的一句是 Windows 命令行里的git 不是内部或外部命令也不是可运行的程序macOS 或 Linux 上则是command not found: git。这跟 GitHub、跟网络一点关系都没有纯粹是 Git 没装或者装了但没进 PATH。Windows 用户装 Git for Windows 时安装向导里有一个选择 PATH 环境的界面。默认选项是Git from the command line and also from 3rd-party software这个选项会把 Git 加进系统 PATH推荐选它。如果你图快一路下一步选到了Use Git from Git Bash only那 cmd 和 PowerShell 里就永远找不到 git只能用 Git Bash。这不是 bug是安装选项决定的。已经装错了也不用重装。找到 Git 的安装目录通常在C:\Program Files\Git\cmd把它加进系统环境变量 Path 里重开一个终端窗口即可生效。注意一定要重开终端改环境变量对已经打开的窗口无效这一点我第一次配的时候也懵了几分钟。验证方式很简单敲git --version正常会打印形如git version 2.43.0.windows.1的版本号。顺手再看一眼git --exec-path输出的路径能对上你的安装目录就说明 PATH 配对了。macOS 上还有个坑系统自带的/usr/bin/git是个壳第一次执行会弹窗提示你安装命令行开发者工具。如果你不想装那一大坨用包管理器单独装一份更清爽装完确认which git指向的是你自己装的那份而不是系统壳。2.2 提交时报 Please tell me who you are报错长这样*** Please tell me who you are. Run git config --global user.email youexample.com git config --global user.name Your Name to set your accounts default identity.这个报错发生在git commit阶段不是 push 阶段。Git 要给每个 commit 打上作者信息你没告诉它你是谁它就拒绝提交。解决就两条命令git config --global user.name Zhang San git config --global user.email zhangsanexample.com这里有个实操细节值得说邮箱要填你 GitHub 账号绑定的邮箱或者 GitHub 提供的那串xxxusers.noreply.github.com匿名邮箱否则 commit 不会和你的账号头像、贡献图关联上你在个人主页上看着一片空白会以为提交没成功其实是邮箱对不上。另外--global是写进用户级配置对这台机器上所有仓库生效。如果公司项目和个人项目要用不同的身份那就去掉--global在具体仓库目录里执行一次写进这个仓库的.git/config优先级高于全局配置。查看当前生效的身份用git config user.name和git config user.email不带--global查的就是最终生效值。注意不要把仓库级的.git/config提交上去它本来也不在版本控制范围内。但如果你手滑把邮箱写成了工作邮箱又推到了公开仓库历史里的邮箱是会被别人看到的改写历史很麻烦第一次配的时候多看一眼。2.3 分支名不一致导致的 src refspec 报错error: src refspec main does not match any是我见过最多的假报错之一。它跟网络、权限都无关只有两种可能本地压根没有这个分支或者你一次 commit 都没做过。判断方法很直接git branch # 看本地到底有哪些分支 git log --oneline # 看有没有提交记录如果git log直接报 does not have any commits yet说明你只git init了但没提交过。Git 里分支本质上是指向某个 commit 的指针没有 commit 就没有分支自然也推不出去。老老实实走一遍git add . git commit -m init: 项目初始化如果是有提交但分支名不对比如本地叫master、远端默认是main那就显式指定映射关系git push -u origin master:main或者更干脆把本地分支改名再推git branch -M main git push -u origin main-M是强制重命名哪怕目标名已存在-u是建立本地分支与远端分支的追踪关系配好之后以后直接敲git push就行不用每次写全origin main。2.4 换行符与中文文件名带来的隐形坑这两类问题不会让你 push 失败但会让你推送后发现问题同样值得单独提。换行符问题表现为warning: LF will be replaced by CRLF in xxx。Windows 用 CRLFmacOS 和 Linux 用 LFGit 默认会在签出时自动转换于是团队协作时经常出现我只改了一行diff 却显示整个文件都变了的诡异现象。稳妥的做法是统一配置# Windows git config --global core.autocrlf true # macOS / Linux git config --global core.autocrlf input更规范的做法是在仓库根目录放一个.gitattributes把文本文件类型显式声明出来让所有协作者行为一致* textauto *.sh text eollf *.bat text eolcrlf中文文件名的问题通常出现在跨平台场景。Windows 的文件系统编码和 Git 的默认配置不一致时中文名会显示成八进制转义比如\346\226\207\346\241\243.txt。执行一次下面的命令就能让 Git 原样显示中文git config --global core.quotepath false这行配置本身不影响文件内容纯粹是显示层面的但排错时能省下大量猜测时间。3. 认证授权层的报错与修复3.1 密码认证已经被彻底移除如果你在 push 时被要求输入用户名和密码输完账号密码后收到Support for password authentication was removed on August 13, 2021这不是你密码错了而是 GitHub 早就不再接受账号密码做 Git 操作的认证了。现在有两条正路。第一条是 HTTPS 个人访问令牌PAT。在 GitHub 的 Settings → Developer settings → Personal access tokens 里创建一个令牌勾选repo相关权限用这个令牌当作密码填进去。令牌只显示一次关掉页面就再也看不到一定要当场复制存好。第二条是改用 SSH 密钥也是我更推荐的方式因为配好之后基本一劳永逸不用惦记令牌过期。3.2 SSH 密钥从生成到验证的完整流程先把现有密钥检查一遍避免覆盖掉你可能正在用的那份ls -al ~/.ssh看到id_ed25519和id_ed25519.pub这两个文件说明已经有一对了。如果没有生成一对新的ssh-keygen -t ed25519 -C your_emailexample.com一路回车即可。中间会问你要不要设 passphrase设了更安全但每次操作都要输一遍配合 ssh-agent 可以只输一次。密钥类型优先选ed25519比 RSA 更短更安全如果因为某些老系统兼容性必须用 RSA长度至少 4096 位。生成之后把公钥内容复制出来# macOS pbcopy ~/.ssh/id_ed25519.pub # Windows PowerShell Get-Content ~/.ssh/id_ed25519.pub | Set-Clipboard # Linux cat ~/.ssh/id_ed25519.pub然后到 GitHub 的 Settings → SSH and GPG keys → New SSH key把内容粘进去。注意粘贴的是.pub结尾的公钥绝对不能是私钥私钥泄露等于把钥匙交给了别人。最后做验证ssh -T gitgithub.com第一次连接会问你是否信任主机指纹输入yes。成功的话会看到Hi 你的用户名! Youve successfully authenticated, but GitHub does not provide shell access.看到这句话就说明认证通了后半句只是说明 GitHub 不给你 shell不是错误。如果这一步失败加上-v参数看详细日志ssh -vT gitgithub.com日志里会明确告诉你是找不到密钥文件、还是被拒绝、还是卡在连接阶段比猜快得多。3.3 Permission denied 的几种面孔同样是Permission denied背后原因可以差很远我把常见的几种列出来对照。第一种是Permission denied (publickey)出现在ssh -T或 push 时。九成是公钥没加到账号里或者本地密钥文件名不是默认名导致 SSH 没自动加载。用ssh-add ~/.ssh/你的私钥手动加载一下或者写一个~/.ssh/configHost github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes第二种是remote: Permission to userA/repo.git denied to userB注意报错里出现了两个不同的用户名。这是典型的凭据串号你机器上缓存的凭据是 userB 的但你想推的是 userA 的仓库。Windows 用户到凭据管理器里删掉 GitHub 相关条目macOS 用户在钥匙串访问里搜 github 删掉然后重新 push 触发一次认证输入。第三种是 403 或remote: Permission denied但公钥明明配好了。这时候要看的是仓库的协作权限你只是一个只读协作者或者推的是别人名下的仓库而你没有写权限。让仓库所有者到 Settings → Collaborators 里把你加进去或者你 fork 一份推到自己的仓库去。实操心得多账号场景比如一个工作号一个个人号最容易出这种问题。我的做法是给每个账号配一个 Host 别名工作用github-work个人用github.com克隆时显式写别名这样凭据永远不会串。4. 仓库状态冲突类的报错4.1 remote origin already exists这个报错出现在执行git remote add origin xxx时意思是已经有一个叫 origin 的远端了。属于纯粹的配置冲突。先看一眼现有的git remote -v会打印两行fetch 和 push 各一行。如果你只是想换地址不要 add用 set-urlgit remote set-url origin gitgithub.com:user/repo.git如果你确实想推到一个全新的远端换个名字就行git remote add backup gitgithub.com:user/repo2.git想彻底删掉重建也可以git remote remove origin git remote add origin gitgithub.com:user/repo.git一个仓库挂多个远端是很实用的做法后面讲网络问题时还会用到。4.2 rejected 与 non-fast-forward 的真相报错长这样! [rejected] main - main (fetch first) error: failed to push some refs to gitgithub.com:user/repo.git hint: Updates were rejected because the remote contains work that you do hint: not have locally.关键在于remote contains work that you do not have locally——远端有你本地没有的提交Git 拒绝用你的版本覆盖它因为那会丢掉别人的工作。这种情况通常发生在两种场景一是在 GitHub 网页上点了Add README或者Add .gitignore创建了初始提交然后本地又git init出一套独立历史二是多人协作别人先推了一次。标准解法是先拉再推git pull --rebase origin main git push origin main用--rebase而不是默认的 merge是为了让你的提交线性接在远端的更新之后历史更干净。如果 pull 过程中出现冲突Git 会停下来让你处理冲突文件的对应位置会有、、标记手工编辑保留想要的内容然后git add 冲突文件 git rebase --continuerebase 过程中想放弃git rebase --abort能回到操作前的状态这一点比 merge 友好我经常靠它兜底。如果确认远端那些提交确实不需要比如就是个自动生成的 README强制推送也能解决git push --force-with-lease origin main注意这里我用的是--force-with-lease而不是--force。前者会在远端分支被别人更新过时拒绝推送防止你覆盖掉别人的提交后者是无条件覆盖协作用它早晚出事。4.3 refusing to merge unrelated histories这个报错往往出现在git pull时fatal: refusing to merge unrelated histories意思是两边的提交历史完全没有共同祖先Git 认为你可能是拉错了仓库出于保护拒绝合并。本地git init了一套历史远端又有一套网页端生成的历史就是这个局面。如果确认两边就是同一个项目强行允许合并git pull origin main --allow-unrelated-histories执行后大概率要处理冲突处理完提交即可。之后正常 push。我个人的建议是新建仓库时如果打算用本地已有代码就在 GitHub 上新建一个完全空白的仓库别勾选 README、License、.gitignore 这些初始化选项本地推上去之后啥事没有。这个习惯能规避掉上面这一整类问题。4.4 大文件超限GH001 与 100MB 红线GitHub 对单文件的硬限制是 100MB超过直接拒绝超过 50MB 会给出警告。推送整个包也有体积上限。报错通常长这样remote: error: GH001: Large files detected. You may want to try Git Large File Storage. remote: error: Trace: xxxxx remote: error: See https://git-lfs.github.com for more information. remote: error: File model.pth is 210.00 MB; this exceeds GitHubs file size limit of 100.00 MB最容易踩坑的是git rm的误解。很多人的第一反应是删掉文件再推git rm --cached model.pth文件确实从后续提交里消失了但它仍然躺在历史里push 的时候照样会被拒。因为推送传的是整个对象图只要历史中引用了这个大 blob它就得被传上去。真正要做的有两件事。第一件是阻止它继续被跟踪把规则写进.gitignore*.pth *.zip *.psd dataset/第二件是从历史里彻底清除。官方的git filter-repo效率最高先安装pip install git-filter-repo然后在仓库根目录执行git filter-repo --strip-blobs-bigger-than 100M它会重写整个历史把所有超过 100MB 的 blob 从所有提交里剔除。执行完检查git log --stat确认无误再强制推送git push --force-with-lease origin main注意改写历史对协作者来说是破坏性的。他们的本地分支会和远端彻底分叉需要重新克隆或者硬重置。所以这个操作要么在项目早期做要么提前通知所有人别闷头就推。如果大文件是必须版本化的模型权重、设计稿、素材包那正确姿势是 Git LFSgit lfs install git lfs track *.psd git add .gitattributes git add design.psd git commit -m chore: 接入 LFS 管理设计稿LFS 会提交一个指针文件而不是文件本体本体存放在单独的存储里。要留意的是免费账户的 LFS 存储和流量都有额度超了会限制下载。团队里上传大素材前最好先确认额度够不够不然某天下拉代码失败排查半天才发现是流量用完了。5. 网络传输层的报错5.1 Failed to connect to github.com port 443完整报错通常是fatal: unable to access https://github.com/user/repo.git/: Failed to connect to github.com port 443 after 21000 ms: Timed out这个报错只说明一件事你的机器没能和 github.com 的 443 端口建立 TCP 连接。它和 Git 无关和账号无关纯粹是网络链路问题。排查顺序建议这样走。先用ping github.com看能不能解析出 IP如果连域名都解析不了说明是 DNS 层面的问题换个网络环境或者在系统网络设置里换一组公共 DNS 试试看。如果能解析但连不上那大概率是当前网络出口对这个目标的访问受限这类情况在部分办公网络、校园网络里很常见。处理方式我觉得没必要跟网络较劲务实一点一是换个网络环境试试家庭宽带和手机热点往往表现不同二是问一下公司运维确认是不是出口策略限制三是更根本的方案把代码同时托管到团队能稳定访问的平台用双远端的方式做同步。第 5.4 节会展开讲这个布局。另外提醒一句报错里那个21000 ms是超时阈值能看出你等了 21 秒才失败说明不是秒拒而是连接被丢弃这两种表现对应的原因不同观察这个细节有助于判断。5.2 RPC failed 与 curl 56 / early EOF这组报错经常一起出现error: RPC failed; curl 56 OpenSSL SSL_read: Connection was reset, errno 10054 fatal: the remote end hung up unexpectedly fatal: early EOF fatal: index-pack failed它的含义是连接建立了、数据传输启动了但中途断了。curl 56是接收数据时连接被重置early EOF是数据流提前结束index-pack failed是收到的包不完整无法解压成对象。三个最常见原因。第一是单次推送体积太大几百兆的包在弱网下几乎必然失败第二是链路本身抖动严重传一半掉线第三是 HTTP/2 协商在某些网络设备上不兼容握手看着正常传数据就崩。针对第一种把大提交拆成多次小提交分批推。一次推 20MB 比一次推 500MB 成功率高一截虽然麻烦但确实有效。针对第三种切换到 HTTP/1.1git config --global http.version HTTP/1.1改完之后重试一次。如果问题消失就说明是协议协商的问题这条配置长期留着也没副作用。这个坑我印象特别深当时对着几 G 的仓库折腾了一下午改完这一行当场就通了。还有个辅助手段是打开详细日志看握手过程GIT_CURL_VERBOSE1 git push origin main它会打印每一个 HTTP 请求和响应头卡在哪一步一目了然比对着失败了三个字瞎猜强太多。5.3 降低单次传输压力的几个参数网上流传最广的参数是http.postBuffergit config --global http.postBuffer 524288000这个参数把缓冲区调到 500MB。它在早期 Git 版本里确实有用因为当时大包走的是单一 HTTP 请求缓冲区不够就断。但现代 Git 用的是 smart HTTP 分块传输包会被切成多块发这个参数的作用已经非常有限了。我的实测体会是它对几百 MB 的单次推送偶尔有点效果但别指望靠它解决所有超时问题更不要无脑调到 GB 级别那只会让内存占用变高。真正值得调的是低速超时相关参数git config --global http.lowSpeedLimit 1000 git config --global http.lowSpeedTime 60含义是如果传输速度连续 60 秒低于 1000 字节/秒就判定为卡死并中断。默认值是 1000 字节/秒持续 300 秒在弱网下会挂很久。把时间调短能让失败来得更快你也能更快重试而不是盯着进度条干等。当然如果你网络确实很慢调太激进会导致本来能传完的包被误杀这个值要按自己网络情况找平衡。还有两个和体积相关的配置git config --global core.compression 0 git config --global pack.windowMemory 256m第一个关闭压缩牺牲带宽换 CPU 和内存在低配机器上传大仓库时有用第二个限制打包时使用的内存窗口避免在内存吃紧的环境里打包阶段就崩掉。另外如果仓库历史已经非常臃肿推送前先做一次本地整理git gc --aggressive --prunenow它会把松散对象重新打包压缩体积可能明显下降。这属于治本的手段比调参数更值得做。5.4 网络长期不稳定时的仓库布局如果 GitHub 在你的日常环境里本来就时通时不通那与其每次推送都提心吊胆不如调整一下仓库布局从架构上绕开这个问题。我的做法是配置双远端。主远端指向团队能稳定访问的托管服务备用远端指向 GitHubgit remote add origin 主仓库地址 git remote add github gitgithub.com:user/repo.git日常推送到 origingit push origin main需要同步到 GitHub 时再补一条git push github main这样做的好处是所有代码提交和协作都走稳定链路GitHub 只是镜像备份偶尔通一次就同步一次。你还可以用一条命令同时推两个远端但我不建议默认这么做因为它会把推送时间拉长一倍其中任一失败都会让命令返回非零状态反而干扰判断。手动分开推成功和失败都清清楚楚。对于刚接手仓库的人还有一种降低传输压力的技巧浅克隆。只拉最近一次提交体积能小一个数量级git clone --depth 1 仓库地址需要完整历史的时候再补全git fetch --unshallow这个技巧在大仓库、弱网的组合下特别管用第一次 clone 就超时的时候尤其值得一试。6. 排查顺序与速查表6.1 一套固定下来的排查七步踩的坑多了之后我给自己定了一套固定流程遇到任何上传失败都按这个顺序走基本不会跑偏。第一步git status看工作区和暂存区状态确认该加的都加了、该提交的都提交了。第二步git log --oneline -5确认本地确实有提交而且当前分支名符合预期。第三步git remote -v确认远端地址写对了用的是 SSH 还是 HTTPS 也一清二楚。第四步git config user.name和git config user.email确认身份没问题。第五步如果是 SSH 地址ssh -T gitgithub.com单独验证一次认证如果是 HTTPS确认令牌没过期。第六步git pull --rebase origin 分支主动同步一次远端把 non-fast-forward 的可能性提前消掉。第七步以上都没问题再带着GIT_CURL_VERBOSE1重试 push看网络层面的具体表现。这套流程的价值在于它把排查变成了逐项确认你每次只需要判断一项是或否而不是面对一团乱麻。我见过太多人一上来就改网络参数最后发现是根本没提交时间全浪费了。6.2 报错速查表把这几年遇到的高频报错整理成一张表方便直接对号入座。报错信息片段所属层级直接原因处理动作git 不是内部或外部命令本地环境Git 未装或未进 PATH检查安装选项追加 PATH重开终端Please tell me who you are本地环境未配置身份git config --global user.name/user.emailsrc refspec main does not match any本地环境无提交或分支名不符先 commit或git branch -M mainSupport for password authentication was removed认证授权用了账号密码换 PAT 或改用 SSHPermission denied (publickey)认证授权公钥未加载ssh-add或配~/.ssh/configPermission to A/repo denied to B认证授权凭据串号清除系统凭据后重新认证remote origin already exists仓库状态远端重名git remote set-url或换名字rejected / non-fast-forward仓库状态远端有新提交git pull --rebase后重推refusing to merge unrelated histories仓库状态历史无共同祖先--allow-unrelated-historiesGH001 Large files detected仓库状态历史含超大文件.gitignoregit filter-repoFailed to connect to port 443网络传输链路不通换网络确认出口策略考虑双远端RPC failed; curl 56 / early EOF网络传输传输中断或包过大http.version HTTP/1.1拆包推送the remote end hung up unexpectedly网络传输单次包过大分批提交core.compression 0表格里每一条在前面的章节都有展开遇到不熟悉的再翻回去看细节。7. 上传前养成的几个自检习惯7.1 上传前花一分钟过一遍清单与其事后救火不如提交前花一分钟。我现在形成了固定的自检动作基本能挡掉九成问题。第一确认.gitignore存在且内容合理。至少要覆盖node_modules/、venv/、.env、dist/、build/、各类 IDE 的配置目录、系统生成的.DS_Store和Thumbs.db。特别是.env里面往往有数据库密码和接口密钥一旦推上公开仓库几分钟内就会被自动化脚本扫到后果很严重。这一点我见得太多真心建议把.env写进全局忽略git config --global core.excludesFile ~/.gitignore_global echo .env ~/.gitignore_global第二用git status再扫一眼待提交列表。看到陌生的文件名就停下来想想它是怎么进来的。第三用git diff --cached --stat看一眼改了哪些文件、增删了多少行。如果发现自己只改了一个小功能却显示改了几十个文件、删了几万行那大概率是换行符或者构建产物混进去了。第四确认大于 10MB 的文件不是无意中加入的。如果确实需要走 LFS。第五提交信息写清楚别用update、fix这种。git log是给未来的自己看的半年后回来看fix bug完全想不起改了什么。7.2 提交粒度与分支策略的实际取舍关于提交粒度我的经验是一个提交只做一件事。改了格式化又改了逻辑拆成两个提交。这样万一格式化那个提交引入了问题回滚起来干净利落。关于分支很多人一开始都在 main 上直接推。小项目无所谓一旦有了协作者建议至少养成这样的习惯新功能开分支推分支走一次合并流程再同步到主分支。git checkout -b feature/login git add . git commit -m feat: 增加登录页面表单校验 git push -u origin feature/login第一次推新分支要带-u把追踪关系建好。之后在这个分支上直接git push就行。分支推上去后可以在网页端发起合并请求让流程更规范也留下变更记录。顺带说一个清理习惯合并完的分支记得删本地git branch -d feature/login远端在网页上删。分支堆多了之后git branch -a输出几十行找东西特别费劲。7.3 几个能省时间的配置项最后分享几个我每台新机器都会配上的项属于一次性投入、长期受益的类型。# 显示中文文件名而不是转义字符 git config --global core.quotepath false # 让 log 更可读 git config --global alias.lg log --oneline --graph --decorate --all # 让 status 更简洁 git config --global alias.st status -sb # 推送当前分支的快捷方式 git config --global alias.ps push # 默认以 rebase 方式拉取减少多余的合并提交 git config --global pull.rebase truegit lg这个别名我用了很多年一屏就能看清分支走向和提交关系排查我的提交到底推上去没有这类问题时特别直观。pull.rebase true则能从源头上减少无意义的合并提交让历史保持直线看不懂分支图的人也能一眼跟上。有一点要提醒pull.rebase true在有冲突时会把流程变成 rebase 交互对新手来说不如 merge 直观merge 至少会生成一个合并提交冲突解决后是明确的提交动作。如果你还不熟悉 rebase 的--continue和--abort可以先不设这一项等熟悉了再开。我个人在实际操作中的体会是GitHub 上传文件报错看着花样繁多但真正的原因翻来覆去就那么几个——环境没配、身份没设、认证过期、历史分叉、包太大、链路不稳。把这些关键词和对应处理动作记牢遇到再陌生的报错也能在两三分钟内定位到方向。真正浪费时间的从来不是报错本身而是没有章法地乱试。