十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Git版本控制实战指南:从入门命令到协作与排错

Git版本控制实战指南:从入门命令到协作与排错 写git学习这个话题我其实是有点感慨的。入行这些年见过太多同事把git用得跟“复制粘贴备份文件夹”似的也见过不少新手被几个报错卡得整晚睡不着。git这东西表面上是命令和参数背后其实是一套完整的版本管理思维。学git不是为了背命令是为了让你改代码的时候心里有底改坏了能回去写岔了能分叉多人一起干也不打架。这篇内容我尽量按自己从安装配置到日常实战的顺序来写把常见报错和那些文档里不会明说的坑一并放进去了不管是刚接触git的小白还是用了一阵子但总觉得没吃透的同学应该都能找到点有用的东西。1. 为什么git值得专门花时间学1.1 从一个“手滑删库”的真实场景说起有一回我同事在项目上线前一天想清理一下本地多余文件顺手执行了一个删除命令等他反应过来的时候整个项目文件夹已经空了。幸好我们用git他在终端里敲了一句恢复命令代码完完整整地回来了。那一刻他跟我说“我学git的时候觉得不就是几个命令嘛没想到真能救命。”这事儿特别能说明git的核心价值版本管理就是给代码上了时间机器。你每一个阶段的修改都会留下记录随时随地可以回退到任意一个历史节点。这种“后悔药”能力是任何手动备份都替代不了的。你手动复制文件夹做备份一是慢二是容易搞混哪个是最新版三是没法多人协作。git把这些全部解决了。我用一个生活化的类比帮你理解git就像游戏里的存档系统。你每打一个关键boss之前都会存档打挂了就回到存档点重来。写代码也一样每次完成一个小功能就提交一次以后出了bug回到上一个绿色存档点就行完全没有心理包袱。1.2 学会git能帮你解决哪些实际问题git学习的价值具体落在三个场景上。第一个是个人开发的安心感所有代码历史都在本地仓库里完整保存哪怕远程仓库崩了你本地也有全量记录。第二个是团队协作的秩序感多个开发者同时改同一个项目git通过分支和合并机制让大家的改动有序地汇合谁改了什么一目了然。第三个是版本发布的节奏感你可以基于某个稳定版本打tag出问题可以快速定位是哪个版本引入的这对线上维护至关重要。顺着这个思路往下走学习路径就很清晰了先装好工具再跑通本地操作然后是分支合并接着是远程协作最后是规范化和问题排查。这篇博文就按这条线帮你捋一遍。2. 环境准备git安装与初始配置2.1 各平台的安装方式与关键细节git安装这件事看起来简单但不少人的第一个坑就埋在这里。先说Windows平台最主流的做法是去git官网下载安装包。下载的时候要留意你的系统是64位还是32位现在绝大多数电脑都是64位选64-bit版本就行。安装过程中有一个步骤会问你要不要调整PATH环境变量这里我建议选**“Git from the command line and also from 3rd-party software”**这样你在CMD、PowerShell里都能直接用git命令。很多新手在Windows上装完git打开cmd输git --version却提示“git不是内部或外部命令”十有八九就是安装时没勾选PATH相关选项或者装完没重新打开终端。这个问题的排查方法我在后面第8部分会详细说这里先记住装完git一定记得重启终端。macOS用户就比较省事系统自带的话版本可能旧建议用Homebrew装最新版一条命令搞定。Linux用户用各自的包管理器Ubuntu是apt install gitCentOS是yum install git。装完统一用git --version验证版本我这边是2.40以上的版本功能完整用起来没毛病。另外多说一句网上搜“git下载”经常搜出一堆第三方站点我不建议从那些地方下因为没法保证安装包没被动过手脚。只认官网或者系统官方源这是最基本的安全意识。2.2 三个必须做的初始化配置git装好以后第一件事不是急着建仓库而是告诉git“你是谁”。这两条命令是必须的git config --global user.name 你的名字 git config --global user.email 你的邮箱别小看这两行你每次提交代码git都会把这两条信息写到提交记录里。如果没配置你提交的时候git会报错提示你Please tell me who you are。团队协作的时候提交记录里显示的名字和邮箱就是别人识别你的方式所以团队里一般会要求统一真实姓名而不是网名这样出了问题好找人。除了姓名邮箱还有几个配置我建议顺手就设好。一个是默认分支名现在主流平台都默认用main而不是master了你可以设置git config --global init.defaultBranch main这样以后初始化仓库默认分支就是main。另一个是换行符处理Windows和macOS/Linux的换行符不一样为了避免“明明没改代码却显示整个文件都变了”的尴尬Windows用户建议设置git config --global core.autocrlf trueMac/Linux用户就设成input。这个配置是个细节但真能帮你避免很多莫名其妙的diff。还有一个跟中文相关的配置我要特别提一下。我见过很多人用git status查看中文文件名时显示成转义字符乱七八糟没法看。这其实跟git的一个默认行为有关它对非ASCII字符做了转义。解决办法是执行这行命令git config --global core.quotepath false设置了之后中文文件名就能正常显示了。这行命令我很多人不知道但属于那种“知道以后幸福感大幅提升”的配置。2.3 配置的查看与修改配置完了怎么检查呢用git config --list可以列出当前所有生效的配置。这里有个细节值得注意git配置分三个层级系统级system、全局级global、仓库级local。优先级是仓库级最高就是你只对当前仓库生效的配置会覆盖全局配置。比如你个人用全局的user.email是私人邮箱公司某个仓库要改成公司邮箱你就在那个仓库目录下执行不带--global的config命令只改这个仓库的邮箱。配置文件的位置也要知道全局配置在用户主目录下的.gitconfig文件仓库级配置在仓库目录下的.git/config文件。有时候图形界面改了配置没生效直接去看这两个文件反而更清楚。到这里git的基本盘就搭好了。3. 从零跑通本地仓库操作闭环3.1 初始化、添加、提交、查看历史现在正式进入操作环节。我先带你完整走一遍“初始化到提交”的流程这是git世界里最核心的循环。git init这个命令会在当前目录创建一个隐藏的.git文件夹这个文件夹就是git的“数据库”里面存着所有版本历史。注意.git文件夹相当于整个仓库的心脏没事不要手动去改里面的东西。然后是git status建议你养成每次操作前先输入这个命令的习惯。它会告诉你当前工作区处于什么状态哪些文件被修改了哪些文件还没被跟踪。这个命令是我日常用最多的一个没有之一。接着是添加文件到暂存区git add .或者指定文件git add filename.txt。这个步骤相当于告诉git“我准备把这些文件纳入下一次提交”。我经常听人说“git add之后文件就保存了”这句话不严谨。add只是把文件放进了暂存区真正产生一个历史版本的是下一步git commit -m feat: 添加用户登录功能commit会把你暂存区里的内容打包成一个版本记录存进git数据库。这个版本就有了唯一的ID以后想回退就靠它。提交之后用git log看历史你会看到每个提交的哈希值、作者、时间、提交说明。这个列表就是你的代码存档清单。3.2 你真的理解工作区、暂存区、版本库吗很多git教程会画三张区域图工作区、暂存区、版本库。我用一个购物车的类比帮大家记住工作区是你电脑上肉眼可见的文件夹你正在编辑的代码就在这里。暂存区是购物车你逛超市把想买的东西一件件放进去对应git add。版本库是收银台结账后的购物袋你已经付款拿走的商品对应git commit。为什么git要设计这么一道“购物车”环节因为有时候你改了三个文件但只想把其中两个提交成一个版本。暂存区给了你选择“哪些改动进这次提交”的自由度。比如你修了一个bug同时加了两个跟bug无关的格式调整你就可以只把bug修复那个文件add进去提交另外的文件留到下次提交。这就是原子提交的实践基础一次提交只做一件事。3.3 撤销与恢复restore、reset、amend怎么选git之所以让人有安全感很大程度在于撤销操作很强大。但恰恰是撤销这一块命令特别多容易把人绕晕。我按场景给你捋一下。场景一文件改了但还没add想放弃修改。git restore filename这命令把工作区的文件恢复到最近一次提交/暂存的状态。注意会直接覆盖你的修改执行前想清楚。场景二文件已经add进暂存区了想取消暂存。git restore --staged filename文件内容不改动只是把它从暂存区退出来变成“已修改未暂存”的状态。场景三commit之后发现提交信息写错了或者发现漏了一个文件。git commit --amend这会修改最近一次提交。如果只是改提交信息直接git commit --amend -m 新的说明。如果是漏了文件先git add那个文件再执行git commit --amend这样新的提交会替代旧的提交不会产生多余的历史记录。场景四已经commit了想回退到某个历史版本。这里要格外小心。如果你还没push到远程可以用git reset如果已经push到远程了那就不要随便reset而是用git revert。reset是移动HEAD指针历史会被改写revert是生成一个新提交来“反向操作”某次提交历史是完整的。我个人的经验是本地代码想怎么折腾都行push过的内容优先考虑revert。这样不破坏远程仓库的历史协作时不会坑队友。4. 分支与合并多人协作的基石4.1 分支的本质是“平行世界”分支这个概念理解透了git就学会一大半了。你可以把分支想象成平行宇宙你从主线上分出一条分支在分支里随便折腾折腾完了再合回主线互相之间不影响。git branch # 查看本地分支列表当前分支前面会有*号 git branch feature-login # 创建一个名为feature-login的分支 git checkout feature-login # 切换到该分支旧命令 git switch feature-login # 切换分支新命令git 2.23我建议用git switch来做切换语义更清晰不容易跟别的操作混淆。创建并切换可以合并成一条git switch -c feature-login这里有个关键机制要理解git的分支本质上只是指向提交的指针。创建分支就是在某个提交上贴了一个新标签成本极低所以git鼓励“多用分支、大胆开分支”。每开一个分支就是开辟一个独立的开发空间互不干扰。4.2 合并与冲突解决分支开发完需要合回主分支用git merge feature-loginmerge的工作方式多数情况下是fast-forward快进合并就是主分支指针直接往前推到feature分支的位置。但如果主分支在你分叉之后又有新的提交git会生成一个特殊的“合并提交”merge commit。大部分时候git能自动合并但两个人改了同一个文件的同一块区域就会产生冲突。冲突长什么样呢你打开冲突文件会看到一堆特殊标记 HEAD 这是你当前分支的内容 这是你要合并进来的分支的内容 feature-login别慌解决办法是手动编辑文件把、、这些标记删掉保留你想要的内容然后保存文件git add再git commit即可。我处理冲突的经验是不急着解决先看清楚双方改动的意图。如果是两个人改了同一处最好把相关同事拉上一起确认因为你自己擅自决定保留哪边可能会吞掉别人的逻辑。解决完冲突一定要跑一遍相关功能测试这一点再强调都不过分。4.3 merge还是rebase这是个问题和merge经常一起被讨论的是rebase。git rebase做的事情是把你的分支“基底”移动到另一个分支的最新提交上让提交历史变成一条直线看起来更整洁。什么时候用rebase我个人的习惯是自己的功能分支想同步主分支最新代码时用rebase。这样你的分支会包含最新的主分支代码而且历史干净后续合并回主分支就是一个快进没有乱七八糟的分叉。**绝不要在共享分支上rebase。**因为rebase会改写提交历史一旦别人已经基于你的旧提交做了开发你rebase后他们的本地历史就跟远程对不上了协作直接乱套。这个原则我记得比较牢“rebase是用来让自己分支保持整洁的不是用来重写公共历史的。”5. 远程仓库让代码在不同机器间流动5.1 clone与remote本地操作熟练之后就该接触远程仓库了。远程仓库是放在服务器上的git仓库常见的托管平台有GitHub、GitLab、Gitee等。把远程仓库复制到本地用git clone https://github.com/gaoshu705/qzonearchive.git注意clone后面跟的地址是你远程仓库的URL。clone下来的项目会自动关联远程仓库直接就能看到origin这个远程主机名。如果你本地已经有一个项目想关联到远程仓库通常的流程是在平台上新建一个空仓库然后git remote add origin https://github.com/你的用户名/你的仓库名.git git branch -M main # 确保本地默认分支叫main git push -u origin main-u的意思是设置上游跟踪以后可以直接用git push和git pull不用再带远程主机名和分支名。这个细节很多人会忽略但不加的话每次push都要打一长串参数很麻烦。5.2 push、pull、fetch的准确用法git push # 把本地提交推送到远程 git pull # 拉取远程最新代码并自动合并 git fetch # 拉取远程最新代码但不自动合并fetch和pull的区别值得专门说明。fetch只是把远程仓库的更新下载到本地的一个“远程跟踪分支”上比如origin/main但不会动你当前的工作分支。pull则是fetch加merge两步一起干。为什么有时候推荐先用fetch因为pull的自动合并可能会在你的工作区产生意外的冲突或合并提交而且你还没反应过来就已经合并了。先git fetch再git log origin/main..HEAD对比一下差异心里有数了再决定怎么合并会更稳妥。5.3 SSH免密配置一次配置长期受益每次push都输账号密码体验太差了这也是“git免密”一直被搜索的原因。git支持两种远程认证方式HTTPS和SSH。HTTPS方式下你可以用密码或者personal access token来认证但每次都输确实烦。所以我更推荐用SSH。第一步生成SSH密钥对。ssh-keygen -t ed25519 -C 你的邮箱一路回车就行会生成一对密钥私钥放在~/.ssh/id_ed25519这个必须保密绝对不能传给任何人或上传到任何仓库公钥放在~/.ssh/id_ed25519.pub这个可以公开。**第二步把公钥添加到代码托管平台。**用文本编辑器打开公钥文件把内容复制出来在GitHub或GitLab的设置页面找到“SSH Keys”选项粘贴进去保存。第三步验证是否配置成功。ssh -T gitgithub.com如果你用的是GitHub看到Hi 用户名! Youve successfully authenticated就说明成功了。以后clone远程仓库的时候用SSH协议地址一般是gitgithub.com:用户名/仓库名.git而不是HTTPS地址就再也不用输密码了。这块我踩过一个小坑SSH的配置文件里如果配了代理或者用了非默认的密钥路径会连不上。如果你日后遇到gitgithub.com: Permission denied (publickey)先用ssh -vT gitgithub.com看debug输出多半能找到原因。5.4 强制推送的代价很多人为了让远程跟本地保持一致会用git push -f也就是强制推送。这是很有用的操作但也很危险。强制推送意味着用本地历史覆盖远程历史如果团队里别人已经在远程上推了新提交push -f会直接把别人的提交冲掉。我见过因为这个出事的。一个同事解决冲突后用了push -f把另一个同事一天的工作直接覆盖没了。虽然后来用reflog找回来了但过程极其痛苦。**我的建议是能不用push -f就不用必须用的时候先跟团队确认并确保你清楚自己在干什么。**很多平台默认保护main分支不允许强制推送这是非常合理的设置。6. 工程化素养提交规范与协作工作流6.1 提交信息这么写才专业提交规范看起来是个“软技能”但在团队里特别重要。你回头看一个混乱的提交记录和清晰的提交记录心情完全不同。我这边强烈推荐一种约定式提交的写法每条提交信息用类型前缀开头类型含义示例feat新功能feat: 增加用户注册接口fix修复bugfix: 修复登录超时问题docs文档变更docs: 更新READMEstyle格式调整不影响逻辑style: 格式化代码refactor重构不新增功能也不修bugrefactor: 重构用户模块test添加或修改测试test: 增加接口测试用例chore构建工具、依赖等杂项chore: 升级依赖版本首次提交可以做主标题和正文的区分简单点的提交一行就够复杂的需求建议加正文描述背景和改动点。这样别人看commit log的时候不需要打开代码就能知道这次提交的意图排查问题的时候效率翻倍。6.2 适合团队的简单分支工作流分支策略不用搞得太复杂对多数团队来说一套简单的Git Flow精简版就够用main分支永远是稳定可发布的版本受保护不允许直接push。feature分支每个功能一个分支从最新的main拉出来开发完通过合并请求Pull Request / Merge Request合并回main。fix分支紧急修bug用同样走合并请求流程。这套工作流的好处是main分支永远稳定任何一次合并都经过审查出问题可以快速定位是哪个合并请求引入的。小团队哪怕只有两三个人我也建议走这个流程。麻烦是麻烦了一点但只要坚持项目质量会有明显提升。7. 日常高频命令与终端技巧7.1 高频命令速查表这份速查表是我自己这些年最常用的命令集合基本覆盖日常80%的操作git status # 查看当前状态 git log --oneline --graph # 图形化查看提交历史 git diff # 查看未暂存的改动 git diff --staged # 查看已暂存但未提交的改动 git stash # 暂存当前工作区改动让工作区干净 git stash pop # 恢复暂存的改动 git tag v1.0.0 # 给当前提交打标签 git remote -v # 查看远程仓库地址git stash这个命令我要单独说一下它的场景特别典型你正在feature分支开发一个功能改到一半突然需要切到另外一个分支修一个紧急bug。这时候直接切分支是不行的因为工作区有未提交的改动。你不想随便commit一个半成品也不想丢失改动git stash就是为此设计的。它把当前改动“存起来”让工作区回到干净状态你切到别的分支干完活再切回来git stash pop恢复改动继续开发。7.2 那些隐藏在GUI背后的命令你可能在用图形界面工具操作git某个时候会发现控制台输出一行奇怪的长命令看起来像这样git -c diff.mnemonicprefixfalse -c core.quotepathfalse --no-optional-locks status -sb这其实是图形界面工具比如某些GUI客户端在后台调用git命令行时附加的参数。-c keyvalue是让git临时使用某个配置项diff.mnemonicprefixfalse是要求diff输出不使用自定义前缀而用标准的a/b前缀core.quotepathfalse就是我们前面提到的中文路径正常显示设置--no-optional-locks则是告诉git在执行这个命令时不要去获取那些可选的锁避免跟正在进行的其他git操作冲突。理解了这条命令的含义你会发现一个规律很多GUI工具本质上是命令行git的包装。所以用GUI工具遇到疑难杂症的时候去读它生成的命令行日志往往能看出真正的问题。图形界面和命令行不是对立关系配合使用效率最高。8. 常见问题与报错排查实录8.1 “git不是内部或外部命令”与“无法识别为cmdlet”这是新手最常遇到的报错在Windows上尤为常见。你装完git后打开CMD或PowerShell输入git系统提示“不是内部或外部命令”或者一串红色的“无法将git项识别为cmdlet、函数、脚本文件或可运行程序的名称”本质上都是同一个问题系统在PATH环境变量里找不到git的可执行文件。排查分三步走。第一步确认你确实装了git可以到安装目录看看默认路径一般是C:\Program Files\Git或C:\Program Files (x86)\Git。第二步检查PATH环境变量里有没有包含C:\Program Files\Git\cmd。没包含就手动加进去。第三步修改完环境变量后一定要关闭终端重新打开环境变量的修改不会自动刷新到已经打开的终端。按照这个顺序查大概率能解决。顺便说个细节你安装git的时候选择“Git from the command line and also from 3rd-party software”安装器就会自动帮你把git加到PATH里。所以最省事的方式是重新跑一遍安装程序把那个选项选上。8.2 “fatal: not a git repository”是怎么回事这个报错的意思是“当前目录不是一个git仓库”。最常见的原因是你进入了一个不是git仓库的目录然后执行了git命令。比如你刚clone完一个项目还在父目录下就直接敲git命令就会报这个。解决思路也很直接确认当前目录是否是仓库目录用pwd查看当前位置用ls -la看看有没有.git目录。也有可能你创建了子目录但没有在子目录初始化仓库。记住git命令必须在仓库目录或其子目录里执行才有效。8.3 “login failed. check api token or gitlab version”这个报错常见于通过图形工具或API连接GitLab的时候。字面意思是登录失败请检查API token或GitLab版本。我遇到过的几种情况一是token过期或权限不足重新生成一个有足够权限的token二是GitLab版本过旧API接口跟工具不兼容需要升级服务端或更换工具三是网络问题导致连不上GitLab先确认网络连通性再排查别的。这个报错给我们的启发是认证层的问题要系统地排查先确认账号有权限再确认token没过期最后确认版本兼容性。一项一项试不要瞎猜。8.4 “git目录泄露”的风险提示这里要提示一个偏安全的问题就是“git目录泄露”。前面说了git会在项目根目录生成一个.git文件夹里面完整保存了所有提交历史。如果把git仓库所在目录直接作为网站根目录发布到服务器上或者配置文件没有拦截对.git目录的访问那么别人就可以通过URL去访问.git里的文件甚至把整个仓库的数据下载下来。这不是危言耸听业界有过不少事故。防护措施其实不复杂Web服务器配置里要明确禁止访问.git目录发布代码时不要直接把整个仓库复制到web根目录更重要的一点是不要轻易把包含敏感信息的文件提交进git仓库。密码、密钥、token这类东西一旦进了git历史就算后面删了历史记录里也找得到。所以常用做法是用.gitignore文件把这些内容排除掉或者用环境变量/密钥管理工具统一管理敏感信息。8.5 图形界面小乌龟、VSCode插件与其他Git GUI命令行熟了以后很多人仍然喜欢用图形界面这很正常图形界面在查看历史、对比改动、解决冲突的时候确实比命令行直观。Windows上我见过用“小乌龟”TortoiseGit的人不少它在资源管理器里右键就能操作胜在方便提交、拉取、切换分支都能点两下搞定。VSCode里内置的git功能也很实用左侧的源代码管理面板可以看改动、写提交信息、直接add和commit配合GitLens插件看代码行对应的提交历史体验很好。但我还是建议图形界面可以日常用命令行必须会。因为很多报错信息、复杂操作、应急恢复场景最终还是要回到命令行去处理。图形界面和命令行不是二选一的关系而是互为补充。9. 一些我踩过后的经验沉淀最后想分享几个可能不是所有教程都会讲、但我在实际使用中觉得很有用的经验。第一不要硬背命令。git命令是工具不是考试题。记不住就查用多了自然就记住了。真正重要的是理解git的模型工作区、暂存区、版本库、分支指针、远程跟踪分支。模型理解了命令忘了一半也能用逻辑推出来。第二多用别名提高效率。我自己的git配置里加了一堆常用别名比如git config --global alias.st status git config --global alias.cm commit git config --global alias.co checkout git config --global alias.br branch设置之后git st就等价于git status敲键盘的次数直接减半。你完全可以按自己的习惯配置一套别名长期下来省下的时间很可观。第三遇到搞不定的问题用git reflog。git reflog记录的是HEAD的所有移动历史包括被reset掉的那些。万一你误操作把分支搞没了去reflog里找一下之前的commit哈希再用git branch 分支名 哈希值就能恢复。这个命令是真·后悔药虽然希望你永远用不上但知道了遇到紧急情况就不慌。git这个东西初学的时候会觉得概念多、命令杂但一旦把核心模型和常用流程跑通它就会变成你开发中最得力的助手。代码写错了能回退方案走偏了能分叉团队协作有了秩序这就是我理解的git学习的全部意义。希望这篇内容能帮你少踩点坑走得更顺一些。
返回列表