刚从 SVN 或者干脆是“用U盘拷代码”时代转型过来的朋友,通常接触 Git 的第一周都会有点懵。网上教程铺天盖地,但要么只讲命令不解释为什么,要么一上来就扔出一堆分支模型把人绕晕。这篇东西不整虚的,就围绕“git本地基础操作”这条主线,从安装、配置、提交、撤销、分支到关联远程仓库,把日常开发里最常用、也最容易踩坑的环节捋一遍。你照着敲,基本就能应付日常工作流了。
1. 安装与初始配置:先把“你是谁”交代清楚
1.1 各系统下的安装方式
Windows 用户最简单,去 Git 官网下载安装包,一路 Next 就行。这里有几个选项需要注意一下:
- Git Bash:强烈建议保留,它模拟了 Linux 终端环境,后续很多命令操作在 Git Bash 里跑会更顺手,也避开了 Windows CMD 对单引号、斜杠等字符的恶心处理。
- 默认编辑器:默认选 Vim 就行,虽然初次进 Vim 会被卡住(按
i编辑,按Esc再输入:wq保存退出),但总比你系统里装了某个奇怪编辑器导致 Git 无法调用要稳定。 - PATH 环境:选择 “Git from the command line and also from 3rd-party software”,确保你在任何终端窗口都能敲
git命令。
macOS 用户如果装了 Homebrew,直接brew install git,没装的话去官网下载 pkg 包也很方便。Linux 用户更不用说,apt install git或yum install git一条命令的事。装完验证一下:
git --version能输出版本号,说明命令已经可用。之前在热搜里看到有人反馈“git 无法将‘git’项识别为 cmdlet、函数、脚本文件或可运行程序的名称”,十有八九是 Windows 下没勾选 PATH 选项,或者装完忘了重开终端窗口——环境变量不是实时刷新的,必须新开一个窗口才生效。
1.2 全局配置:不配这个,你连提交都做不了
装完先别急着建仓库,马上配置你的身份信息。这是新手最容易跳过的一步,然后第一次git commit就会报错:
Please tell me who you are.配置其实就两行:
git config --global user.name "你的名字" git config --global user.email "你的邮箱"有人不理解为什么提交代码要绑身份信息。道理很简单:Git 记录的每一次改动,都需要知道“谁在什么时间改了什么”。这个信息会永久写入提交历史里。工作场景下,建议直接用公司邮箱,这样代码评审、追溯责任的时候能一眼认出是你。如果在家用自己的电脑玩个人项目,也可以单独配置。注意--global是全局生效,要是某几个项目想用不同身份,可以在项目目录下去掉--global重新设置,项目级配置会覆盖全局配置。
顺便说一句,很多初学者会用git config --list看到一堆配置项,里面有core.autocrlf=true之类的东西,看不懂就先别动,默认就够用。等哪天你在 Windows 和 Linux 之间来回切代码,发现每一行末尾都有^M这种奇怪符号,再来研究 autocrlf 也来得及。
2. 创建仓库与第一次提交:理解“三个区域”是关键
2.1 初始化仓库
用git init把一个普通文件夹变成仓库:
cd my-project git init执行完这步,项目目录下会出现一个隐藏的.git文件夹。所有版本记录、分支信息都存在这里面。这个文件夹千万别手贱去删,删了等于这个仓库的所有历史记录全没了。建议在文件管理器里把“显示隐藏文件”打开,方便你随时看到它的存在。
如果你是从零开始一个新项目,也可以跳过git init,直接用git clone把远程仓库拉到本地,这样本地会自动初始化好。
2.2 工作区、暂存区、版本库
弄懂这三个区域,Git 的地基就算打牢了。我习惯用一个生活化的比喻来解释:
- 工作区:你正在编辑的文件夹,相当于你的“草稿纸”。
- 暂存区:存放你准备提交的改动清单,相当于你把草稿里有用的部分挑出来,放进一个“待发货的快递盒”。
- 版本库:Git 存储所有提交记录的地方,相当于“已经签收发货的包裹记录档案”。
日常流程就是:改代码(草稿纸)→git add把改动的文件放进暂存区(装快递盒)→git commit把这些改动固化成一个版本存档(签收归档)。
2.3 第一次提交的完整操作
假设你新建了一个index.html,想把它加入版本管理:
# 查看当前状态 git status # 把文件添加到暂存区 git add index.html # 再查看状态,这时文件应该在 "Changes to be committed" 下面 git status # 提交,-m 后面是提交说明 git commit -m "添加首页文件"git status是你整个使用过程中敲得最频繁的命令。红颜色显示的是没被追踪或改动了但还没暂存的文件,绿颜色显示的是已经放进暂存区的文件。每次提交前养成先看git status的习惯,能有效避免误提交。
如果项目里有一堆文件,想全部添加,可以用:
git add .那个点表示“当前目录下所有改动”,相当方便。但这里有个坑:如果你不小心把node_modules、target、.idea这类依赖或 IDE 配置文件也加进来了,仓库会变得又脏又大。正确做法是提前写好.gitignore文件,把不需要版本控制的路径排除掉:
node_modules/ target/ .idea/ *.log.gitignore支持通配符和目录匹配,写完提交一次,之后git add .就会自动跳过这些路径。
2.4 提交信息怎么写
git commit -m "fix: 修复登录页按钮点击无响应"和git commit -m "修改"的差距,等到你三个月后回来看历史记录的时候就体现出来了。不用过度设计,但至少遵循一个基本格式:类型 + 简述。
feat:新功能fix:修复BUGdocs:文档变更style:格式调整refactor:重构
比如feat: 新增订单导出功能就比修改了一些东西让人省心无数倍。这个习惯越早养成越好,别问我怎么知道的,翻自己半年前写的“修改”提交记录时,那种绝望感你不想体验。
3. 撤销与修正:Git 给了你后悔药,但要分清“药效”范围
3.1 文件改乱了想还原
辛苦改了半天的代码,发现思路错了,想回到上次提交的状态:
git checkout -- index.html这个命令的含义是:用版本库里最新一次提交的内容覆盖工作区的文件,你工作区里对这个文件做的所有改动都会被丢掉,且无法找回。用之前务必三思,最好的确认方式是先git status看一下这个文件确实有改动,再想想这些改动是否真的不要了。
新版 Git(2.23+)推荐用git restore替代 checkout 做这件事:
git restore index.html作用完全一样,只是语义更清晰。我个人的习惯是,如果文件改动比较复杂,我会先备份一份到别处再执行还原,小心驶得万年船。
3.2 暂存错了,想取消暂存
有时候git add手滑把不相关的文件加进来了,但文件改动还没丢,只想把它从暂存区拿出来:
git reset HEAD index.html新版同样有对应的语义化命令:
git restore --staged index.html执行完再看git status,这个文件会回到红色的“未暂存”状态,工作区里的内容原封不动。这个操作很安全,放心用。
3.3 提交信息写错了,用 amend 救急
热搜词里有“git commit --amend怎么使用”,这说明被提交信息折磨过的人真不少。--amend的作用是修改最近一次提交的提交信息:
git commit --amend -m "正确的提交信息"一个容易被忽略的用法是,它还能把新的改动补进上一次提交里。比如你刚提交完,发现漏了一个文件没加进去:
git add 漏掉的文件 git commit --amend -m "还是原来的提交信息,但内容补全了"这个操作的结果是:你不必为了一个漏网的小文件额外生成一条“补充提交”记录,整个提交历史看起来干净利落。但必须注意,amend会改变提交的哈希值,仅适用于还没推送到远程仓库的提交。如果已经把 commit 推给了别人,再用 amend 重写历史,会让同事那儿的仓库历史和你这边对不上,后续 pull 会相当痛苦。
在本地开发阶段的提交,尽情用;一旦进了协作流程、已经 push 的分支,绝对别碰 amend 或者后面会提到的 reset,这是铁律。
3.4 彻底回退到某个历史版本
如果不止是修提交信息,而是想撤回提交本身,把代码状态还原到某个历史节点,用:
git log --oneline这个命令列出的列表里,每行开头就是提交的哈希值缩写。找到你想回退到的那个提交 ID,然后:
git reset --hard a1b2c3d--hard是最彻底的:工作区、暂存区、版本库全部回到指定提交的状态,指定提交之后的所有本地改动全部灰飞烟灭。使用前一定确认这确实是你想要的。相对温和的git reset --soft只回退版本库指针,暂存区和工作区还保留着文件状态,适合“提交错了但代码还想留”的场景。
不过日常开发里我其实很少建议新手用 reset,特别是在分支上作业时。更稳妥的做法是基于误操作的提交新建一个反向提交,即git revert,但这就引出分支和协作的概念了,下一节慢慢讲。
4. 分支管理与合并:这个才是 Git 的真正灵魂
4.1 为什么要用分支
刚上手的人可能会觉得“我就一个人写代码,要分支干嘛?”但分支的意义不在于多人协作,而在于隔离风险。你在main分支上写项目,突然有个新想法想试试,或者要临时修一个线上 bug,如果直接在主分支上动手动脚,项目随时可能被改坏。
开一个分支,相当于从当前提交节点分出一条独立的“平行时间线”,你在不影响主干的前提下随便折腾,改坏了直接丢弃分支也没事。等验证通过,再把这条时间线并回主干。
4.2 常用分支命令
# 列出所有分支,当前所在分支前面会有 * 标记 git branch # 创建新分支 git branch dev # 切换到新分支 git checkout dev # 创建并切换,一条命令搞定(最常用) git checkout -b feature/login # 新版更语义化的方式 git switch -c feature/login热搜里的git分支合并指的就是把一条分支的改动合到另一条分支。假设你人在main分支,想把feature/login的成果合并过来:
git checkout main git merge feature/login合并成功后,feature/login分支就没啥用了,可以删掉:
git branch -d feature/login4.3 合并的本质:fast-forward 与真实合并
如果main分支在你拉出feature/login之后一直没动过,合并会走fast-forward模式——Git 直接把 main 的指针挪到 feature 分支最新的提交上,历史是一条直线,非常干净。
但如果 main 在你开发期间也有新提交,两条分支从“分叉点”开始各自前进了,Git 就没办法简单移动指针,它会发起一个“三方合并”:把两个分支的最新状态和它们的公共祖先进行比较,生成一个新的合并提交。这种合并会在历史里多出一个 “Merge branch ‘feature/login’” 的提交记录,完全正常,别慌。
4.4 合并冲突:最吓人但最该面对的事
凡是两个人改了同一个文件的同一处地方,或者删改名文件,合并时 Git 就会不知所措,进入冲突状态。这时候git status会显示 "both modified" 之类的标记,冲突文件里会出现一段内容:
<<<<<<< HEAD 这是 main 分支上的版本 ======= 这是 feature/login 分支上的版本 >>>>>>> feature/login<<<<<<< HEAD和=======之间的是当前分支的内容,=======和>>>>>>>之间的是要合并进来的分支内容。Git 不会替你决定要哪个,只能人肉判断,把不要的那部分删掉,保留要的,最后把<<<<<<<、=======、>>>>>>>三行也删干净。然后:
git add 冲突文件 git commit这里不需要再带-m,Git 会为你生成一条合并提交信息,默认文本就是 “Merge branch…”,直接保存退出就行。
新手第一次遇到合并冲突大概率手忙脚乱,我教你一个保命技巧:先 Ctrl+S 保存所有编辑器里的文件,再把冲突标记完整截图存到聊天记录里,然后一条一条处理。只要冲突文件不是上百行级别,通常几分钟就能解决。千万别在冲突状态下提交,那样会把<<<<<<<这种残留符号一起提交进去,污染历史仓库。
4.5 分支合并实战套路
日常工作里,我推荐“先合并再提交”这个流程,顺序很重要:
- 切到主干:
git checkout main - 拉取最新主干:
git pull origin main(会关联远程仓库,下一节细说) - 把功能分支合过来:
git merge feature/login - 解决冲突后提交,推送远程:
git push
这能最大程度减少你本地分支和远程主干之间的“代沟”,避免最后 push 时被远程拒绝。
5. 关联远程仓库与推送拉取:本地只是开始
5.1 添加远程地址与首次推送
本地操作再熟练,最终目标还是把代码推到远程,GitHub、Gitee、GitLab 都行。远程仓库建好之后,拿到 HTTPS 或 SSH 地址,在本地关联:
git remote add origin https://gitee.com/你的用户名/项目名.gitorigin是远程仓库的默认别名,约定俗成就这么叫。然后推送本地 main 分支上去:
git push -u origin main-u参数表示“记住这条推送关系”,之后直接敲git push就能往这个分支推,不用每次追加origin main。
如果你不是从头初始化,而是想把远程已有项目拉下来,在本地操作:
git clone https://gitee.com/你的用户名/项目名.git这个命令会自动创建本地仓库、关联远程、切换到默认分支。日常用得最多的场景其实就是 clone + commit + push 三步循环,并不需要每次手动 init + remote add。
5.2 SSH 密钥配置:一劳永逸的认证方式
热搜词里“ssh认证失败 git”和“git配置gitee密钥”出现的频次相当高,几乎每个新手都会在认证环节卡住。推荐优先用 SSH 方式替代 HTTPS,配好之后既不用每次输密码,认证也更稳定。
生成 SSH 密钥:
ssh-keygen -t rsa -b 4096 -C "你的邮箱"一路回车,默认生成到~/.ssh/id_rsa和~/.ssh/id_rsa.pub。注意-b 4096是指定密钥长度,4096 位的 RSA 是当前广泛接受的安全强度。
然后把公钥内容复制。Windows 下可以:
cat ~/.ssh/id_rsa.pub然后把输出的那段以ssh-rsa AAAA...开头的长字符串复制下来。打开你的 Gitee 或 GitHub,进入设置 → SSH 公钥,粘贴保存。最后验证:
ssh -T git@gitee.com首次连接会提示确认指纹,输入 yes 回车。如果返回 "Hi xxx! You've successfully authenticated",说明配好了。此时你 clone 远程仓库时,地址要选 SSH 形式(git@gitee.com:用户名/项目名.git),而不是 HTTPS 形式。
如果遇到 "Permission denied (publickey)" 报错,按顺序排查:
- 公钥是否粘贴完整,结尾邮箱是否一致。
- 是否在正确的平台上配置了对应的公钥,Gitee 的公钥不能用于 GitHub。
- 本地是否启动了 ssh-agent,
eval "$(ssh-agent -s)"然后ssh-add ~/.ssh/id_rsa可以修复大部分问题。
曾经有位同事折腾了一下午“SSH 认证失败”,最后发现是复制公钥时少复制了最后一个字符,这坑很常见。
5.3 pull 与 push 的正确姿势
在团队协作里,最常见的报错场面是:
! [rejected] main -> main (fetch first) error: failed to push some refs to '...' hint: Updates were rejected because the remote contains work that you do hint: not have locally.这个报错翻译成大白话就是:远程仓库有别人推送的提交,而你没有。Git 不允许你把本地落后的状态直接推上去,怕把你同事的代码盖掉。
这时候先git pull把远程改动拉下来合并到本地,再git push:
git pull origin main git pushgit pull实际上是git fetch(下载远程改动)+git merge(合并进本地当前分支)的合体。如果拉取时产生了冲突,按上一节处理合并冲突的办法解决。这里有个很实用的建议:推送前先拉取,永远不要盲目 push,这是多人协作的第一条军规。你永远不知道在你上次 push 之后,队友往同一个分支推了多少东西。
5.4 免密与清理本地账号密码
如果你之前用的是 HTTPS 方式并且输过密码,Windows 的 Git 会默认把凭据存在“Windows 凭据管理器”里。热搜词里“git清除账号密码”就是指清理这个。
在命令行里重置缓存:
git config --system --unset credential.helper git config --global --unset credential.helper或者在控制面板 → 凭据管理器 → Windows 凭据里手动删掉git:https://gitee.com之类的条目。删掉之后下次 push 会重新要求输入账号密码。如果想彻底免输,建议直接换 SSH 方式,那才是真正的免密。
6. 常见报错与排查技巧实录(避坑速查)
把搜索热度最高的几个报错集中列一下,直接对照解决:
| 报错信息 | 出现原因 | 解决办法 |
|---|---|---|
fatal: not a git repository (or any of the parent directories): .git | 当前目录不是 Git 仓库,或者用git init初始化失败 | cd到仓库根目录,用ls -a确认有没有.git文件夹,没有就重新git init |
Please tell me who you are. | 没配置 user.name 和 user.email | 执行第 1 节里的全局配置 |
git 无法将“git”项识别为 cmdlet、函数、脚本文件或可运行程序的名称 | Git 未安装或不在 PATH | 重新执行 Git 安装程序,选中添加到 PATH;装完重开终端 |
Permission denied (publickey)/ssh: connect to host gitee.com port 22: Connection timed out | SSH 公钥未配置或本地私钥未加载 | 验证公钥是否粘贴完整;ssh-add ~/.ssh/id_rsa加载密钥;确认访问的是对应平台 |
Updates were rejected because the remote contains work that you do not have locally | 远程有别人推送的提交,本地落后 | git pull拉取合并,解决冲突后再 push |
CONFLICT (content): Merge conflict in xxx.java | 两人改了同一文件同一位置 | 打开冲突文件,删除<<<<<<<、=======、>>>>>>>标记,保留有用代码,git add后提交 |
除了整理报错,我再分享几个实战里很容易踩的小坑:
坑一:git add 了不该提交的大文件。比如不小心把一个 500MB 的数据包git add了,哪怕后面删掉再提交,这个文件体积依然会永久留在 Git 历史里,仓库会越来越臃肿。解决办法是用git rm --cached 文件名取消追踪,但历史记录里的残留反而更难清理。预防胜于治疗,重要项目的.gitignore务必严格。
坑二:commit message 里写了包含#号的内容。在 Git 的默认配置下,#开头的行会被当作注释忽略。比如你提交“修复 #123 问题”,如果这对#123在提交说明里独占一行,这一行会被丢掉,导致你在远程仓库的项目看板里无法通过提交关联 issue。可以改用 “fix 123”、“issue 123” 这类写法避开。
坑三:切分支前没提交当前工作区的改动。如果你的工作区有改动,直接git checkout切到别的分支,Git 会把改动一并带过去(前提是目标分支没有相同文件的冲突),结果你切过去发现刚才改的东西不在,一脸懵。建议养成习惯:切分支前先git status确认工作区干净,要么提交要么git stash暂存。
坑四:在 Windows 上安装了 Git 但 VS Code 等编辑器认不出。打开 VS Code 的终端,如果还是认不出 git 命令,把 Git 的安装路径(比如C:\Program Files\Git\cmd)加到系统 PATH 里,重启 VS Code 即可。这也是“vscode配置git账号密码”类问题最常见的底层原因。
7. 基于搜索引擎热词的疑难点补充
再挑几个热度较高但上面没展开的词补充说明,这些词背后其实是特定场景下的真实痛点。
7.1 git 和 svn 的区别,为什么都建议切 Git
问这个问题的人多半是刚脱离 SVN 环境。区别的核心在于本地仓库与分支成本。SVN 的仓库集中在服务端,离线基本没法提交,分支操作在服务端做,重且慢,每个分支是不同目录,合并是个噩梦。Git 把完整仓库建在本地,提交、分支、合并都在本地瞬间完成,离线办公也能放心提交,等有网了再 push。分支在 Git 里就是一个引用指针,创建切换几乎零成本,这也是现在主流协作模式“每个功能开一个分支”能成立的根本原因。
7.2 git worktree:一个目录不够用时的高级玩法
热搜里有“git worktree”,简单介绍一下。正常情况下一个本地仓库绑定一个工作目录,但如果你同时维护多个分支,又不想频繁切来切去(切换会导致工作区内容全部替换),可以对同一个仓库创建多个工作目录:
git worktree add ../my-project-hotfix hotfix这个命令会在../my-project-hotfix目录下检出一个hotfix分支的副本,你可以在不打断主干开发的前提下,并行维护多个分支。不过这个功能对新手来说不是必备,先会用checkout -b就够了,等哪天切分支切烦了再来体验 worktree 的香。
7.3 IDEA 等 IDE 里的 Git 操作
热搜里“diea创建新项目拉取git”、“vscode git”这类词说明很多人是先在 IDE 里接触 Git 的。IDE 的图形界面确实降低了门槛,比如 IDEA 里VCS→Get from Version Control可以直接填远程仓库地址完成 clone,提交的按钮也有明确提示。但我依然建议你在命令行里把这些操作跑熟,因为 IDE 的 UI 会把很多操作细节藏起来,报错信息也往往只给个对话框弹窗,信息量远不如终端完整。遇到疑难杂症,最终还是得回到命令行看原始日志来判断问题。
7.4 git bash 是干嘛的
Git Bash 不只是用来跑git命令的。它在 Windows 平台上提供了一个轻量化的 Unix 风格终端,支持ls、cd、cat、mkdir等常见的 Linux 命令。对很多刚学 Git 的 Windows 用户来说,Git Bash 算半个 Linux 入门工具,它比 CMD 更像开发环境,也比 WSL 轻量得多。日常我建议就把 Git Bash 当成默认终端用,比 Windows Terminal 的 PowerShell 更贴近大量教程里的命令语法。
7.5 git clone 时提示仓库不存在或无法访问
新手在第一次git clone时最常见的三个原因:地址复制错了(注意区分 HTTPS 和 SSH 两种格式)、仓库权限不够(私有仓库需要你在团队里)、网络无法访问某些托管平台。前两个自己检查一下就能解决,最后一个场景请选择你所在网络环境能稳定访问的平台,或者干脆用企业内部部署的 GitLab。这类问题在团队内部问一下同事,通常几秒钟就能给出答案。
8. 本地到远程的整体工作流总结
最后把整套“本地基础操作”串成一个标准流程,你可以直接把这一段当作操作手册:
# 1. 新项目本地初始化 cd 项目目录 git init # 2. 关联远程仓库(如果没有远程,跳过此步) git remote add origin 远程仓库地址 # 3. 查看状态,确认改了哪些文件 git status # 4. 添加所有改动到暂存区 git add . # 5. 查看暂存区内容,确认没问题 git status # 6. 提交,写明提交信息 git commit -m "feat: 描述本次改动" # 7. 推送到远程(首次加 -u) git push -u origin main日常迭代无非就是“改代码 → add → commit → push”四步循环,加上偶尔的“pull → merge → 解决冲突 → push”。这套基本功打扎实了,再去看那些讲 Git 工作流(Git Flow、GitHub Flow)的文章,就能理解它们到底在解决什么问题了。
我个人在实际操作里还有一个习惯:每个功能分支提交前,先用git diff快速过一遍改动。这个命令能在不提交的情况下展示你所有改动的具体内容,相当于提交前最后一道语法检查和自审。看多了历史里那些“提交完才发现代码里残留了调试日志”的教训,你就会明白这多花的一分钟到底值在哪。
在 Git 上踩过的坑越多,越会发现绝大部分问题都不是 Git 本身难,而是基础概念没吃透。本地操作是这一切的起点,把 add、commit、branch、merge 这几个动作揉进肌肉记忆,后面不管接触多少高级特性,都不会再手忙脚乱了。