Git这个工具,只要是写代码的人,早晚都得面对它。不管你是刚进公司的实习生,还是自己折腾开源项目的独立开发者,都绕不开这六个字母。今天这篇东西,我不打算长篇大论地讲Git的内部实现原理,那玩意见官方文档就行;我更想从实际干活的角度,把从安装、配置、日常提交、分支合并到远程协作、SSH认证失败排查这一整条链路给你捋明白。你可以把它当成一份能直接照着抄作业的操作手册,也可以当成一份避坑清单来用。
先说清楚这篇到底覆盖什么:Git是什么、为什么要用;Windows和Mac上怎么装;装完之后必做的身份配置;日常最常用的add、commit、status、log、diff这些命令怎么配合;分支到底怎么建、怎么切、怎么合并、冲突怎么解;远程仓库的clone、push、pull、fetch之间有什么区别;以及很多人第一个月就会被卡住的SSH认证失败到底怎么排查。看完这篇文章,你不需要背任何命令,只需要理解每个动作在解决什么问题,剩下的交给肌肉记忆。
1. 先搞清楚Git到底在解决什么问题
1.1 Git是版本管理工具,不是网盘
很多人第一次接触Git,容易把它跟“网盘”“同步盘”搞混。网盘的逻辑是我把文件传上去,你在另一台设备下载下来,两边数据尽量保持一致。Git的逻辑完全不同,它的核心是版本快照——你每提交一次,Git就把当前所有文件的状态拍一张“照片”存下来,这张照片里不仅包含文件内容,还包含这次提交的作者、时间、说明信息,以及和上一张照片之间的前后关系。
这个设计解决了一个很实际的痛点:你在改代码、写文档、做设计稿的时候,经常会遇到“我把上一版改坏了,得退回之前那个能用的版本”的情况。没有Git的时候,大家惯用的做法是手动复制一份带上日期后缀的文件夹:项目_最终版、项目_真最终版、项目_绝对不改了。这种命名方式短期内能忍,一旦项目超过两周、参与的人超过两个,你根本记不住哪个是哪版,更说不清楚谁在什么时候改了哪一行。
Git把这一切变成了结构化的记录。你每一次提交都有一个唯一的版本号(哈希值),可以随时回退到任何一次提交,可以对比任意两个版本之间到底改了什么,还可以在同一个项目里并行开多条“时间线”,互不干扰。这就是它和网盘最本质的区别:网盘关注“现在有什么”,Git关注的是“怎么一步一步变成现在这样的”。
1.2 使用Git前后,开发体验差在哪
我举一个特别常见的场景。你在一个项目里同时要改两个功能,一个是紧急的线上Bug,一个是下周才需要的新特性。没有Git的时候,你只能在同一个代码目录里改来改去,经常出现“修Bug修到一半,被叫去写新功能,改完新功能回来发现自己忘了Bug改到哪儿了”的窘境。
有Git之后,你先在新特性这条分支(branch)上写代码,写到一半要修Bug,提交或暂存当前进度,切回主分支,新建一条修Bug的分支,修完合并回去,再切回新特性分支继续写。所有代码都待在它们该待的地方,互不干扰。这种感觉,用一次就回不去了。
再说团队协作。几个人同时在一个项目里干活,如果没有版本管理,最常见的死法就是“互相覆盖文件”:A同学改了登录页,B同学也改了登录页,最后上传的时候看运气,谁后上传谁赢。Git通过“分支+合并”机制,接受多人同时修改,然后在你合并代码的时候,明确指出哪些地方产生了冲突,由人工来决定每一处冲突保留谁的内容。这个机制本身就是现代软件工程能够多人并行开发的基础。
2. 装环境配身份:从零开始把Git跑起来
2.1 Windows和macOS下的安装方式
Windows下最简单的方式是直接下载官方安装包。官网下载页面提供64位和32位两个版本,现在绝大多数机器都是64位,选带“64-bit”字样的那个就行。安装过程基本全程Next,但有几个选项值得注意:安装到“Select Components”这一步时,建议勾选“Add a Git Bash Profile to Windows Terminal”(如果选项里能看到),这样后续可以用终端工具直接打开Git Bash;在“Choosing the default editor”这一步,新手建议保持默认的Vim不要换,哪怕你觉得Vim反人类,等以后熟悉了再说,因为很多教程和命令行的默认操作都假设它没被动过;在“Adjusting your PATH environment”这一步,务必保持默认选项“Git from the command line and also from 3rd-party software”,这个选项保证你在CMD和PowerShell里也能直接用git命令。
装完之后检查是否成功,打开任意终端,输入:
git --version能输出版本号类似git version 2.47.1.windows.1,就说明安装成功了。这一步虽然简单,但很多人装完不知道去哪验证,以为装完必须看到桌面快捷方式才算成功,其实Git是没有图形界面的,它的快捷方式是右键菜单里的“Git Bash Here”。
macOS的情况要取决于你的机器状态。最省事的方式是安装Xcode Command Line Tools,在终端里输入:
xcode-select --install系统会弹窗引导安装,装完之后Git通常就已经可用了。如果你需要更新版本的Git,可以考虑用Homebrew安装:brew install git。这里要留意一个细节,macOS自带的git版本可能比较老,跟你在项目里用到的某些Git特性不兼容,所以如果你靠Homebrew装了新版,要注意PATH优先级,确保which git指向的是Homebrew的版本,而不是系统的旧版。
还有一个容易忽视的大坑:很多Windows用户装完Git之后不会用Git Bash,反而跑到CMD里去敲Linux风格的命令。比如mkdir -p a/b这种命令在CMD里是跑不通的。我的建议是,Windows用户凡是涉及Git操作,一律右键打开Git Bash Here,它模拟了Linux终端环境,几乎所有教程里的命令都能直接跑。
2.2 安装完必须先配置身份
Git的每一次提交都会记录作者信息,这个信息不是系统自动从你的电脑里读取的,而是来自一个全局配置文件。如果不配置,提交时会报错或者使用占位的错误信息。配置方法很简单:
git config --global user.name "你的名字" git config --global user.email "你的邮箱"这里有几个值得展开的点。第一,--global参数表示当前操作系统用户范围内的全局配置,通常一台开发机上所有项目的作者信息都是同一个,所以用global是合理的。如果某个特殊项目要用不同的名字和邮箱,可以在项目目录里不加--global单独设置,那个项目的配置会覆盖全局配置。
第二,邮箱不一定要用真实邮箱,但建议使用你在代码托管平台注册的邮箱。因为很多平台就是靠email跟你的账号关联的,如果你的提交邮箱跟平台账号不一致,提交记录虽然能推上去,但头像和用户名不会正确显示,甚至会被算成另一个人的贡献。这个问题在团队里经常被忽略,最后统计KPI的时候才发现一堆提交没落到自己头上。
配置完之后,你可以用git config --list查看所有配置项,确认没问题再开始建仓库。
2.3 配置SSH密钥,免掉每次输入密码的麻烦
日常操作远程仓库有HTTPS和SSH两种协议。HTTPS每次推拉代码都要输入账号密码(或者在凭据管理器里记住密码),SSH则通过公钥私钥配对实现免密认证。很多新手在第一次面对远程仓库时直接选HTTPS,结果每次push都输密码,输到崩溃;还有一批人想配SSH,结果一上来就遇到“SSH认证失败”,直接卡在第一关。
配置SSH的标准流程是这样的。先检查本机是否已有SSH密钥:
ls -al ~/.ssh如果目录下有id_rsa和id_rsa.pub这两个文件,说明你之前生成过密钥,可以跳过生成步骤;如果没有,执行:
ssh-keygen -t rsa -b 4096 -C "你的邮箱"一路回车即可,默认会在~/.ssh目录下生成一对密钥。id_rsa.pub是公钥,可以公开,把它的内容复制出来,粘贴到你使用的代码托管平台的“SSH Keys”设置页面里。id_rsa是私钥,绝对不能泄露给任何人,它相当于你访问远程仓库的身份证。
验证配置是否成功,在Git Bash里执行:
ssh -T git@github.com如果看到类似“Hi xxx! You've successfully authenticated”的话,说明SSH链路已经通了。这里要特别强调一点:SSH认证连接的是平台,不是具体项目仓库,所以你只需要成功认证一次,后续访问该平台下所有仓库都不需要再输入密码。
还有一类常见情况是公司自建的GitLab,端口可能不是默认的22,需要在~/.ssh/config里单独配置Host和Port,这个我们后面在问题排查部分展开。
3. 日常高频命令:从初始化仓库到看懂历史记录
3.1 创建一个新仓库并完成第一次提交
有了Git之后,你随时可以把任意一个本地文件夹变成Git仓库。在项目根目录执行:
git init执行之后该目录下会多出一个隐藏的.git文件夹,这个文件夹装着所有版本历史和配置信息,属于Git的“数据库”。这个时刻你可能会好奇,我怎么知道Git现在到底处于什么状态?用git status:
git status它会告诉你当前分支名(默认通常是master或main)、有哪些文件还没被跟踪、有哪些文件修改了还没提交。新手最常见的困惑是:我明明往项目里放了个文件,怎么git status说它是“Untracked”?这个状态的意思是Git发现了这个文件,但还没决定要不要把它纳入版本管理。你得先告诉Git“我要管这个文件”,执行:
git add 文件名再执行git status,文件从“Untracked”变成了“Changes to be committed”,意思是它已经被放进了“暂存区”。这时候就可以提交了:
git commit -m "初始化项目,添加了README"到这里,你的项目就有了第一个版本快照。很多人不理解为什么要分“add”和“commit”两步,其实这个设计非常实用。你可以把add理解为“挑菜”——从一堆改动里选出你这次想记录的内容;把commit理解为“拍照”——把选好的内容打包成一条不可变的历史记录。这一步拆开之后,你可以同一个文件改两处,只提交其中一处,这在复杂的工作流里非常关键。
3.2 用生活化类比理解工作区、暂存区、版本库
如果不用术语,可以这样想:工作区就是你的编辑器里正在编辑的文件;暂存区是一个“待提交清单”,你点一下git add,就相当于在清单上打了个勾;版本库就是你Git仓库的历史档案柜,每commit一次,就把当前清单上的内容封锁成一个档案存进去,永不可变。
这三个区域的转换是理解Git的命门。在工作中你会反复遇到的情况是:改了一堆文件,看了git status,发现有些改动想提交,有些改动还不想提交,这时git add就提供了精准控制能力——只把想提交的文件加入暂存区,其他改动留在工作区继续“挂机”。
想撤销误add的文件怎么办?
git reset HEAD 文件名想撤销工作区里某个文件的修改、恢复到最近一次提交的状态怎么办?
git checkout -- 文件名这两个命令属于“后悔药”,但要注意它们都不可轻易乱用。尤其git checkout -- 文件名会直接丢弃工作区的修改,而且改动不会进回收站,找不回来的。如果你不确定那些改动是否还要,建议先git stash暂存起来,而不是直接撤销。
3.3 查看历史与对比差异:status、log、diff三兄弟
三个命令分别解决三个问题。git status回答“现在处于什么状态”,git log回答“过去发生了什么”,git diff回答“到底改了什么”。
git log的输出初看很吓人,一长串哈希值加提交信息:
git log --oneline这个命令把每次提交压缩成一行,只显示简短的哈希前缀和提交说明,这是日常查看历史最常用的方式。如果你觉得提交历史太多太乱,可以加参数过滤,比如git log --oneline -5只看最近5条,git log --oneline --author="你的名字"只看某人的提交。
git diff是排查问题的利器。它默认比较“工作区”和“暂存区”之间的差异,说白了就是:你改了但还没add的内容,具体改了哪些行。执行:
git diff输出里带-号的是删除或修改前的行,带+号的是新增或修改后的行。如果你已经git add了,想看看暂存区跟最近一次提交的差异,用git diff --cached。这个命令在你准备提交之前一定要养成习惯跑一遍,能避免把调试用的临时代码提交到正式仓库。
4. 分支管理:并行开发的基石
4.1 分支是什么,为什么这么设计
分支(branch)大概是Git区别于老式版本控制系统的标志性设计。你可以这样理解:主分支是一条主干道,分支是从主干道上分出来的岔路。你在岔路上怎么折腾都不影响主干道,折腾完了可以把岔路合并回主干道,也可以直接丢在一边不管。
创建分支和切换分支是两个动作:
git branch feature-login git checkout feature-login第一个命令创建分支但还不切换,第二个命令切换过去。Git后来提供了一条合成命令:
git checkout -b feature-login它的意思是“创建并切换”,日常使用频率极高。在老版本里,checkout干的活特别杂,既能切分支又能撤销文件,后来Git团队推出了语义更清晰的switch命令:
git switch -c feature-login功能跟checkout -b一样。现在新项目里推荐用switch来处理分支切换,语义清楚,不容易跟撤销文件搞混。
分支名取什么也很讲究。我见过的优秀习惯是用类型前缀:feature/xxx表示新功能,fix/xxx表示修Bug,docs/xxx表示文档更新。这个命名习惯在后来的协作中会大大降低沟通成本,你一看分支名就知道这条分支是干嘛的。
4.2 合并分支的两种思路:merge和rebase
分支开发完后要把成果带回主分支,最常见的是merge(合并)。切回主分支后执行:
git merge feature-loginGit会把两个分支的修改合并到一起。如果两边改的是不同文件,Git会智能地自动合并,不需要你做任何事;如果两边改的是同一个文件的同一行,就会产生合并冲突,需要手动处理。
这里新手常遇到一个心理坎:明明只是把分支合并到主分支,为什么git log里出现了一条“Merge branch 'xxx'”的记录?这是merge的正常且合理的表现——它忠实记录了“在什么时间点把哪条分支并了进来”这个事实。有强迫症的人会觉得历史不够线性整洁,于是想用rebase来让历史像一条直线。
rebase的原理是把当前分支的提交摘下来,接到另一个分支的最新提交之后,相当于“重新放一遍”你的提交。比如你在feature分支上有三个提交,主分支在这期间新增了一个提交,rebase会把你的三个提交按顺序接到主分支最新提交的后面,看起来像你是在主分支最新状态下依次做了三个修改,历史非常线性。
git checkout feature-login git rebase main但rebase有一个危险点:如果这个分支是多人协作共用的,已经在远程被别人的代码依赖了,你rebase会改变提交历史(因为提交的哈希变了),推送出去会引发一堆混乱。我的原则很简单:还没推到远程的本地分支,随便rebase;已经推到远程和别人协作的分支,老老实实用merge。
4.3 合并冲突的真实现场与解决步骤
冲突是每个用Git的人迟早要面对的,它不是错误,而是Git在明确告诉你“我没法替你决定,需要你出面裁决”。冲突发生时,git status会列出哪些文件是“both modified”状态。打开冲突文件,你会看到类似这样的标记:
<<<<<<< HEAD 这是当前分支的代码 ======= 这是被合并分支的代码 >>>>>>> feature-login这个标记不是代码,是冲突的提示。<<<<<<<到=======之间是当前分支的内容,=======到>>>>>>>之间是你要合入分支的内容。你需要手动决定保留哪个、删除哪个,或者混合修改。处理完之后删掉那些标记行,然后把这个文件git add,再git commit,冲突就正式解决了。
我在处理冲突时有个经验很管用:先看几处冲突的上下文,不要急着逐个改。有时候多个冲突分布在同一个文件的逻辑关联位置,单个看可能觉得两边都有道理,但整体看你会发现一个方案明显是对的。如果冲突数量巨大,优先用图形化工具(比如VS Code的Source Control面板、IDEA的Merge窗口),它们会把左右两边的内容并排展示,比在编辑器里看标记符号直观得多。
还有一个实战建议:合并前先拉一下最新代码。如果你在主分支上执行merge之前,主分支本身已经落后远端,那合并出来的结果大概率会产生莫名其妙的冲突,甚至引入别人的改动问题。先把主分支更新到跟远端一致,再合并本地特性分支,冲突范围会小很多。
5. 远程仓库协作:代码如何与他人同步
5.1 clone、push、pull、fetch到底什么区别
本地仓库玩熟之后,就要面对远程仓库了。远程仓库的本质是一台不断线的服务器,它存着所有版本历史和当前代码,大家各自往它上面“取”或“交”代码。
clone是把远程仓库完整复制到本地。一个经典问题:“我要怎么把别人的项目拿到本地?”答案是git clone 仓库地址。执行后,本地会生成一个与远程同名的文件夹,而且这个文件夹里自动配置好了远程仓库地址,可以直接push、pull。如果只需要克隆某个分支,可以加-b 分支名参数。
push是把本地提交推送到远程。注意,如果你本地有3个提交,远程一个都没有,执行git push后远程会依次出现这3个提交。推送失败最常见的原因是远程有本地没有的提交,Git会拒收,提示你“Your branch is ahead of...”。这时候你不能硬推,得先把远程的最新提交拉下来,或者用git pull --rebase把本地提交叠加到远程最新之后,再推上去。
pull是fetch + merge的组合动作。很多人搞不清它和fetch的区别,其实fetch只是“下载远程的最新提交到本地”,但不会自动修改你正在工作的文件;pull则会把这些提交合并到当前分支,直接改变工作区。对新手来说,直接理解成“pull = 获取远端最新代码并合到当前分支”就够了。想预览远程有没有新提交、但还不想动自己的代码,就执行git fetch。
fetch和pull的选择,我在实操里的建议是:单人开发时直接git pull最省心;在多人并行开发、你手头有一堆未提交改动时,先git fetch看看远程有哪些新提交,再判断是merge还是rebase,更安全。
5.2 完整协作场景演练:新成员拉取项目并提交代码
假设你刚加入一个项目,同事给了你一个仓库地址。完整流程是:
- 克隆仓库:
git clone git@code.platform.com:team/project.git - 进入项目目录:
cd project - 查看当前分支:
git branch -a(看看有哪些远程分支) - 基于远程分支创建自己的本地分支:
git checkout -b feature/xxx origin/xxx(注意新分支要关联远程分支,之后push才知道推到哪) - 开发完提交:
git add .,git commit -m "完成了xxx功能" - 推送:
git push -u origin feature/xxx(-u建立远程追踪关系,第一次推送后以后直接git push就行)
很多人第一次操作时会漏掉第4步里关联远程分支这个环节,结果git push之后提示git push --set-upstream origin feature/xxx。这是Git在告诉你“我暂时不知道你要推到远程哪条分支”,按提示执行--set-upstream即可,不需要慌。
还有一个小细节:在提交前养成看git status和git diff的习惯,确保添加的就是你想提交的内容,别把本地调试用的垃圾文件一起推上去。团队协作的底线是:不要把本地私有信息提交上去。比如配置文件里含数据库密码、密钥,这类内容一旦推到远程,即使后续删掉,也会留存于Git历史里,重新修复成本极高。这个问题严重的时候甚至需要改写历史,非常麻烦。
5.3 主分支命名与常见协作模型
远程仓库的主分支,老项目通常叫master,新项目很多改叫main。创建仓库的时候平台一般默认帮你建好主分支了,本地git init时则默认是master,如果你希望改成main:
git branch -M main-M是强制改名的意思,大写M表示“不管目标分支存不存在,直接改”。Git允许本地主分支名和远程不一致,但团队协作时统一命名能省掉很多不必要的困扰。
常见的协作模型有三种。最简单的是单主分支模型,所有人都在main上直接提交,适合一两人的小项目;稍微规范一点的是功能分支模型,每个人开一条feature/xxx分支,完成后合回main,适合三五个人的项目;再正式一点的是Git Flow模型,维护main、develop、release、hotfix等多条常设分支,适合发布节奏严格的中大型项目。新手不用一上来就背模型,先掌握“主分支+功能分支”就够了,等你真的到了项目需要的阶段自然而然会去学。
6. 高频报错与排查实战:别让第一个月卡死在环境上
6.1 SSH认证失败:最常见的拦路虎
“ssh认证失败 git”在热搜词里挂着不是没道理的,我见过太多人在配好密钥之后被这个报错折磨。先搞清楚这个错误出现的两种场景:一是clone或push时报错Permission denied (publickey),二是ssh -T git@xxxx时直接显示Permission denied。
排查思路,按以下顺序走:
第一步,确认本机是否生成了密钥。执行ls -al ~/.ssh,看有没有id_rsa.pub。没有就重新生成,生成时注意它会问你“Enter file in which to save the key”,直接回车使用默认路径。
第二步,确认公钥是否已添加到托管平台。复制id_rsa.pub的全文内容,不要多复制换行符,粘贴到平台个人设置里的SSH Keys页面。有些平台要求标题,随便起个能标识设备的名字即可。
第三步,确认本机SSH正在使用哪个私钥。执行ssh -vT git@xxxx.com(加-v参数进入调试模式),它会打印详细连接过程,你可以从日志里看到它尝试了哪个私钥文件、有没有被接受。如果它尝试的私钥跟你实际在用的私钥不是同一个,需要在~/.ssh/config里指定:
Host code.platform.com HostName code.platform.com User git IdentityFile ~/.ssh/id_rsa Port 22第四步,检查系统时间和密钥权限。这个问题比较少但真实存在:电脑系统时间不正导致SSH证书验证失败;~/.ssh密钥文件的权限太开放也会被拒绝,特别是Windows上配置多用户时,建议对私钥文件执行chmod 600 ~/.ssh/id_rsa、对目录执行chmod 700 ~/.ssh。
我在这个环节还有一个建议:办公环境下公司的GitLab可能配了自定义端口,比如2222,你在clone地址里会看到ssh://git@code.company.com:2222/group/project.git这种形式。这种地址如果直接配SSH,默认端口匹配不上就会失败,必须在~/.ssh/config里把Port写成2222。这是很多人反复失败又找不到原因的高频坑。
6.2 其他高频报错速查
fatal: Not a git repository:在不是Git仓库的目录里执行了Git命令。如果你确实在项目目录里,可能是.git文件夹被删了,或者你不在项目根目录而在某个子文件夹但该文件夹没有被Git跟踪(通常子目录在Git仓库内是能用的)。最简单的验证方式是git rev-parse --git-dir,它能输出Git仓库的路径,如果报错说明当前不在仓库内。
Please tell me who you are:忘了配user.name和user.email,回到第2.2节配置全局身份即可。注意,如果这个项目是用系统用户安装的Git,而你的终端是管理员权限开的,配置可能会写进不同的用户目录,导致“我明明配了还是报错”,这时候用git config --list确认配置在哪个层级生效。
fatal: refusing to merge unrelated histories:两个仓库没有共同的提交祖先,最常见于本地新建项目后用git remote add origin连接了远程仓库,然后直接git pull,Git默认拒绝合并这种没有关联的历史。如果你明确知道两边内容一致或者确认可以合并,命令里加--allow-unrelated-histories:
git pull origin main --allow-unrelated-histories我一般不推荐随手用这个参数,它会让Git把两边各自的历史拼接起来,可能产生大量冲突,先确认你的操作意图再使用。
error: failed to push some refs to ...:远程有本地没有的新提交。不要用git push -f强推解决,在团队项目里强制推送会覆盖其他人的提交,属于高危操作。正确做法是git pull --rebase把远程新提交拉下来,让本地提交叠加到最上方,然后再push。
warning: LF will be replaced by CRLF:Windows和Linux换行符差异导致的警告。这类警告通常不会阻断操作,但如果团队跨平台协作,建议在项目根目录放一个.gitattributes文件统一行尾规则,避免后续出现“明明没改内容却显示整文件都有改动”的诡异情况。
6.3 几个能提升体验的实测小技巧
git stash是移动的后悔药。你在一半的工作区改动还没写完时,需要紧急切到另一分支处理事情,直接切分支会带着未提交的改动过去,容易混乱。执行git stash可以把当前改动临时收起来,工作区回到干净状态;切分支做完事回来,执行git stash pop把改动恢复。这个命令我几乎每个星期都用,属于投入产出比极高的操作。
配置常用别名。给高频命令起短名字能显著提升效率,我目前最常用的两组:git config --global alias.lg "log --oneline --graph --all",用一个git lg就能查看图形化的提交历史;git config --global alias.co checkout,把checkout缩成co。这类配置纯属个人习惯,但在频繁操作时非常省时间。
提交信息用动词开头。写git commit -m "fix: 修复登录超时问题"而不是git commit -m "修复了登录超时问题"。前者描述动作,后者描述状态,很多团队规范也会要求提交信息遵循特定格式,养成好习惯以后去任何团队都受用。
遇到不确定的命令时先查帮助。git help 命令名会打开本地完整文档,git 命令名 -h会输出简版帮助。很多人觉得出了报错才去搜索,其实先把常用命令的-h看一遍,能减少大半的无效搜索时间。
我自己刚接触Git那阵子,栽得最多的就是SSH认证和合并冲突这两件事。SSH配好了之后推送成功率提升,心里踏实一大截;合并冲突处理过两三次之后,再看到那些<<<<<<<标记就不会慌,反而会觉得“哦,Git又在明确告诉我到底哪儿有分歧了”。Git这个东西,其实不复杂,它的每一个设计都在解决一个真实世界里的协作或者版本管理痛点,你顺着“这个命令在解决什么问题”这个思路去学,就没什么难的了。把上面这些基础练熟,日常开发已经够用;剩下的高级功能,等真遇到特定场景再去查,效率会高很多。