Git学习记录:从安装配置到分支管理与免密方案全解析
我真的不是标题党为什么我会写这样一份Git学习记录先交代一下背景。2024年以前我一直是个“能跑就行”的半吊子用户Git在我手里基本只有三板斧add、commit、push。直到有一次帮同事排查代码冲突发现自己连git rebase和git merge的区别都讲不清楚更别提背后那套索引和对象模型了。那段时间我吭哧吭哧翻文档、看专栏、记笔记前前后后折腾了一个月踩了无数坑才慢慢把Git从“工具”用成了“习惯”。这份“Git学习记录”不是官方文档的复读也不是命令大全式的罗列。它是我自己从零开始、亲手敲过每一个命令之后的经验沉淀包含完整安装配置、高频命令、免密方案、常见网络热词背后的真实场景以及一些冷门但实用的排查技巧。适合刚起步的新手照着操作也适合给用了一段时间但总感觉哪里没通的人查漏补缺。如果你正准备系统梳理一遍Git这篇文章应该能帮你少走大半弯路。1. 先别急着敲命令Git安装前的三个认知铺垫很多教程上来就让你下载安装装完再讲概念结果就是命令敲得飞起出了问题完全不知道去哪找原因。我自己踩过这个坑所以强烈建议你动手之前先把下面三件事在脑子里过一遍。1.1 为什么要先理解Git和GitHub的区别这是个特别基础但又特别容易被混淆的点。Git是一个分布式版本控制系统它负责在你本地记录文件的每一次改动、管理分支、支持回滚而GitHub、GitLab、Gitee这些平台只是基于Git协议搭建的远程托管服务相当于给本地仓库提供了一个云端备份和协作的中转站。没有远程仓库Git本身也能完整工作。我在没有联网的飞机上提交过代码落地后一push所有提交记录都在这就是分布式带来的安全感。搞清楚这层关系之后你就不会再把“上传到GitHub”和“使用Git”画等号了后面理解remote、push、pull这些概念会顺畅很多。1.2 版本选择和包管理器之争官方安装包还是命令行安装Git的安装方式很多但不同方式的后续维护成本差异非常大。以我的实战经验分系统来说Windows环境官方exe安装包从git-scm.com下载和winget install --id Git.Git -e效果差不多exe安装时注意勾选“Add to PATH”即可。不建议用非常古老的“便携版”或来路不明的绿色版因为Git在Windows依赖系统环境变量和OpenSSL配置封装过度的版本容易出幺蛾子。macOS环境我强烈推荐通过Homebrew安装也就是brew install git。好处有两点第一它自动处理依赖关系第二后续升级只要一条brew upgrade git就够了不用跑到官网重新下载安装包覆盖。Linux环境用发行版自带源安装最简单Debian/Ubuntu系执行sudo apt install gitCentOS/RHEL系执行sudo yum install git。如果源里的版本太老那就编译安装新版或者配置第三方源但这适合有经验的用户新手建议先用系统源。从我的实操心得来看无论哪个系统装完之后第一件事都应该是执行git --version确认安装成功同时看一眼版本号。不同版本的Git对协议、默认分支名、认证插件的支持不同版本信息是排查问题的第一线索很多人遇到疑难杂症最后发现是版本太老导致的。1.3 一次安装后的全局体检验证Git是否具备完整工作能力安装不等于配置完成。我见过很多人在这一步翻车因为装完之后什么都没验证就进入下一步等到推送代码才发现认证有问题。安装完我习惯顺手执行下面这几条命令做体检# 查看版本确认安装成功 git --version # 查看全局配置文件位置方便后续手动编辑 git config --global --list --show-origin # 查看Git默认使用的编辑器 git config --global core.editor如果git config --global --list返回空说明你还没设置用户信息如果提示找不到命令那就从PATH变量排查。我曾经在Windows上遇到过装完Git但重启终端才生效的情况因为环境变量在系统重启前不会重新加载。这些都是小问题但提前知道解法总比临时抓瞎强。2. 安装及配置教程的进阶组合用户信息、换行符、别名的完整调优关于“Git安装及配置教程”的热搜词常年居高不下说明大家都卡在安装之后的那一步怎么配置才顺手这里我把自己长期使用的配置方案完整拆开每一步都告诉你为什么要这样设置。2.1 用户信息配置user.name和user.email的真正作用git config --global user.name Your Name git config --global user.email youremail.com这是每个教程都会教的命令但我特别想强调一点这个user.email和你的远程仓库登录账号没有必然关系。它只作为提交记录里的作者标识将来显示在commit历史里。所以哪怕你的邮箱填错了提交依然能成功只是提交历史里会留下错误的作者信息。这里有三个级别需要分清--system全机器生效、--global当前用户生效、--local当前仓库生效。作用域越小优先级越高。如果一个项目需要用特定的企业邮箱覆盖全局的个人邮箱就在该项目目录下执行git config --local user.email workcompany.com这样不会影响其他项目。修改完user信息后已经产生的旧提交不会自动更新。如果需要在改邮箱后修正历史可以用git filter-branch或git filter-repo但那个操作会改写提交哈希强烈不建议在共享分支上执行。我个人的习惯是先想清楚用什么邮箱提交前检查一遍省得后续折腾。2.2 core.autocrlf新老手最容易忽略的换行符陷井换行符的问题表面看不致命但一旦遇到解决起来最费时间。Windows系统里的文本默认用CRLF回车换行结尾而Linux和macOS用的是LF换行。Git如果不去管它同一份文件在不同系统之间切换时会在diff里看到整行都被标为改动造成“文件没动但diff很乱”的假象。处理这个问题的配置项是core.autocrlf。我推荐按系统分开设置Windows用户设置为trueGit在提交时会把CRLF转为LF存进仓库检出时再转回CRLFmacOS和Linux用户设置为input提交时转成LF但检出时不强制转换如果你确定团队所有成员都用同一种系统那就设置false彻底关闭转换。我个人的做法比较稳妥在仓库根目录增加一个.gitattributes文件明确指定哪些文件用什么换行符。比如* textauto *.sh text eollf *.bat text eolcrlf把这个文件提交到仓库后所有成员无论在哪套系统上操作都会被Git强制按规则处理换行符比靠每个人自觉修改配置可靠得多。这个技巧是从一次线上事故里学来的当时因为Windows成员提交时把整个文件从LF转成了CRLF导致diff全部显示为删除再新增代码评审差点没法做。2.3 配置别名和默认编辑器让Git用起来更顺手的小细节Git允许为命令配置别名也就是快捷键。我常用的别名配置如下git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status git config --global alias.lg log --graph --prettyformat:%h -%d %s (%cr) %an --abbrev-commit --daterelative设置完git lg之后你会得到一棵清晰的分支提交图谱每次看历史都比默认的git log舒服得多。别名的本质是字符串替换所以还能组合出更复杂的自定义命令比如git config --global alias.unstage reset HEAD --以后想取消暂存就可以直接执行git unstage file.txt不用记那一长串reset参数。配置编辑器同理执行git config --global core.editor code --wait之后commit信息弹窗就会用VS Code打开写完保存关闭即可。3. 核心命令的精讲与实操add、commit、branch和撤销策略很多人把“Git命令”直接理解为一堆离散指令背了就忘。实际上Git的高频命令背后有一条非常清晰的路径往索引里放内容add、把索引固化成记录commit、在记录之间切换和分叉checkout/branch、必要时抹掉或修改记录reset/revert。一旦你理解这条路径命令就不再需要死记硬背了。3.1 把目录变成仓库init和clone的适用场景git init是把当前文件夹变成一个仓库适合你手头已有项目、准备开始用Git管理的情况。执行完会生成一个.git隐藏目录这个目录里存放着Git的全部对象、引用和配置信息不要手贱去改里面的文件。git clone则适合从零开始接手一个已有项目。它的本质是在本地把远程仓库完整复刻一份包括所有历史提交。所以clone出来的项目自带完整log不需要重新init。我建议新手在GitHub上练习时多采用clone方式——GitHub会默认生成README等文件避免你陷入“先有仓库还是先有文件”的鸡生蛋问题。3.2 add和commit之间的那道“暗门”暂存区到底装了什么我刚学Git时最不理解的就是暂存区Index/Stage存在的意义为什么不能一步到位直接提交后来才意识到暂存区提供的恰恰是“挑挑拣拣再打包”的能力。git add会把文件当前的内容复制到暂存区生成一个二进制快照git commit则把暂存区里的快照正式提交为版本记录。如果你改了文件却不add无论怎么commit这次改动都不会进去。这个报错提示“Changes not staged for commit”就是这么来的。工作中的高频场景是只需要提交一部分文件改动这时可以用git add file1.txt file2.txt git commit -m 只提交这两个文件的改动或者更精细一点只想提交某个文件中的部分改动git add -p这条命令会逐块hunk询问你是否要暂存某个改动的片段适合那种“顺手在一份文件里改了两个无关点”的情况。我几乎每天都在用git add -p它能帮你把提交记录拆得干净整洁这也是评审代码的同事对提交粒度比较满意的关键。3.3 分支管理实操新建、切换、合并和删除分支是Git的杀手级能力但它的开销问题曾让很多SVN用户产生误解——以为分支很重不敢多用。实际上Git创建分支的成本极低因为它只是创建一个指向某个提交的指针不复制文件所以“早建分支、勤建分支”是靠谱的实践。常用命令# 查看本地和远程的分支列表 git branch -a # 新建并切换到某分支 git checkout -b feature/login # 普通切换 git checkout main # 合并feature分支到当前分支 git merge feature/login # 删除本地分支 git branch -d feature/logingit checkout -b这个复合命令等价的底层逻辑是先branch再checkout。我在实际工作中发现一个常见的坑如果当前工作区有未提交的改动checkout切换分支时可能会把改动带过去。解决方法是提交或stash之后再切换。合并代码时我倾向用git merge --no-ff保留一条合并记录便于回溯时确认“这个功能是哪批合并请求带进来的”。如果你想规整历史那再学git rebase把一条分支上的多次提交“变基”到目标分支顶部。这里先按个暂停rebase会重写提交哈希只在本地未推送的分支上使用不要在团队共享分支上使用。3.4 撤销操作的三个维度工作区、暂存区、提交记录撤销是Git学习和使用的高频痛点也是新手最容易把状态搞乱的地方。我按操作对象把撤销策略拆成三层第一层工作区改动未暂存时git restore file.txt这条命令会把文件还原成最近一次提交或暂存的状态相当于放弃当前还没add的修改。它是危险命令一旦执行未提交的修改无法恢复。第二层已经add进暂存区时git restore --staged file.txt这会把文件从暂存区移出来变成“已修改未暂存”的状态但文件内容本身不会动。如果你需要连暂存区的保存内容一起回滚到最新提交的状态那就git reset HEAD file.txt这里的核心思路是--staged只动索引不动工作区想同时清空工作区就把两个参数组合使用如git reset --hard HEAD。但注意reset --hard非常暴力会同时丢弃工作区和暂存区的全部改动使用时务必谨慎。第三层提交记录需要修正时如果只是commit信息写错了用git commit --amend重新编辑上次提交信息如果提交内容有遗漏用git add补加文件后再执行git commit --amend它会合并进上一条记录不产生额外的新提交如果某个提交已经push到远程需要撤销这次提交产生的内容变动用git revert commit-hash。revert会生成一条新的反向提交保留原有历史适合团队协作场景。撤销命令对比速查表操作场景命令是否影响历史适用场景放弃工作区未暂存改动git restore file否本地改乱了想还原撤销暂存但不删文件git restore --staged file否误add了不想提交的文件重置提交指针git reset --hard HEAD~1是本地废弃最近一次本地提交新增反向提交以撤销远端改动git revert hash是追加一条已推送提交需要回滚我从自己多年的实操中总结出一条血泪教训不确认命令后果前不要带--hard参数。宁可多执行一步git status看清当前工作区状态也不要莽撞操作后在回收站里找日志。真的碰到误删还有一个缓兵之计是git reflog它能查看HEAD和分支引用在过去一段时间内的变动记录误删的提交往往还能通过它捞回来。4. 远程仓库与免密配置的完整方案“Git免密”、“Git下载安装教程”、“git -c diff.mnemonicprefixfalse -c core.quotepathfalse --no-optional-locks”等热词背后反映出大家真正遇到的问题其实集中在“怎么跟远程仓库舒服地打交道”。这一章我会把远程协作相关的配置和使用讲透。4.1 添加远程仓库、推送与拉取的操作细节假设你在GitHub上新建了一个空仓库回到本地# 给当前仓库添加远程地址 git remote add origin gitgithub.com:username/repo.git # 推送本地main分支到远程并建立跟踪关系 git push -u origin main-u参数的作用是把本地分支与远程分支关联起来这样以后直接执行git push或git pull时Git就知道该跟哪个远程分支交互无需每次带上仓库名和分支名。日常开发中执行git pull之前我会习惯先看一眼当前工作区是否干净。如果本地有未提交改动pull可能引发冲突或者报错“Your local changes would be overwritten”这时要么先提交要么用git stash把改动暂存起来pull之后再git stash pop取回。一个我反复推荐给团队同学的小技巧push之前先pullpull之前先stash或commit。这个顺序能规避绝大多数协作冲突。4.2 SSH免密配置为什么我推荐它而不是HTTPS输密码如果不想每次git push都手动输入用户名和密码就必须做免密配置。Git认证的主流有两种方式一是HTTPS 凭证管理器credential helper。Windows上安装Git时通常自带“Git Credential Manager”第一个推送会弹窗让你输入用户名和Token此后凭证被加密保存Git会自动复用。macOS则有“osxkeychain”作为凭据存储。这种方式对新手很友好简单快捷。二是SSH密钥对。我本人更推荐这种方式因为SSH密钥一旦配置好对后台脚本、持续集成、多仓同步都很友好。说下完整流程# 第一步生成SSH密钥对 ssh-keygen -t ed25519 -C youremail.com # 生成结果建议保存在 ~/.ssh/id_ed25519 和 ~/.ssh/id_ed25519.pub # 第二步启动ssh-agent并添加私钥 eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519 # 第三步把公钥内容复制到GitHub/GitLab的SSH key设置页 cat ~/.ssh/id_ed25519.pub为什么选择ed25519而不是传统的rsa因为ed25519密钥更短、生成更快、安全强度也足够GitHub早在2021年就全面支持了。把公钥加到平台后我建议用ssh -T gitgithub.com测试连通性出现“Hi username!”的提示说明验证通过。之后在执行git remote add时选用SSH地址形如gitgithub.com:username/repo.git推送过程就不再要求输入密码了。HTTPS与SSH免密方案对比维度HTTPS Credential ManagerSSH密钥首次配置难度低弹窗引导中需要理解公钥/私钥多设备管理每台设备都要登录授权每台设备生成独立密钥并添加公钥适合场景新手、少量克隆公有仓库开发主力、CI脚本、日常多仓库管理安全风险Token泄露需要到平台撤销私钥泄露等同于账号泄露4.3 git凭据管理器与token登录别再傻傻输入账号密码了如果你确实不想生成SSH密钥但又必须用HTTPS方式操作Github那么现代GitHub的密码认证已经不能使用账号密码的组合了必须使用Personal Access TokenPAT。在GitHub“Settings Developer settings Personal access tokens”中生成一个Token把它当成密码粘贴或者干脆写进URL里git remote set-url origin https://TOKENgithub.com/username/repo.git不过直接在remote地址里嵌入Token很容易泄露我不建议长期使用。更好的做法是使用credential helper缓存一次git config --global credential.helper cache # 默认缓存15分钟 git config --global credential.helper cache --timeout3600实际上Windows上的Git Credential Manager和macOS的osxkeychain都能做到持久化存储第一次输完Token之后就不再重复询问了。5. 一个冷门但常见的Git命令场景当你在日志里看到“git -c diff.mnemonicprefixfalse ...”有时候你会在IDE、GUI客户端或自动化工具的运行记录里看到类似git -c diff.mnemonicprefixfalse -c core.quotepathfalse --no-optional-locks ...的命令。很多初学者会被这种超长命令吓到以为是什么深奥魔法。其实它只是带了一堆临时配置项的普通Git调用。理解它有助于你看懂GUI工具在后台做了什么。5.1 拆解这条命令里的三个参数先看它的结构git -c keyvalue command。-c的作用是临时修改一个配置项只对当次命令生效不写入配置文件。例如diff.mnemonicprefixfalsemnemonicprefix如果为trueGit在diff输出时会把a/和b/前缀换成index/、worktree/之类的语义化前缀置为false则保持默认的a/和b/前缀。GUI工具设置成false往往是为了让输出的patch行为更传统、更便于解析。core.quotepathfalse这个配置很实用。它控制Git对非ASCII文件名的处理。默认情况下Git为了安全会把中文或带空格的文件路径转义成八进制字符串类似\346\265\213\350\257\225.txt很难读。设置为false之后可以直接显示原始路径。--no-optional-locks这是一个命令行选项意思是禁止执行某些可选锁操作。例如当git命令运行在类似Sourcetree这样的GUI工具里时工具只看状态但不想改变仓库的访问时间等元数据加这个参数可以避免不必要的锁等待。5.2 从这条命令学到的事Git所有配置都可以临时覆盖理解这条命令的收获不只是认参数而是一个底层思路Git的配置项几乎都能在前缀临时指定。比如你在CI脚本里临时需要用户身份覆盖仓库里的配置可以不带--global直接在一条命令前加-c user.name... -c user.email...然后执行commit。脚本里调试也是这么干的。我遇到一次线上部署脚本因为仓库历史里的user.name不匹配导致审计失败当时就是用临时覆盖方式快速定位的并没有改动全局配置。所以不要把-c理解成冷门技能它是真正能救命的排查工具。6. 常见问题与排查技巧实录这一章我记录一些自己从新手期一路走来实际踩过的坑。它不像前面的章节那样线性更像一份“速查手册”你遇到问题时可以按图索骥。6.1 中文文件名显示成八进制乱码这是Git老用户都会遇到一次的谜之现象执行git status改动的中文文件名显示成\346\265\213\350\257\225.txt。根本原因就是上面提到的core.quotepath默认值为true。Git默认对非ASCII路径做了转义处理避免不同编码环境下文件名输出不一致。解决方案很朴素git config --global core.quotepath false修改后立即生效中文路径正常显示。开发环境是UTF-8编码的朋友建议直接配成全局省得每台新机器都踩一次。6.2 明明文件删了为什么Git还说有改动新手常遇到的两张“灵异脸”移除了文件但Git没感知到误删了文件想恢复但不知道命令。如果是在文件管理器里手动删除文件Git会感知到“deleted”状态但不会自动暂存。你需要执行git rm file.txtgit rm会同时删除工作区文件和暂存区记录。如果你只是想从版本控制里移除文件但保留本地文件那就用git rm --cached file.txt这个命令适合处理误提交进去的大文件或配置文件。需要注意的是执行后必须提交删除操作才会真正记录到版本历史里。恢复误删文件同样简单git restore file.txt只要文件在最近一次提交里存在它就能被恢复。但前提是你还没有把删除操作提交上去如果已经提交那就到对应提交里取文件。6.3 提交信息写错或漏了文件善用commit --amend很多人第一次用git commit --amend都心惊胆战担心改坏了历史。其实它只是把当前暂存内容合并到上一个提交上不改变分支脉络。应用场景有两类改错别字或规范提交信息git commit --amend -m fix: 修正登录接口参数校验漏提交了一个文件git add forgot-file.txt git commit --amend --no-edit--no-edit表示沿用上一条提交信息不用重新编辑。这个命令的唯一坑是如果那个提交已经push到远程共享分支amend之后本地和远程的提交哈希会不一致此时直接push会被拒绝需要git push --force或git push --force-with-lease。force push是协作禁区除非你明确知道自己在做什么否则不建议对共享分支执行。6.4 误操作的后悔药reflog到底能救回什么如果上面的方案都不能解决你的问题还有一个终极后悔药。Git里有个概念叫“引用日志”reflog它记录了HEAD指针的历史移动轨迹。即使你执行了git reset --hard丢弃了某次提交只要那次提交还在reflog里躺着就能被找回。git reflog输出会列出序号、操作前后的commit哈希以及操作描述。找到丢失前的位置后比如HEAD{2}执行git reset --hard HEAD{2}就能回到那个状态。这个命令在找回误删分支、误reset提交时非常管用。注意reflog有保留期默认是90天过期后不可恢复所以挽救要趁早。6.5 高频问题速查表现象原因处理建议push被拒绝提示“non-fast-forward”远程有新提交本地落后先pull或fetch再merge/rebase提交里作者显示的邮箱不对user.email配置错误结合filter-branch修正谨慎操作共享分支中文文件名显示乱码core.quotepath为true设置core.quotepath falsepull时报“local changes would be overwritten”本地有未提交改动commit或stash后再pull切换分支时未提交改动被带过去工作区状态跨分支延续先checkout前确认干净或用stash隔离某文件无故被标记为已修改换行符不一致用.core.autocrlf和.gitattributes统一换行符commit --amend之后push失败本地与远端历史哈希不一致改用新提交或仅在确认安全的情况下force-with-lease误删分支找不到分支引用已删除用git reflog找回该分支最后一次的commit哈希7. 这份学习的延续思考到底该怎么继续深入Git走到这里你已经把日常开发和团队协作中使用频率最高的Git能力过了一遍。但Git的水远比我现在写到的深得多。比如git bisect定位引入bug的提交、git worktree实现一个仓库同时检出多个分支、git replace和git filter-repo做历史改写都是进阶路上的好课题。我自己学Git最深的体会是一定要想办法把命令和实际场景挂钩。单纯记住git merge是什么意思没有意义当你真的在分支上写下一天代码之后merge失败亲历一次冲突解决、亲手逐行选出保留内容这个知识点才能真正沉淀下来。所以多看官方文档有价值但更重要的是在自己项目里把每个命令都用一遍。最后分享一个我保持了很久的习惯给自己的开源小项目单独建一个仓库每次想尝试不熟悉的Git操作就到这个仓库里做实验。分支、reset、rebase、amend随便折腾反正只是个测试场。等你在测试仓库里把所有操作跑顺手再去动自己真正的代码心里会踏实很多。这也是我在实际使用中觉得最值得推荐的一种学习方式。